2010-07-01 16 views
7

ich mit einer Milliarde Zeilen einen Tisch haben, und ich möchte die durchschnittliche Zeit und die Standardabweichung der Zeit für mehrere Abfragen der Form bestimmen:Statistiken über Abfragezeit (PostgreSQL)

select * from mytable where col1 = '36e2ae77-43fa-4efa-aece-cd7b8b669043'; 
select * from mytable where col1 = '4b58c002-bea4-42c9-8f31-06a499cabc51'; 
select * from mytable where col1 = 'b97242ae-9f6c-4f36-ad12-baee9afae194'; 

.... 

ich tausend haben zufällige Werte für col1 in einer anderen Tabelle gespeichert.

Gibt es eine Möglichkeit zu speichern, wie lange jede dieser Abfragen (in Millisekunden) in einer separaten Tabelle dauerte, damit ich einige Statistiken über sie ausführen kann? So etwas wie: führe für jeden col1 in meiner zufälligen Tabelle die Abfrage aus, zeichne die Zeit auf und speichere sie in einer anderen Tabelle.

Ein völlig anderer Ansatz wäre in Ordnung, solange ich in PostgreSQL bleiben kann (d. H. Ich möchte kein externes Programm schreiben, um dies zu tun).

Antwort

6

Kennen Sie die EXPLAIN statement?

Dieser Befehl zeigt den Ausführungsplan an, den der PostgreSQL-Planer für die angegebene Anweisung generiert. Der Ausführungsplan zeigt, wie die von der Anweisung referenzierten Tabellen gescannt werden - durch einfachen sequenziellen Scan, Index-Scan usw. - und wenn mehrere Tabellen referenziert werden, welche Join-Algorithmen verwendet werden, um die erforderlichen Zeilen von jedem zusammenzuführen Eingabetabelle.

Der kritischste Teil der Anzeige sind die geschätzten Anweisungsausführungskosten, die der Planer schätzt, wie lange es dauern wird, die Anweisung auszuführen (gemessen in Einheiten der Festplattenseitenabrufe). Tatsächlich werden zwei Zahlen angezeigt: die Startzeit vor der ersten Zeile und die Gesamtzeit für die Rückgabe aller Zeilen. Für die meisten Abfragen ist die Gesamtzeit von Bedeutung, aber in Kontexten wie einer Unterabfrage in EXISTS wählt der Planer die kleinste Startzeit anstelle der kleinsten Gesamtzeit (da der Executor sowieso anhält, nachdem er eine Zeile erhalten hat). Wenn Sie die Anzahl der Zeilen begrenzen, die mit einer LIMIT-Klausel zurückgegeben werden sollen, führt der Planer eine geeignete Interpolation zwischen den Endpunktkosten durch, um zu schätzen, welcher Plan wirklich der günstigste ist.

Die Option ANALYZE bewirkt, dass die Anweisung tatsächlich ausgeführt wird, nicht nur geplant. Die gesamte verstrichene Zeit, die innerhalb jedes Planknotens verbraucht wurde (in Millisekunden) und die Gesamtzahl der tatsächlich zurückgegebenen Zeilen werden der Anzeige hinzugefügt. Dies ist nützlich, um zu sehen, ob die Schätzungen des Planers der Realität entsprechen.

konnte ziemlich leicht ein Skript schreiben, die für jede der Zufallswerte in einer Tabelle, die ein EXPLAIN ANALYZE auf Abfrage der Fall ist, und die Ausgabe in eine Datei speichern/Tabelle/usw.

+0

Gibt es eine Möglichkeit, nur die Zeit auszugeben, so dass ich keine Datei analysieren muss? Das werde ich tun, wenn es sein muss, aber es scheint einfach so zu sein, dass es einen einfacheren Weg geben sollte. –

+0

'psql -c" EXPLAIN ANALYSE wähle * aus mytable wo col1 ... "| grep "Total runtime" ' –

+0

Ich bin wirklich auf der Suche nach einer Möglichkeit, dies vollständig in SQL zu tun, wenn möglich. Es scheint, als ob ich in der Lage sein sollte, die Laufzeit, die sie in der interaktiven Shell von psql zurückgibt, direkt als Wert zu speichern. Ihre Antwort ist ziemlich korrekt und ist, was ich geplant habe, wenn niemand mir eine reine SQL-Antwort geben kann. Danke für Ihre Zeit! –

11

Sie benötigen zu ändern PostgreSQL-Konfigurationsdatei.

Sie diese Eigenschaft aktivieren:

log_min_duration_statement = -1  # -1 is disabled, 0 logs all statements          
             # and their durations, > 0 logs only          
             # statements running at least this number         
             # of milliseconds    

Danach wird die Ausführungszeit protokolliert werden, und Sie werden, genau herauszufinden, in der Lage, wie schlecht (oder gut) Ihre Abfragen durchführen.

Sie können auch einige LOG PARSING-Dienstprogramme verwenden, um eine hervorragende HTML-Ausgabe für weitere Analysen wie pgfouine bereitzustellen.

0

Sie können dies nicht in SQL tun, denn selbst wenn Sie in der Lage wären, jede dieser Anweisungen in einer Schleife aufzurufen, würde jeder Aufruf von now() dasselbe Ergebnis liefern, da Sie sich in einer einzigen Transaktion befinden.

Es ist nur möglich, indem Sie eine eigene volatile now() -Funktion erstellen, die bei jedem Aufruf einen anderen Wert zurückgibt.

2

Direkt, nein, nicht. Aber Sie können eine indirekte und ziemlich genaue Schätzung vornehmen, indem Sie die Zeit direkt vor und nach der Abfrage, die Sie zeitlich bestimmen möchten, überprüfen.

Funktion clock_timestamp() gibt Ihnen die tatsächliche Serverzeit, wenn die Anweisung beginnt. Da SELECT keine Tabellen enthält, können wir erwarten, dass es fast augenblicklich ist. Ich denke, jeder Pg-Treiber bietet Unterstützung für mehrere Abfragen; es ist wichtig, dass diese 3 Abfragen (die echte und die 2 Extras) zusammen gehen, sonst würden Sie auch Datentransportzeiten messen ...

Für PHP habe ich eine Funktion, damit umzugehen. Zusammenfassend heißt es:

<?php 

function pgquery($sql, $conn) 
{ 
    // Prepend and append benchmarking queries 
    $bm = "SELECT extract(epoch FROM clock_timestamp())"; 
    $query = "{$bm}; {$sql}; {$bm};"; 

    // Execute the query, and time it (data transport included) 
    $ini = microtime(true); 

    pg_send_query($conn, $query); 

    while ($resource = pg_get_result($conn)) 
    { 
     $resources[] = $resource; 
    } 

    $end = microtime(true); 

    // "Extract" the benchmarking results 
    $q_ini = pg_fetch_row(array_shift($resources)); 
    $q_end = pg_fetch_row(array_pop($resources)); 

    // Compute times 
    $time = round($end - $ini, 4);    # Total time (inc. transport) 
    $q_time = round($q_end[0] - $q_ini[0], 4); # Query time (Pg server only) 

    return $resources; 
} 

?> 

Ich habe nur die Grundlagen dort gelassen. $ conn enthält eine Verbindung zu einer Pg-Verbindung und $ resources ist ein Array von zurückgegebenen pg-Ressourcen (falls Sie mehrere Abfragen in Ihrem $ sql gesendet haben).

$ time enthält die Gesamtzeit seit der Abfrage für den Pg-Server, bis das Ergebnis eintrifft. $ q-time enthält nur die tatsächliche Abfragezeit (oder eine sehr gute Annäherung).

Fügen Sie Fehlerbehandlung und andere Verarbeitung nach Ihren Wünschen, ich habe viel, aber es ist irrelevant für Ihre Frage.

Verwandte Themen