Обнаружение медленных запросов В БД

Даже, когда база данных работает в сочетании с самым современным аппаратным обеспечением, некоторые запросы могут значительно снижать производительность системы. Чтобы оптимизировать скорость работы БД можно использовать техники для выявления и оптимизации SQL-запросов. В данном разделе приведены рекомендации по выявлению ожиданий и медленных запросов в БД Microsoft SQL Server Management Studio и PostgreSQL.

Выявление ожиданий

Для выявления проблем с производительностью Microsoft SQL Server Management Studio используется методология выявления ожиданий. SQL Server автоматически распределяет потоки в очередь на выполнение. Microsoft SQL Server Management Studio Server сохраняет информацию о потоках, ожидающих в очереди. Администратор БД может запросить эту информацию при помощи утилиты DVTrace и использовать её для выявления проблем производительности.

SQL Server постоянно отслеживают ожидания, которые создают очереди на получение доступа к ресурсам. Ожидания не всегда являются проблемой, их нужно правильно интерпретировать.

Для лучшего понимания и за списком наиболее часто встречаемых ожиданий рекомендуем обратиться к следующим статьям:

  • Ожидания в Microsoft SQL Server Management Studio — habr.com,

  • Ожидания в PostgreSQL — simply.name.

Выявление медленных запросов в Microsoft SQL Server Management Studio

В статье на docs.microsoft.com предложен метод для определения запросов, с наивысшим числом логических операций чтения.

SELECT TOP 20 SUBSTRING(qt.text, (qs.statement_start_offset/2)+1,
        ((CASE qs.statement_end_offset
          WHEN -1 THEN DATALENGTH(qt.text)
         ELSE qs.statement_end_offset
         END - qs.statement_start_offset)/2)+1),
qs.execution_count,
qs.total_logical_reads, qs.last_logical_reads,
qs.min_logical_reads, qs.max_logical_reads,
qs.total_elapsed_time, qs.last_elapsed_time,
qs.min_elapsed_time, qs.max_elapsed_time,
qs.last_execution_time,
qp.query_plan
FROM sys.dm_exec_query_stats qs
CROSS APPLY sys.dm_exec_sql_text(qs.sql_handle) qt
CROSS APPLY sys.dm_exec_query_plan(qs.plan_handle) qp
WHERE qt.encrypted=0
ORDER BY qs.total_logical_reads DESC

Данный запрос предоставит синтаксис и статистику 20 самых требовательных запросах из кэшированного плана выполнения. Использовать запрос может быть удобно, когда требуется быстро определить запросы, которые загружают сервер БД больше всего. Недостаток использования этого запроса в том, что он полагается на кэш запросов. Это значит, что любой запрос, который не был кэширован, в выдачу не попадёт.

После выявления медленных запросов можно заняться оптимизацией их работы. В упомянутой выше статье автор предлагает использовать индексы. Индексы — один из основных способов повышения производительности БД. Чтобы больше узнать об индексах, ознакомьтесь с оригинальной англоязычной статьёй на docs.microsoft.com. Чтобы узнать больше о том, как индексы помогают повысить производительность БД, можно также прочитать вот эту статью на habr.com.

Выявление медленных запросов в PostgreSQL

Включение журнала медленных запросов

Самый простой способ выявить медленные запросы в PostgreSQL — посмотреть журнал медленных запросов. По умолчанию журнал медленных запросов не ведётся, но его можно включить. Есть два способа включения: глобально — путём редактирования postgresql.conf и локально — для определённого пользователя или БД.

Чтобы включить журнал медленных запросов глобально, в конфигурационном файле postgresql.conf измените следующую строчку:
log_min_duration_statement = 5000

При такой конфигурации в журнал будут записаны все запросы, на выполнение которых требуется больше 5 секунд. После изменения конфигурационного файла необходимо будет перезапустить сервер БД:

postgres=# SELECT pg_reload_conf();
 pg_reload_conf
----------------
 t
(1 row)

Если необходимо сделать изменения только для одной БД или пользователя, используйте следующий запрос:

postgres=# ALTER DATABASE test SET log_min_duration_statement = 5000;
ALTER DATABASE

Теперь каждый запрос, требующий на выполнение больше 5 секунд будет записан в журнал. Чтобы проанализировать медленный запрос можно запустить команду, которая выполнит запрос и предоставит план его выполнения:

explain analyze

Преимущество такого метода в его скорости — можно моментально определить наиболее медленные запросы. Однако, когда производительность БД ухудшается не несколькими медленными запросами, а большим количеством быстрых, такой подход окажется бесполезным.

Использование pg_stat_statements

Применение pg_stat_statements позволяет объединить одинаковые запросы с разными параметрами в группу, собрать и представить общую статистику выполнения для группы запросов.

Чтобы активировать pg_stat_statements, добавьте в конфигурационный файл postgresql.conf следующую строку и перезапустите сервер БД:
shared_preload_libraries = 'pg_stat_statements'

Выполните запрос:

CREATE EXTENSION pg_stat_statements

На экран будет выведена примерно следующая таблица:

test=# CREATE EXTENSION pg_stat_statements;
CREATE EXTENSION
test=# \d pg_stat_statements
View "public.pg_stat_statements"
       Column        |       Type       | Collation | Nullable | Default
---------------------+------------------+-----------+----------+---------
userid               | oid              |           |          |
dbid                 | oid              |           |          |
queryid              | bigint           |           |          |
query                | text             |           |          |
calls                | bigint           |           |          |
total_time           | double precision |           |          |
min_time             | double precision |           |          |
max_time             | double precision |           |          |
mean_time            | double precision |           |          |
stddev_time          | double precision |           |          |
rows                 | bigint           |           |          |
shared_blks_hit      | bigint           |           |          |
shared_blks_read     | bigint           |           |          |
shared_blks_dirtied  | bigint           |           |          |
shared_blks_written  | bigint           |           |          |
local_blks_hit       | bigint           |           |          |
local_blks_read      | bigint           |           |          |
local_blks_dirtied   | bigint           |           |          |
local_blks_written   | bigint           |           |          |
temp_blks_read       | bigint           |           |          |
temp_blks_written    | bigint           |           |          |
blk_read_time        | double precision |           |          |
blk_write_time       | double precision |           |          |

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

Данный метод позволяет выявить большое количество быстрых запросов, которые могут замедлять работу сервера БД. Недостаток метода в том, что он не даёт возможности быстро определить обычно быстрые запросы, которые иногда выполняются медленно.

Подробнее ознакомиться с методами выявления медленных запросов в PostgreSQL можно в статье Hans-Jürgen Schönig (анг.), с переводом статьи можно ознакомится на habr.com. Подробнее о выявлении медленных запросов при помощи pg_stat_statements в другой статье того же автора.