PostgreSQL-Unterschied zwischen VACUUM FULL und CLUSTER


13

Ich habe eine Tabelle mit 200 GB Größe von Daten und 180 GB Größe von den 6 Indizes darauf besetzt. Es ist zu 30% aufgebläht, daher möchte ich unerwünschten Speicherplatz zurückfordern, der damit belegt ist. Es ist auf job_id_idx-Index gruppiert .

Muss ich also clusterBefehl oder vacuum fullBefehl verwenden , um den Speicherplatz freizugeben ?

  1. Was ist der Unterschied zwischen diesen beiden Befehlen?

  2. Entspricht die vacuum fullReihenfolge einer Spalte dem clusterBefehl?

  3. Wird der Index in beiden Befehlen neu erstellt?

  4. In meinem Fall, welcher wird schneller sein?

Die Version der PostgreSQL-Datenbank ist 9.1


1
Ja, die Indizes werden neu erstellt. Was schneller ist, hängt von ein paar Dingen ab, stelle ich mir vor. Eines ist jedoch sicher: Es gibt nichts Besseres als "Vakuum nach Spalten".
Dezso

1
Lassen Sie mich auch erwähnen, dass VACUUM nicht innerhalb einer Transaktion ausgeführt werden kann, was CLUSTER in vielen Fällen zu einer besseren Alternative (und manchmal zur einzigen Alternative) macht, die ähnliche Ergebnisse liefert.
15.

Antworten:


8

Um zu überprüfen, was CLUSTERfunktioniert, habe ich eine Tabelle aus einem früheren Experiment genommen, die im Grunde die ersten 10 Millionen positiven ganzen Zahlen enthielt. Ich habe bereits einige Zeilen gelöscht, und es gibt auch eine andere Spalte, die sich jedoch nur auf die tatsächliche Tabellengröße auswirkt. Das ist also nicht so interessant.

Nachdem ich VACUUM FULLauf dem Tisch gelaufen war fka, nahm ich seine Größe an:

\dt+ fka
                    List of relations
 Schema | Name | Type  |  Owner   |  Size  | Description 
--------+------+-------+----------+--------+-------------
 public | fka  | table | test     | 338 MB | 

Dann sehen wir uns die physikalische Reihenfolge der Daten vom Anfang der Tabelle an:

SELECT *, ctid FROM fka ORDER BY ctid LIMIT 5;

 id  | col1 |  ctid   
-----+------+---------
   2 | 2    | (0,1)
   3 | 3    | (0,2)
   4 | 4    | (0,3)
   5 | 5    | (0,4)
   6 | 6    | (0,5)

Nun löschen wir einige Zeilen:

DELETE FROM fka WHERE id % 10 = 5;
--DELETE 1000000

Danach hat sich die gemeldete Tabellengröße nicht geändert. Also mal sehen, was CLUSTERmacht:

CLUSTER fka USING fka_pkey;

SELECT *, ctid FROM fka ORDER BY ctid LIMIT 5;

 id  | col1 |  ctid   
-----+------+---------
   2 | 2    | (0,1)
   3 | 3    | (0,2)
   4 | 4    | (0,3)
   6 | 6    | (0,4)
   7 | 7    | (0,5)

Nach der Operation änderte sich die Tabellengröße von 338 auf 296 MB. In der ctidSpalte, die die physische Position des Tupels auf der Seite beschreibt, sehen Sie auch, dass es keine Lücke gibt, in der die Zeilenübereinstimmung stattgefunden hat id = 5.

Da die Tupel neu angeordnet wurden, sollten Indizes neu erstellt werden, damit sie auf die richtigen Stellen verweisen.

Der Unterschied VACUUM FULLscheint also zu sein, dass die Zeilen nicht sortiert werden. Soweit ich weiß, gibt es einige Unterschiede in dem Mechanismus, den die beiden Befehle verwenden, aber aus praktischer Sicht scheint dies der Hauptunterschied (nur?) Zu sein.


Ich war mir nicht sicher, was die ctidKolumne ist. Es stellt sich heraus, dass es sich um eine Systemspalte handelt, die den physischen Speicherort der Zeile in ihrer Tabelle beschreibt. postgresql.org/docs/current/ddl-system-columns.html
Gajus

8

VACUUM FULLSchreibt den gesamten Inhalt der Tabelle in eine neue Festplattendatei ohne zusätzlichen Speicherplatz, sodass nicht verwendeter Speicherplatz an das Betriebssystem zurückgegeben werden kann. Diese Methode erfordert außerdem zusätzlichen Speicherplatz, da eine neue Kopie der Tabelle geschrieben und die alte Kopie erst freigegeben wird, wenn der Vorgang abgeschlossen ist. Normalerweise sollte dies nur verwendet werden, wenn eine erhebliche Menge an Speicherplatz innerhalb der Tabelle zurückgefordert werden muss.

http://www.postgresql.org/docs/9.1/static/sql-vacuum.html

CLUSTERweist PostgreSQL an, die durch table_name angegebene Tabelle auf der Grundlage des durch index_name angegebenen Index zu gruppieren. Der Index muss bereits für tabellenname definiert worden sein. Wenn eine Tabelle gruppiert wird, wird sie basierend auf den Indexinformationen physisch neu geordnet und eine ACCESS EXCLUSIVE-Sperre wird für sie aktiviert.

http://www.postgresql.org/docs/9.1/static/sql-cluster.html

auch interessant: ist ein reindex erforderlich nach cluster

Möglicherweise benötigen Sie jedoch nur eine einfache REINDEXMethode, mit der ein Index anhand der in der Indextabelle gespeicherten Daten neu erstellt wird und die alte Kopie des Index ersetzt wird.

http://www.postgresql.org/docs/9.1/static/sql-reindex.html


1
Woah! Schöner Tipp auch zum REINDEX! Ich habe ein paar Tabellen sowohl von VACUUM als auch von CLUSTER verkleinert (um Zeiten und Auswirkungen zu vergleichen, um es live zu machen) und jetzt sind meine größten Objekte tatsächlich Indizes.
Mike
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.