Статистика по времени запроса (PostgreSQL) - PullRequest
7 голосов
/ 01 июля 2010

У меня есть таблица с миллиардом строк, и я хотел бы определить среднее время и стандартное отклонение времени для нескольких запросов в форме:

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 (т.е.Я не хочу писать внешнюю программу для этого).

Ответы [ 4 ]

12 голосов
/ 01 июля 2010

Вам необходимо изменить файл конфигурации 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 .

6 голосов
/ 01 июля 2010

Вам известно о EXPLAIN утверждении ?

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

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

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

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

2 голосов
/ 24 апреля 2013

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

$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).

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

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

0 голосов
/ 11 февраля 2011

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...