PostgreSQL
 sql >> Datenbank >  >> RDS >> PostgreSQL

Optimieren Sie den Abfragebereich für Postgres-Zeitstempel

CLUSTER

Wenn Sie beabsichtigen, CLUSTER zu verwenden , ist die angezeigte Syntax ungültig.

create CLUSTER ticket USING ticket_1_idx;

Einmal ausführen:

CLUSTER ticket USING ticket_1_idx;

Das kann helfen viel mit größeren Ergebnismengen. Nicht so sehr für eine einzelne zurückgegebene Zeile.
Postgres merkt sich, welcher Index für nachfolgende Aufrufe verwendet werden soll. Wenn Ihre Tabelle nicht schreibgeschützt ist, verschlechtert sich der Effekt mit der Zeit und Sie müssen sie in bestimmten Abständen erneut ausführen:

CLUSTER ticket;

Möglicherweise nur auf flüchtigen Partitionen. Siehe unten.

Allerdings , wenn Sie viele Updates haben, CLUSTER (oder VACUUM FULL ) kann tatsächlich schlecht für die Leistung sein. Die richtige Menge an Aufblähung erlaubt UPDATE neue Zeilenversionen auf derselben Datenseite zu platzieren und vermeidet die Notwendigkeit, die zugrunde liegende Datei im Betriebssystem zu oft physisch zu erweitern. Sie können einen sorgfältig abgestimmten FILLFACTOR verwenden um das Beste aus beiden Welten zu bekommen:

  • Füllfaktor für einen sequentiellen Index, der PK ist

pg_repack

CLUSTER nimmt eine exklusive Sperre für die Tabelle, was in einer Umgebung mit mehreren Benutzern ein Problem sein kann. Zitat aus dem Handbuch:

Wenn eine Tabelle geclustert wird, ein ACCESS EXCLUSIVE es wird eine Sperre erworben. Dies verhindert alle anderen Datenbankoperationen (sowohl Lesen als auch Schreiben ) von der Bearbeitung der Tabelle bis zum CLUSTER ist fertig.

Fette Hervorhebung von mir. Betrachten Sie die Alternative pg_repack :

Im Gegensatz zu CLUSTER und VACUUM FULL es funktioniert online, ohne während der Verarbeitung eine exklusive Sperre für die verarbeiteten Tabellen zu halten. pg_repack lässt sich effizient booten, mit einer Leistung, die mit der Verwendung von CLUSTER vergleichbar ist direkt.

und:

pg_repack muss am Ende der Reorganisation eine exklusive Sperre setzen.

Version 1.3.1 funktioniert mit:

PostgreSQL 8.3, 8.4, 9.0, 9.1, 9.2, 9.3, 9.4

Version 1.4.2 funktioniert mit:

PostgreSQL 9.1, 9.2, 9.3, 9.4, 9.5, 9.6, 10

Abfrage

Die Abfrage ist einfach genug, um per se keine Performance-Probleme zu verursachen.

Aber ein Wort zur Korrektheit :Der BETWEEN includes konstruieren Grenzen. Ihre Abfrage wählt den gesamten 19. Dezember plus aus Aufzeichnungen vom 20. Dezember, 00:00 Uhr. Das ist extrem unwahrscheinlich Erfordernis. Die Chancen stehen gut, dass Sie wirklich wollen:

SELECT *
FROM   ticket 
WHERE  created >= '2012-12-19 0:0'
AND    created <  '2012-12-20 0:0';

Leistung

Zuerst fragen Sie:

Warum wird sequentielles Scannen ausgewählt?

Ihr EXPLAIN Ausgabe zeigt deutlich einen Index Scan , kein sequentieller Tabellenscan. Da muss ein Missverständnis vorliegen.

Wenn Sie unter Druck gesetzt werden, bessere Leistungen zu erbringen, können Sie möglicherweise Dinge verbessern. Aber die nötigen Hintergrundinformationen kommen nicht in Frage. Mögliche Optionen sind:

  • Sie könnten statt * nur erforderliche Spalten abfragen um die Übertragungskosten (und möglicherweise andere Leistungsvorteile) zu reduzieren.

  • Sie könnten sich Partitionierung ansehen und legen Sie praktische Zeitscheiben in separaten Tabellen ab. Fügen Sie nach Bedarf Indizes zu Partitionen hinzu.

  • Wenn die Partitionierung keine Option ist, wäre eine andere verwandte, aber weniger aufdringliche Technik, einen oder mehrere partielle Indizes hinzuzufügen .
    Zum Beispiel, wenn Sie hauptsächlich den aktuellen Monat abfragen , könnten Sie den folgenden Teilindex erstellen:

    CREATE INDEX ticket_created_idx ON ticket(created)
    WHERE created >= '2012-12-01 00:00:00'::timestamp;
    

    CREATE ein neuer Index direkt vor Beginn eines neuen Monats. Sie können die Aufgabe einfach mit einem Cron-Job automatisieren. Optional DROP Teilindizes für alte Monate später.

  • Behalten Sie zusätzlich den Gesamtindex für CLUSTER bei (die nicht mit Teilindizes arbeiten kann). Wenn sich alte Datensätze nie ändern, würde die Tabellenpartitionierung bei dieser Aufgabe sehr hilfreich sein, da Sie nur neuere Partitionen neu gruppieren müssen. Andererseits, wenn sich Datensätze überhaupt nie ändern, brauchen Sie wahrscheinlich CLUSTER nicht .

Wenn Sie die letzten beiden Schritte kombinieren, sollte die Leistung fantastisch sein.

Leistungsgrundlagen

Möglicherweise fehlt Ihnen eine der Grundlagen. Es gelten alle üblichen Leistungshinweise:

  • https://wiki.postgresql.org/wiki/Slow_Query_Questions
  • https://wiki.postgresql.org/wiki/Performance_Optimization