2010-07-01 10 views
7

Tengo una tabla con mil millones de filas y me gustaría para determinar el tiempo promedio y la desviación estándar del tiempo para varias consultas de la forma:estadísticas sobre el tiempo de consulta (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'; 

.... 

tengo mil valores aleatorios para col1 almacenados en otra tabla.

¿Hay alguna manera de almacenar cuánto tiempo tomó cada una de estas consultas (en milisegundos) en una tabla separada, para que pueda ejecutar algunas estadísticas sobre ellas? Algo así como: para cada col1 en mi tabla aleatoria, ejecute la consulta, registre la hora y luego guárdela en otra tabla.

Un enfoque completamente diferente estaría bien, siempre que pueda permanecer dentro de PostgreSQL (es decir, no quiero escribir un programa externo para hacerlo).

Respuesta

6

¿Conoces el EXPLAIN statement?

Este comando muestra el plan de ejecución que el planificador de PostgreSQL genera para la instrucción suministrada. El plan de ejecución muestra cómo se analizarán las tablas a las que se hace referencia en la declaración (escaneo secuencial simple, escaneo de índice, etc.) y si se hace referencia a varias tablas, qué algoritmos de combinación se usarán para reunir las filas requeridas de cada una tabla de entrada.

La parte más crítica de la pantalla es el costo estimado de ejecución de la instrucción, que es la conjetura del planificador de cuánto tiempo llevará ejecutar la instrucción (medida en unidades de recuperaciones de página del disco). En realidad, se muestran dos números: el tiempo de inicio antes de que se pueda devolver la primera fila, y el tiempo total para devolver todas las filas. Para la mayoría de las consultas, el tiempo total es lo que importa, pero en contextos como una subconsulta en EXISTS, el planificador elegirá el menor tiempo de inicio en lugar del menor tiempo total (ya que el ejecutor se detendrá después de obtener una fila, de todos modos). Además, si limita el número de filas a devolver con una cláusula LIMIT, el planificador realiza una interpolación adecuada entre los costos del punto final para estimar qué plan es realmente el más barato.

La opción ANALYZE hace que la declaración sea realmente ejecutada, no solo planificada. El tiempo transcurrido total gastado dentro de cada nodo del plan (en milisegundos) y el número total de filas que realmente devolvió se agregan a la pantalla. Esto es útil para ver si las estimaciones del planificador son cercanas a la realidad.

se pudo escribir con bastante facilidad un script que hace un EXPLAIN ANALYZE en su consulta para cada uno de los valores aleatorios en una mesa, y guardar el resultado en un archivo/tabla/etc

+0

¿Hay alguna manera de simplemente generar el tiempo, de modo que no tenga que analizar un archivo? Esto es lo que haré si es necesario, pero parece que debería haber una manera más directa. –

+0

'psql -c" EXPLAIN ANALYZE select * from mytable where col1 ... "| grep "Total runtime" ' –

+0

Realmente estoy buscando una forma de hacer esto completamente en SQL, si es posible. Parece que debería ser capaz de almacenar el tiempo de ejecución que está volviendo en el shell interactivo psql directamente como un valor. Su respuesta es bastante correcta y es lo que he estado pensando hacer si nadie puede darme una respuesta de SQL puro. ¡Gracias por su tiempo! –

11

Usted necesita cambiar su Archivo de configuración de PostgreSQL

sí permiten esta propiedad:

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    

Después de eso, el tiempo de ejecución será registrada y usted será capaz de averiguar exactamente lo mala (o buena) están llevando a cabo sus consultas.

También puede utilizar algunas utilidades de LOG PARSING para proporcionar una impresionante salida de HTML para análisis posteriores como pgfouine.

0

NO PUEDE hacer esto en SQL, porque incluso si pudiera llamar a cada una de estas instrucciones en un bucle, cada llamada a now() devolvería el mismo resultado, porque está en una sola transacción.

Es posible simplemente creando una función volátil now() propia, devolviendo otro valor en cada invocación.

2

Directamente, no, no lo hay. Pero puede hacer una estimación indirecta y bastante cercana al verificar el tiempo justo antes y después de la consulta que le interesa.

$sql = "Your Query"; 
$bm = "SELECT extract(epoch FROM clock_timestamp())"; 
$query = "{$bm}; {$sql}; {$bm};"; 

La función clock_timestamp() le proporciona el tiempo real del servidor cuando se inicia la instrucción. Como ese SELECT no incluye tablas, podemos esperar que sea casi instantáneo. Supongo que cualquier controlador Pg ofrece soporte para múltiples consultas; es importante que estas 3 consultas (la real y las 2 adicionales) vayan juntas, de lo contrario estarías midiendo los tiempos de transporte de datos ...

Para PHP Tengo una función para manejar esto. En resumen, es como:

<?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; 
} 

?> 

Dejé lo básico allí. $ conn tiene un enlace a una conexión Pg, y $ resources es una matriz de recursos pg devueltos (en caso de que haya enviado varias consultas en su $ sql).

$ tiempo tiene el tiempo total desde que salió la consulta para el servidor Pg hasta que llega el resultado. $ q-time solo contiene el tiempo real de consulta que desea (o una muy buena aproximación).

Agregue el manejo de errores y otros procesos a su gusto, tengo muchos pero es irrelevante para su pregunta.

Cuestiones relacionadas