В YugabyteDB, распределенной SQL базе данных, использующей PostgreSQL, расширение pg_stat_statements установлено по умолчанию. Однако утверждения собираются локально в каждом узле, что означает, что вам нужно запросить pg_stat_statements
или вызвать pg_stat_statements_reset()
на каждом узле. YugabyteDB является “облачной”, вы можете добавлять и удалять узлы. При использовании YugabyteDB Managed или YugabyteDB Anywhere это делается автоматически. Если вы используете YugabyteDB бесплатно, вы должны автоматизировать это.
Здесь я показываю простой способ сделать это.
Сначала создадим таблицу, в которой будут храниться выписки, собранные со всех узлов, с указанием host
, с которого они получены, и ts
– метки времени, когда они были собраны:
drop table if exists ybwr_statements ;
create table ybwr_statements as
select now() as ts,'' as host, *
from pg_stat_statements where null is not null;
Использование Create Table As Select делает его независимым от структуры таблицы, которая может меняться в зависимости от версии.
Теперь, в качестве примера, код plpgsql для сбора данных со всех узлов.
- Я запрашиваю список серверов из
yb_servers()
. - Я использую COPY TO PROGRAM для выполнения
ysqlsh
, эквивалентаpsql
, который присутствует на каждом узле. - Я нахожу его из файла
postmaster.opts
. Вы также можетенайти
его или получить из рабочего каталогаyb-tserver
. - Я запускаю
insert into ybwr_statements select '%s','%s',* from pg_stat_statements
, который я передаю как STDIN вysqlsh
через COPY TO, поскольку мне все равно нужен входной запрос. - Я также сбрасываю
pg_stat_statements_reset()
, если сбор проходит успешно (вызываяysqlsh
с-v ON_ERROR_STOP=1
). - для отладки я добавляю
> /tmp/log.txt 2>&1
в конец командной строки. Вы можете предпочесть использовать COPY FROM PROGRAM, передавая запросы с помощью-c
, и хранить вывод в таблице.
Вот как это делается:
do $DO$
declare i record;
begin
for i in (select now() as ts, host from yb_servers()) loop
execute format(
$COPY$
copy (select $SQL$ insert into ybwr_statements select '%s','%s',* from pg_stat_statements; select pg_stat_statements_reset(); $SQL$ ) to program
$BASH$ $(awk '{sub("/postgres/bin/postgres .*","");print}' ./postmaster.opts)/bin/ysqlsh -h $(hostname) -v ON_ERROR_STOP=1 $BASH$
$COPY$
,i.ts,i.host);
end loop;
end;
$DO$
;
Затем вы можете запросить ybwr_statements
:
select ts, host, calls, total_time, query
from ybwr_statements
order by total_time;
Вот пример на незанятой базе данных, где я захватил только свои запросы на захват:
Это пример для демонстрации техники. Вы можете запланировать его, например, каждый час, и у вас будут ежечасные снимки запросов в таблице ybwr_statements
. Вы можете не вызывать pg_stat_statements_reset()
и будете различать снимки при выполнении запросов.