Ist REINDEX gefährlich?

17

Ich habe versucht, COUNT(*)eine Tabelle mit 150.000 Zeilen, die einen Primärschlüssel hat. Es dauert ungefähr 5 Minuten, also habe ich herausgefunden, dass dies ein Indizierungsproblem ist.

Zitieren des PostgreSQL-Handbuchs :

REINDEX ähnelt dem Löschen und Neuerstellen des Index, indem der Indexinhalt von Grund auf neu erstellt wird. Die Überlegungen zum Sperren sind jedoch recht unterschiedlich. REINDEX sperrt Schreibvorgänge, jedoch keine Lesevorgänge für die übergeordnete Tabelle des Index. Es wird auch eine exklusive Sperre für den bestimmten Index benötigt, der verarbeitet wird. Dadurch werden Lesevorgänge blockiert, die versuchen, diesen Index zu verwenden (...). Da der Index nicht vorhanden ist, versucht kein Lesevorgang, ihn zu verwenden. Dies bedeutet, dass keine Blockierung erfolgt, Lesevorgänge jedoch möglicherweise zu teuren sequenziellen Scans gezwungen werden.

Kannst du aus eigener Erfahrung sagen:

  • ist REINDEXINGgefährlich? Kann dies die Datenkonsistenz beeinträchtigen?
  • Kann es viel Zeit dauern?
  • Ist es eine wahrscheinliche Lösung für mein Szenario?

Aktualisieren:

Die für uns funktionierende Lösung bestand darin, denselben Index mit einem anderen Namen neu zu erstellen und dann den alten Index zu löschen.

Die Indexerstellung ist sehr schnell und wir haben die Indexgröße von 650 MB auf 8 MB reduziert. Die Verwendung von a COUNT(*)mit betweendauert nur 3 Sekunden.

Adam Matan
quelle

Antworten:

15

Die Neuindizierung ist nicht gefährlich und kann die Datenkonsistenz nicht beeinträchtigen. Wenn Sie jedoch zeitkritische Schreibvorgänge ausführen, können Sie Daten verlieren, wenn die Tabelle gesperrt ist und die DML abgebrochen wird.

Die Neuindizierung sollte nicht viel Zeit in Anspruch nehmen, erfordert jedoch in der Regel das Lesen der gesamten Tabelle, das Sortieren der Indexfelder und das Schreiben eines neuen Index. Angesichts der Zeit dafür wird COUNT(*)es wahrscheinlich fünf Minuten oder länger dauern.

Es ist unwahrscheinlich, dass dies ein Indexierungsproblem ist. COUNT(*)sollte einen Tabellenscan verwenden. In diesem Fall wird kein Index gelesen. Ich würde erwarten, dass Sie ein IO-Problem haben.

Versuchen Sie, den Index mit COUNT(1)oder zu COUNT(pk_field)verwenden.

Wenn Sie auf einer Unix- oder Linux-Plattform ausgeführt werden, möchten Sie möglicherweise die Festplattenaktivität mit überwachen sar. Möglicherweise liegt auch eine fehlerhafte Festplatte vor, wodurch die E / A-Raten drastisch gesenkt werden können.

Tabellen mit großen Objekten können auch die E / A erheblich erhöhen, um die Datensätze für COUNT (*) zu erstellen.

BillThor
quelle
2
Laut wiki.postgresql.org COUNT(*)ist die beste Wahl:If you are using count(*), the database is free to use any column to count, which means it can pick the smallest covering index to scan (note that this is why count(*) is much better than count(some_field), as long as you don't care if null values of some_field are counted). Since indexes often fit entirely in memory, this means count(*) is often very fast.
orange80
1

Ich bin mir nicht sicher, welche Antwort für Sie die beste ist. Dieser Thread scheint jedoch einige gute Vorschläge zu bieten: n http://postgresql.1045698.n5.nabble.com/count-performance-issue-td2067873.html

Eine Anmerkung ist, dass Sie einen TRIGGER implementieren könnten, um die Zeilenanzahl in einer separaten Tabelle zu verwalten (wenn COUNT (*) von Ihren Anwendungen häufig aufgerufen würde).

Einige der Antworten deuten darauf hin, dass dies symptomatisch für eine Datenbank ist, die in letzter Zeit nicht ausreichend gesaugt wurde (was darauf hindeutet, dass das automatische Saugen auf Ihrem Server oder speziell für diese Datenbank deaktiviert ist)?

Ein weiterer Vorschlag sieht so aus:

ANALYZE tablename;
SELECT reltuple FROM pg_class WHERE relname = 'tablename';

Und jemand, der als A. Kretschmer identifiziert wurde, bemerkt:

Nein. Die aktuelle Indeximplementierung enthält keine Informationen zur Zeilensichtbarkeit innerhalb der aktuellen Transaktion. Sie müssen die gesamte Datentabelle durchsuchen, um festzustellen, ob die aktuelle Zeile in der aktuellen Transaktion sichtbar ist.

... unterstütze ich meinen Kommentar zu Berechtigungen auf Zeilenebene, die ein Leistungsproblem darstellen.

Meine Suche ergab auch WikiVS: MySQL vs. PostgreSQL: COUNT (*) .

Die anderen Ergebnisse, die ich mithilfe von Google gefunden habe, können Sie nachlesen : postgresql count (*) performance

Jim Dennis
quelle