Aby zwrócić miejsce w systemie operacyjnym, użyj VACUUM FULL
. Będąc przy tym, myślę, że uciekasz VACUUM FULL ANALYZE
. Cytuję instrukcję :
FULL
Wybiera „pełną” próżnię, która może odzyskać więcej miejsca , ale zajmuje znacznie więcej czasu i blokuje wyłącznie stół. Ta metoda wymaga również dodatkowego miejsca na dysku, ponieważ zapisuje nową kopię tabeli i nie zwalnia starej kopii, dopóki operacja nie zostanie zakończona. Zwykle należy tego używać tylko wtedy, gdy znaczna ilość miejsca wymaga odzyskania z wnętrza stołu.
Odważny nacisk moje.
CLUSTER
osiąga to również jako efekt uboczny.
Zwykły VACUUM
zwykle nie osiąga celu ( „jedna lub więcej stron na końcu stołu całkowicie za darmo” ). Nie zmienia kolejności wierszy i przycina tylko puste strony z fizycznego końca pliku, gdy pojawia się taka możliwość - tak jak w cytacie z instrukcji.
Możesz uzyskać puste strony na końcu pliku fizycznego, gdy masz INSERT
partię wierszy i DELETE
je przed dołączeniem innych krotek. Lub może się to zdarzyć zbiegiem okoliczności, jeśli wystarczająca liczba wierszy zostanie usunięta.
Istnieją również specjalne ustawienia, które mogą uniemożliwić VACUUM FULL
odzyskanie miejsca. Widzieć:
Przygotuj puste strony na końcu tabeli do przetestowania
Kolumna systemowa ctid
reprezentuje fizyczną pozycję wiersza. Musisz zrozumieć tę kolumnę:
Możemy z tym pracować i przygotować tabelę, usuwając wszystkie wiersze z ostatniej strony:
DELETE FROM tbl t
USING (
SELECT (split_part(ctid::text, ',', 1) || ',0)')::tid AS min_tid
, (split_part(ctid::text, ',', 1) || ',65535)')::tid AS max_tid
FROM tbl
ORDER BY ctid DESC
LIMIT 1
) d
WHERE t.ctid BETWEEN d.min_tid AND d.max_tid;
Ostatnia strona jest pusta. To ignoruje równoczesne zapisy. Albo jesteś jedynym, który pisze do tej tabeli, albo musisz wziąć blokadę zapisu, aby uniknąć zakłóceń.
Zapytanie jest zoptymalizowane, aby szybko identyfikować kwalifikujące się wiersze. Druga liczba a tid
to indeks krotek przechowywany jako niepodpisany int2
i 65535
jest maksimum dla tego typu ( 2^16 - 1
), więc jest to bezpieczna górna granica.
SQL Fiddle (ponowne użycie prostej tabeli z innego przypadku).
Narzędzia do pomiaru wielkości wiersza / tabeli:
Dysk jest pełny
Do wykonania każdej z tych operacji potrzebujesz miejsca na dysku. Istnieje również narzędzie społecznościowe pg_repack
zastępujące VACUUM FULL
/ CLUSTER
. Unika ekskluzywnych zamków, ale potrzebuje również wolnego miejsca do pracy. Instrukcja:
Wymaga wolnego miejsca na dysku dwa razy większej niż docelowe tabele i indeksy.
W ostateczności możesz uruchomić cykl zrzutu / przywracania. To usuwa również wszelkie wzdęcia z tabel i indeksów. Ściśle powiązane pytanie:
Odpowiedź jest dość radykalna. Jeśli Twoja sytuacja na to pozwala (brak kluczy obcych lub innych referencji uniemożliwiających usunięcie wierszy) i brak równoczesnego dostępu do tabeli), możesz po prostu:
Zrzuć tabelę na dysk łączący się ze zdalnego komputera z dużą ilością miejsca na dysku ( -a
dla --data-only
):
Ze zdalnej powłoki zrzuć dane tabeli:
pg_dump -h <host_name> -p <port> -t mytbl -a mydb > db_mytbl.sql
W sesji pg TRUNCATE
tabela:
-- drop all indexes and constraints here for best performance
TRUNCATE mytbl;
Ze zdalnej powłoki przywróć do tej samej tabeli:
psql -h <host_name> -p <port> mydb -f db_mytbl.sql
-- recreate all indexes and constraints here
Jest teraz wolny od martwych rzędów i wzdęć.
Ale może możesz mieć to prostsze?
Czy możesz zrobić wystarczająco dużo miejsca na dysku, usuwając (przenosząc) niepowiązane pliki?
Czy możesz VACUUM FULL
najpierw pomniejszyć tabele, jeden po drugim, a tym samym zwolnić wystarczająco dużo miejsca na dysku?
Czy możesz uruchomić REINDEX TABLE
lub REINDEX INDEX
zwolnić miejsce na dysku z rozdętych indeksów?
Cokolwiek robisz, nie bądź pochopny . W razie wątpliwości najpierw wykonaj kopię zapasową w bezpiecznej lokalizacji.
update table set field_1 = field_1
Ale odkurzenie tej tabeli po tej operacji nie zwróciło wolnego miejsca, jakieś pomysły?