2010-07-01 8 views
7

У меня есть таблица с миллиардом строк, и я хотел бы, чтобы определить среднее время и стандартное отклонение времени для нескольких запросов вида:Статистика запросов времени (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'; 

.... 

У меня есть тысяча случайные значения для col1, хранящиеся в другой таблице.

Есть ли способ хранить, как долго каждый из этих запросов занимал (в миллисекундах) в отдельной таблице, чтобы я мог запускать некоторые статистические данные по ним? Что-то вроде: для каждого col1 в моей случайной таблице выполните запрос, запишите время, а затем сохраните его в другой таблице.

Совершенно другой подход был бы прекрасен, если я могу оставаться в PostgreSQL (т. Е. Я не хочу писать внешнюю программу для этого).

ответ

6

Знаете ли вы, что EXPLAIN statement?

Эта команда отображает план выполнения, который планировщик PostgreSQL генерирует для поставляемого оператора. План выполнения показывает, как таблица (таблицы), на которую ссылается оператор, будет сканироваться - путем простого последовательного сканирования, сканирования индекса и т. Д. - и если ссылаются на несколько таблиц, какие алгоритмы соединения будут использоваться для объединения требуемых строк из каждого входная таблица.

Наиболее важной частью дисплея является расчетная стоимость выполнения инструкции, которая является предположением планировщика о том, сколько времени потребуется для выполнения инструкции (измеренной в единицах выборки на диске). Фактически отображаются два числа: время запуска до первой строки может быть возвращено и общее время для возврата всех строк. Для большинства запросов общее время имеет значение, но в таких контекстах, как подзапрос в EXISTS, планировщик выберет наименьшее время запуска вместо наименьшего общего времени (так как исполнитель остановится после получения одной строки). Кроме того, если вы ограничиваете количество строк, возвращаемых с помощью предложения LIMIT, планировщик делает соответствующую интерполяцию между затратами на конечную точку, чтобы оценить, какой план действительно самый дешевый.

Опция ANALYZE заставляет выполнение фактически выполненного, а не только запланированного. Общее время, затраченное на каждый узел плана (в миллисекундах), и общее количество строк, которые оно фактически возвращает, добавляется на дисплей. Это полезно для того, чтобы увидеть, приближаются ли оценки планировщика к реальности.

Может довольно легко написать скрипт, который делает EXPLAIN ANALYZE по Вашему запросу для каждой из случайных величин в таблице, и сохранить результат в файл/таблицы/и т.д.

+0

Есть ли способ просто вывести время, так что мне не нужно разбирать файл? Это то, что я буду делать, если понадобится, но похоже, что должен быть более простой способ. –

+0

'psql -c" EXPLAIN ANALYZE выберите * from mytable where col1 ... "| grep «Total runtime» ' –

+0

Я действительно ищу способ сделать это полностью в SQL, если это возможно. Похоже, я должен иметь возможность хранить среду выполнения, которую она возвращает в интерактивной оболочке psql непосредственно как значение. Ваш ответ совершенно верный и является тем, что я планировал делать, если никто не может дать мне ответ на чистый SQL. Спасибо за ваше время! –

11

Вы должны изменить свой Файл конфигурации PostgreSQL.

включить эту недвижимость:

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    

После этого, время выполнения будет зарегистрировано, и вы сможете точно выяснить, насколько плохо (или хорошо) выполняют свои запросы.

Вы также можете использовать некоторые утилиты LOG PARSING для обеспечения потрясающего вывода HTML для дальнейшего анализа, такого как pgfouine.

0

Вы НЕ МОЖЕТЕ сделать это в SQL, потому что даже если вы сможете вызвать каждый из этих операторов в цикле, каждый вызов now() будет возвращать тот же результат, потому что вы находитесь в одной транзакции.

Это возможно, создав собственную функцию volatile now(), возвращая другое значение для каждого вызова.

2

Непосредственно, нет, нет. Но вы можете сделать косвенную и довольно близкую оценку, проверив время прямо перед вами и сразу после запроса, который вам интересен.

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

Функция clock_timestamp() дает вам фактическое время сервера, когда начинается инструкция. Поскольку SELECT не содержит таблиц, мы можем ожидать, что это будет почти мгновенно. Я предполагаю, что любой драйвер Pg предлагает поддержку нескольких запросов; важно, чтобы эти 3 запроса (реальный и 2 дополнения) объединились, иначе вы также будете измерять время передачи данных ...

Для PHP У меня есть функция для обработки этого. В итоге это выглядит так:

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

?> 

Я только что оставил основы. $ conn содержит ссылку на соединение Pg, а $ resources - массив возвращаемых ресурсов pg (в случае, если вы отправили несколько запросов в вашем sql-файле).

$ Время имеет общее время, так как запрос остается на сервере Pg до тех пор, пока результат не достигнет результата. $ q-time содержит только фактическое время запроса (или очень хорошее приближение).

Добавить обработку ошибок и другую обработку по своему вкусу, у меня много, но это не имеет отношения к вашему вопросу.

Смежные вопросы