Mam tabelę PostgreSQL. select *
jest bardzo wolny, select id
ale szybki i przyjemny. Myślę, że może być tak, że rozmiar rzędu jest bardzo duży i transport zajmuje trochę czasu lub może to być jakiś inny czynnik.
Potrzebuję wszystkich pól (lub prawie wszystkich), więc wybranie tylko podzbioru nie jest szybką poprawką. Wybieranie żądanych pól jest nadal wolne.
Oto mój schemat tabeli bez nazw:
integer | not null default nextval('core_page_id_seq'::regclass)
character varying(255) | not null
character varying(64) | not null
text | default '{}'::text
character varying(255) |
integer | not null default 0
text | default '{}'::text
text |
timestamp with time zone |
integer |
timestamp with time zone |
integer |
Rozmiar pola tekstowego może być dowolnego rozmiaru. Ale w najgorszym przypadku nie więcej niż kilka kilobajtów.
pytania
- Czy jest w tym coś, co krzyczy „szalenie nieefektywne”?
- Czy istnieje sposób pomiaru wielkości strony w wierszu polecenia Postgres, aby pomóc mi w debugowaniu?
length(*)
czegoś więcej niż tylkolength(field)
? Wiem, że to znaki nie bajty, ale potrzebuję tylko przybliżonej wartości.Odpowiedzi:
Q2:
way to measure page size
PostgreSQL udostępnia szereg funkcji rozmiaru obiektu bazy danych . W tym zapytaniu spakowałem najciekawsze i na dole dodałem kilka funkcji dostępu do statystyk . (Dodatkowy moduł pgstattuple zapewnia jeszcze więcej przydatnych funkcji.)
To pokaże, że różne metody pomiaru „wielkości wiersza” prowadzą do bardzo różnych wyników. Wszystko zależy dokładnie od tego, co chcesz zmierzyć.
To zapytanie wymaga Postgres 9.3 lub nowszego . W przypadku starszych wersji patrz poniżej.
Używanie
VALUES
wyrażenia wLATERAL
podzapytaniu , aby uniknąć przeliterowania obliczeń dla każdego wiersza.Zamień
public.tbl
(dwukrotnie) na opcjonalnie kwalifikowaną nazwę tabeli, aby uzyskać kompaktowy widok zebranych statystyk dotyczących wielkości twoich wierszy. Możesz zawinąć to w funkcję plpgsql do wielokrotnego użytku, podać nazwę tabeli jako parametr i użyćEXECUTE
...Wynik:
W przypadku starszych wersji (Postgres 9.2 lub starszy):
Ten sam wynik.
P1:
anything inefficient?
Możesz zoptymalizować kolejność kolumn, aby zaoszczędzić kilka bajtów na wiersz, obecnie zmarnowanych na wypełnienie wyrównania:
Oszczędza to od 8 do 18 bajtów na wiersz. Nazywam to „kolumną tetris” . Detale:
Weź również pod uwagę:
źródło
, unnest(val) / ct
przez, (LEAST(unnest(val), unnest(val) * ct)) / (ct - 1 + sign(ct))
i nie będzie rzucał. Uzasadnienie jest takie, że kiedyct
będzie0
,val
zostanie zastąpione przez0
ict
zostanie zastąpione przez1
.Przybliżenie wielkości wiersza, w tym zawartości edytowanej w TOAST , jest łatwe do uzyskania poprzez zapytanie o długość reprezentacji TEKSTOWEJ całego wiersza:
Jest to przybliżone przybliżenie liczby bajtów, które zostaną pobrane po stronie klienta podczas wykonywania:
... zakładając, że wywołujący zapytanie żąda wyników w formacie tekstowym, co robi większość programów (format binarny jest możliwy, ale w większości przypadków nie jest to warte kłopotu).
Tę samą technikę można zastosować do zlokalizowania
N
wierszy „największych w tekście”tablename
:źródło
Może się zdarzyć kilka rzeczy. Ogólnie wątpię, aby długość była problemem proksymalnym. Podejrzewam, że zamiast tego masz problem związany z długością.
Mówisz, że pola tekstowe mogą mieć nawet kilka kilogramów. Wiersz nie może przekroczyć 8k w pamięci głównej i jest prawdopodobne, że twoje większe pola tekstowe zostały TOASTED lub przeniesione z pamięci głównej do pamięci rozszerzonej w oddzielnych plikach. To sprawia, że twoja główna pamięć jest szybsza (więc wybór id jest w rzeczywistości szybszy, ponieważ dostęp do mniejszej liczby stron dysku), ale select * staje się wolniejszy, ponieważ jest więcej losowych operacji we / wy.
Jeśli Twoje całkowite rozmiary wierszy nadal są znacznie mniejsze niż 8 KB, możesz spróbować zmienić ustawienia przechowywania. Ostrzegam jednak, że przy wstawianiu zbyt dużego atrybutu do pamięci głównej może się zdarzyć coś złego, więc najlepiej go nie dotykać, jeśli nie musisz, a jeśli tak, ustaw odpowiednie limity za pomocą ograniczeń sprawdzania. Dlatego transport nie jest jedyną rzeczą. Może to być zestawianie wielu, wielu pól, które wymagają losowych odczytów. Duża liczba losowych odczytów może również powodować pominięcia pamięci podręcznej, a wymagana duża ilość pamięci może wymagać zmaterializowania się rzeczy na dysku, a duża liczba szerokich wierszy, jeśli istnieje połączenie (i jest to jedno, jeśli występuje TOAST) może wymagać kosztowniejszych łączyć wzory itp.
Pierwszą rzeczą, na którą chciałbym spojrzeć, było wybranie mniejszej liczby wierszy i sprawdzenie, czy to pomoże. Jeśli to zadziała, możesz spróbować dodać więcej pamięci RAM również do serwera, ale zacznę i zobaczę, gdzie wydajność zaczyna spadać z powodu zmian w planie i braku pamięci podręcznej w pierwszej kolejności.
źródło
Korzystanie z wyżej wymienionych funkcji rozmiaru obiektu bazy danych :
źródło