Declaração do problema
Para otimizar as consultas do PostgreSQL, ele realmente requer a capacidade de analisar o histórico de atividades, em particular - expectativas, bloqueios, estatísticas da tabela.
Opções disponíveis
Ferramenta de análise de carga histórica ou "AWR for Postgres" : uma solução muito interessante, mas não há histórico de pg_stat_activity e pg_locks.
Extensão pgsentinel :
"
Todas as informações acumuladas são armazenadas apenas na RAM, e a quantidade consumida de memória é regulada pelo número de últimos registros armazenados.
O campo queryid é adicionado - o mesmo queryid da extensão pg_stat_statements (é necessária uma instalação preliminar). "
Isso certamente ajudaria muito, mas o incômodo é o primeiro parágrafo: "
Todas as informações acumuladas são armazenadas apenas na RAM ", ou seja, temos um impacto na base alvo. Além disso, não há histórico de bloqueio e estatísticas de tabela. I.e. de um modo geral, a solução está incompleta: “
Ainda não existe um pacote pronto para instalação. Propõe-se baixar as fontes e construir a biblioteca você mesmo. Primeiro, você precisa instalar o pacote “devel” no seu servidor e escrever o caminho para pg_config na variável PATH. "
Em geral - muita confusão e, no caso de bancos de dados de produção sérios, talvez não haja maneira de fazer algo com o servidor. Novamente, você precisa criar algo próprio.
Advertência
Devido à novidade do tópico e à incompletude do período de teste, o artigo é principalmente apenas para orientação, e não como um conjunto de resumos e resultados intermediários.
Material mais detalhado será preparado posteriormente, em partes.
Descrever os requisitos da solução
É necessário desenvolver uma ferramenta para armazenar:
Pg_stat_activity ver históricoHistórico de bloqueio de sessão usando a visualização pg_locksO requisito de decisão é minimizar o impacto no banco de dados de destino.
A ideia geral é que o agente de coleta de dados seja iniciado não no banco de dados de destino, mas no banco de dados de monitoramento como um serviço systemd. Sim, é possível perder alguns dados, mas isso não é crítico para os relatórios, mas não há impacto no banco de dados de destino da memória e do espaço em disco. E no caso de usar um pool de conexões, o impacto nos processos do usuário é mínimo.
Etapas de implementação
1. Mesas de serviço
Para armazenar tabelas, um esquema separado é usado para não complicar a análise das tabelas principais usadas.
DROP SCHEMA IF EXISTS activity_hist ; CREATE SCHEMA activity_hist AUTHORIZATION monitor ;
Importante: o esquema não é criado no banco de dados de destino, mas no banco de dados de monitoramento.Pg_stat_activity ver histórico
Use a tabela para armazenar as capturas instantâneas atuais da visualização pg_stat_activity
activity_hist.history_pg_stat_activity: Para acelerar a inserção - sem índices ou restrições.
Para armazenar o histórico diretamente, uma tabela particionada é usada:
activity_hist.archive_pg_stat_activity: DROP TABLE IF EXISTS activity_hist.archive_pg_stat_activity; CREATE TABLE activity_hist.archive_pg_stat_activity ( timepoint timestamp without time zone , datid oid , datname name , pid integer, usesysid oid , usename name , application_name text , client_addr inet , client_hostname text , client_port integer, backend_start timestamp with time zone , xact_start timestamp with time zone , query_start timestamp with time zone , state_change timestamp with time zone , wait_event_type text , wait_event text , state text , backend_xid xid , backend_xmin xid , query text , backend_type text , queryid bigint ) PARTITION BY RANGE (timepoint);
Como nesse caso não há requisitos para a velocidade de inserção, alguns índices foram criados para acelerar os relatórios.
Histórico de Bloqueio de Sessão
Para armazenar os instantâneos de bloqueio de sessão atuais, use a tabela:
activity_hist.history_locking: Além disso, para acelerar a inserção - sem índices ou restrições.
Para armazenar o histórico diretamente, uma tabela particionada é usada:
activity_hist.archive_locking: DROP TABLE IF EXISTS activity_hist.archive_locking; CREATE TABLE activity_hist.archive_locking ( timepoint timestamp without time zone , locktype text , relation oid , mode text , tid xid , vtid text , pid integer , blocking_pids integer[] , granted boolean ) PARTITION BY RANGE (timepoint);
Como nesse caso não há requisitos para a velocidade de inserção, alguns índices foram criados para acelerar os relatórios.
2. Preenchendo o histórico atual
Para capturar diretamente os instantâneos de uma visualização, é usado um script bash que executa a função plpgsql.
A função
plpgsql dblink acessa visualizações no banco de dados de destino e insere linhas nas tabelas de serviço no banco de dados de monitoramento.
get_current_activity.sql CREATE OR REPLACE FUNCTION activity_hist.get_current_activity( current_host text , current_s_name text , current_s_pass text ) RETURNS BOOLEAN AS $$ DECLARE database_rec record; dblink_str text ; BEGIN EXECUTE 'SELECT dblink_connect(''LINK1'',''host='||current_host||' port=5432 dbname=postgres'|| ' user='||current_s_name||' password='||current_s_pass|| ' '')'; -------------------------------------------------------------------- --GET pg_stat_activity stats INSERT INTO activity_hist.history_pg_stat_activity ( SELECT * FROM dblink('LINK1', 'SELECT now() , datid , datname , pid , usesysid , usename , application_name , client_addr , client_hostname , client_port , backend_start , xact_start , query_start , state_change , wait_event_type , wait_event , state , backend_xid , backend_xmin , query , backend_type FROM pg_stat_activity ') AS t ( timepoint timestamp without time zone , datid oid , datname name , pid integer, usesysid oid , usename name , application_name text , client_addr inet , client_hostname text , client_port integer, backend_start timestamp with time zone , xact_start timestamp with time zone , query_start timestamp with time zone , state_change timestamp with time zone , wait_event_type text , wait_event text , state text , backend_xid xid , backend_xmin xid , query text , backend_type text ) ); --------------------------------------- --ACTIVITY_HIST.HISTORY_LOCKING INSERT INTO activity_hist.history_locking ( SELECT * FROM dblink('LINK1', 'SELECT now() , lock.locktype, lock.relation, lock.mode, lock.transactionid as tid, lock.virtualtransaction as vtid, lock.pid, pg_blocking_pids(lock.pid), lock.granted FROM pg_catalog.pg_locks lock LEFT JOIN pg_catalog.pg_database db ON db.oid = lock.database WHERE NOT lock.pid = pg_backend_pid() ') AS t ( timepoint timestamp without time zone , locktype text , relation oid , mode text , tid xid , vtid text , pid integer , blocking_pids integer[] , granted boolean ) ); PERFORM dblink_disconnect('LINK1'); RETURN TRUE ; END $$ LANGUAGE plpgsql;
Para coletar capturas instantâneas da exibição, o serviço systemd é usado e dois scripts:
pg_current_activity.service pg_current_activity.timer Atribua direitos a scripts:
# chmod 755 pg_current_activity.timer
# chmod 755 pg_current_activity.service
Iniciamos o serviço:
# systemctl daemon-reload
# systemctl start pg_current_activity.service
Assim, a história das performances é coletada na forma de cada segundo disparo. Obviamente, se tudo permanecer como está, as tabelas aumentarão muito rapidamente de tamanho e o trabalho mais ou menos produtivo se tornará impossível.
É necessário organizar o arquivamento de dados.
3. história do arquivo
Para arquivamento, são usadas tabelas particionadas *.
Novas seções são criadas a cada hora, enquanto os dados antigos das tabelas de histórico * são excluídos, portanto o tamanho das tabelas de histórico * não muda muito e a velocidade de inserção não diminui com o tempo.
A criação de novas seções é realizada pela função plpgsql activity_hist.archive_current_activity. O algoritmo de operação é muito simples (usando o exemplo da seção da tabela archive_pg_stat_activity).
Crie e preencha uma nova seção EXECUTE format( 'CREATE TABLE ' || partition_name || ' PARTITION OF activity_hist.archive_pg_stat_activity FOR VALUES FROM ( %L ) TO ( %L ) ' , to_char(date_trunc('year', partition_min_range ),'YYYY')||'-'|| to_char(date_trunc('month', partition_min_range ),'MM')||'-'|| to_char(date_trunc('day', partition_min_range ),'DD')||' '|| to_char(date_trunc('hour', partition_min_range ),'HH24')||':00', to_char(date_trunc('year', partition_max_range ),'YYYY')||'-'|| to_char(date_trunc('month', partition_max_range ),'MM')||'-'|| to_char(date_trunc('day', partition_max_range ),'DD')||' '|| to_char(date_trunc('hour', partition_max_range ),'HH24')||':00' ); INSERT INTO activity_hist.archive_pg_stat_activity ( SELECT * FROM activity_hist.history_pg_stat_activity WHERE timepoint BETWEEN partition_min_range AND partition_max_range );
Criar índices EXECUTE format ( 'CREATE INDEX '||index_name|| ' ON '||partition_name||' ( wait_event_type , backend_type , timepoint )' ); EXECUTE format ('CREATE INDEX '||index_name|| ' ON '||partition_name||' ( wait_event_type , backend_type , timepoint , queryid )' );
Excluir dados antigos da tabela history_pg_stat_activity DELETE FROM activity_hist.history_pg_stat_activity WHERE timepoint < partition_max_range;
Obviamente, periodicamente, as seções antigas são excluídas como desnecessárias.
Relatórios básicos
Na verdade, por que tudo isso está sendo feito. Para receber relatórios muito remotamente, lembra o Oracle AWR.
É importante adicionar que, para receber relatórios, é necessário construir um relacionamento entre as visualizações pg_stat_activity e pg_stat_statements. As tabelas são vinculadas adicionando a coluna 'queryid' às tabelas 'history_pg_stat_activity', 'archive_pg_stat_activity'. A maneira de adicionar um valor de coluna está além do escopo deste artigo e é descrita aqui - pg_stat_statements + pg_stat_activity + loq_query = pg_ash? .
TEMPO TOTAL DE CPU PARA CONSULTAS
Pedido: WITH hist AS ( SELECT aa.query ,aa.queryid , count(*) * interval '1 second' AS duration FROM activity_hist.archive_pg_stat_activity aa WHERE timepoint BETWEEN pg_stat_history_begin+(current_hour_diff * interval '1 hour') AND pg_stat_history_end+(current_hour_diff * interval '1 hour') AND backend_type = 'client backend' AND datname != 'postgres' AND ( aa.wait_event_type IS NULL ) ANDaa.state = 'active' GROUP BY aa.wait_event_type , aa.wait_event , aa.query ,aa.queryid UNION SELECT ha.query ,ha.queryid, count(*) * interval '1 second' AS duration FROM activity_hist.history_pg_stat_activity_for_reports ha WHERE timepoint BETWEEN pg_stat_history_begin+(current_hour_diff * interval '1 hour') AND pg_stat_history_end+(current_hour_diff * interval '1 hour') AND backend_type = 'client backend' AND datname != 'postgres' AND ( ha.wait_event_type IS NULL )AND ha.state = 'active' GROUP BY ha.wait_event_type , ha.wait_event , ha.query ,ha.queryid ) SELECT query , queryid , SUM( duration ) as duration FROM hist GROUP BY query , queryid ORDER BY 3 DESC
intervalo de ' WITH hist AS ( SELECT aa.query ,aa.queryid , count(*) * interval '1 second' AS duration FROM activity_hist.archive_pg_stat_activity aa WHERE timepoint BETWEEN pg_stat_history_begin+(current_hour_diff * interval '1 hour') AND pg_stat_history_end+(current_hour_diff * interval '1 hour') AND backend_type = 'client backend' AND datname != 'postgres' AND ( aa.wait_event_type IS NULL ) ANDaa.state = 'active' GROUP BY aa.wait_event_type , aa.wait_event , aa.query ,aa.queryid UNION SELECT ha.query ,ha.queryid, count(*) * interval '1 second' AS duration FROM activity_hist.history_pg_stat_activity_for_reports ha WHERE timepoint BETWEEN pg_stat_history_begin+(current_hour_diff * interval '1 hour') AND pg_stat_history_end+(current_hour_diff * interval '1 hour') AND backend_type = 'client backend' AND datname != 'postgres' AND ( ha.wait_event_type IS NULL )AND ha.state = 'active' GROUP BY ha.wait_event_type , ha.wait_event , ha.query ,ha.queryid ) SELECT query , queryid , SUM( duration ) as duration FROM hist GROUP BY query , queryid ORDER BY 3 DESC
* intervalo de ' WITH hist AS ( SELECT aa.query ,aa.queryid , count(*) * interval '1 second' AS duration FROM activity_hist.archive_pg_stat_activity aa WHERE timepoint BETWEEN pg_stat_history_begin+(current_hour_diff * interval '1 hour') AND pg_stat_history_end+(current_hour_diff * interval '1 hour') AND backend_type = 'client backend' AND datname != 'postgres' AND ( aa.wait_event_type IS NULL ) ANDaa.state = 'active' GROUP BY aa.wait_event_type , aa.wait_event , aa.query ,aa.queryid UNION SELECT ha.query ,ha.queryid, count(*) * interval '1 second' AS duration FROM activity_hist.history_pg_stat_activity_for_reports ha WHERE timepoint BETWEEN pg_stat_history_begin+(current_hour_diff * interval '1 hour') AND pg_stat_history_end+(current_hour_diff * interval '1 hour') AND backend_type = 'client backend' AND datname != 'postgres' AND ( ha.wait_event_type IS NULL )AND ha.state = 'active' GROUP BY ha.wait_event_type , ha.wait_event , ha.query ,ha.queryid ) SELECT query , queryid , SUM( duration ) as duration FROM hist GROUP BY query , queryid ORDER BY 3 DESC
backend' E datname! = 'Postgres' E (aa.wait_event_type IS NULL) ANDaa.state = WITH hist AS ( SELECT aa.query ,aa.queryid , count(*) * interval '1 second' AS duration FROM activity_hist.archive_pg_stat_activity aa WHERE timepoint BETWEEN pg_stat_history_begin+(current_hour_diff * interval '1 hour') AND pg_stat_history_end+(current_hour_diff * interval '1 hour') AND backend_type = 'client backend' AND datname != 'postgres' AND ( aa.wait_event_type IS NULL ) ANDaa.state = 'active' GROUP BY aa.wait_event_type , aa.wait_event , aa.query ,aa.queryid UNION SELECT ha.query ,ha.queryid, count(*) * interval '1 second' AS duration FROM activity_hist.history_pg_stat_activity_for_reports ha WHERE timepoint BETWEEN pg_stat_history_begin+(current_hour_diff * interval '1 hour') AND pg_stat_history_end+(current_hour_diff * interval '1 hour') AND backend_type = 'client backend' AND datname != 'postgres' AND ( ha.wait_event_type IS NULL )AND ha.state = 'active' GROUP BY ha.wait_event_type , ha.wait_event , ha.query ,ha.queryid ) SELECT query , queryid , SUM( duration ) as duration FROM hist GROUP BY query , queryid ORDER BY 3 DESC
Um exemplo:
------------------------------------------------------------------- | TOTAL CPU TIME FOR QUERIES : 07:47:36 +----+----------------------------------------+-------------------- | #| queryid| duration +----+----------------------------------------+-------------------- | 1| 389015618226997618| 04:28:58 | 2| | 01:07:29 | 3| 1237430309438971376| 00:59:38 | 4| 4710212362688288619| 00:50:48 | 5| 28942442626229688| 00:15:50 | 6| 9150846928388977274| 00:04:46 | 7| -6572922443698419129| 00:00:06 | 8| | 00:00:01 +----+----------------------------------------+--------------------
Tempo total de espera para consultas
Pedido: WITH hist AS ( SELECT aa.query ,aa.queryid , count(*) * interval '1 second' AS duration FROM activity_hist.archive_pg_stat_activity aa WHERE timepoint BETWEEN pg_stat_history_begin+(current_hour_diff * interval '1 hour') AND pg_stat_history_end+(current_hour_diff * interval '1 hour') AND backend_type = 'client backend' AND datname != 'postgres' AND ( aa.wait_event_type IS NOT NULL ) GROUP BY aa.wait_event_type , aa.wait_event , aa.query ,aa.queryid UNION SELECT ha.query ,ha.queryid, count(*) * interval '1 second' AS duration FROM activity_hist.history_pg_stat_activity_for_reports ha WHERE timepoint BETWEEN pg_stat_history_begin+(current_hour_diff * interval '1 hour') AND pg_stat_history_end+(current_hour_diff * interval '1 hour') AND backend_type = 'client backend' AND datname != 'postgres' AND ( ha.wait_event_type IS NOT NULL ) GROUP BY ha.wait_event_type , ha.wait_event , ha.query ,ha.queryid ) SELECT query , queryid , SUM( duration ) as duration FROM hist GROUP BY query , queryid ORDER BY 3 DESC
Um exemplo: ------------------------------------------------------------------- | TOTAL WAITINGS TIME FOR QUERIES : 21:55:04 +----+----------------------------------------+-------------------- | #| queryid| duration +----+----------------------------------------+-------------------- | 1| 389015618226997618| 16:19:05 | 2| | 03:47:04 | 3| 8085340880788646241| 00:40:20 | 4| 4710212362688288619| 00:13:35 | 5| 9150846928388977274| 00:12:25 | 6| 28942442626229688| 00:11:32 | 7| 1237430309438971376| 00:09:45 | 8| 2649515222348904837| 00:09:37 | 9| | 00:03:45 | 10| 3167065002719415275| 00:02:20 | 11| 5731212217001535134| 00:02:13 | 12| 8304755792398128062| 00:01:31 | 13| 2649515222348904837| 00:00:59 | 14| 2649515222348904837| 00:00:22 | 15| | 00:00:12 | 16| 3422818749220588372| 00:00:08 | 17| -5730801771815999400| 00:00:03 | 18| -1473395109729441239| 00:00:02 | 19| 2404820632950544954| 00:00:02 | 20| -6572922443698419129| 00:00:02 | 21| 2369289265278398647| 00:00:01 | 22| 180077086776069052| 00:00:01 +----+----------------------------------------+--------------------
ESPERANDO QUESTÕES
Pedidos: WITH hist AS ( SELECT aa.wait_event_type , aa.wait_event FROM activity_hist.archive_pg_stat_activity aa WHERE timepoint BETWEEN pg_stat_history_begin+(current_hour_diff * interval '1 hour') AND pg_stat_history_end+(current_hour_diff * interval '1 hour') AND backend_type = 'client backend' AND datname != 'postgres' AND aa.wait_event IS NOT NULL GROUP BY aa.wait_event_type , aa.wait_event UNION SELECT ha.wait_event_type , ha.wait_event FROM activity_hist.history_pg_stat_activity_for_reports ha WHERE timepoint BETWEEN pg_stat_history_begin+(current_hour_diff * interval '1 hour') AND pg_stat_history_end+(current_hour_diff * interval '1 hour') AND backend_type = 'client backend' AND datname != 'postgres' AND ha.wait_event IS NOT NULL GROUP BY ha.wait_event_type , ha.wait_event ) SELECT wait_event_type , wait_event FROM hist GROUP BY wait_event_type , wait_event ORDER BY 1 ASC,2 ASC
Um exemplo: ------------------------------------------------ | WAITINGS FOR QUERIES +----------------------------------------------- | wait_event_type = Client| | wait_event = ClientRead| | Total time = 00:46:56| ------------------------------------------------ | #| queryid| duration +-----+--------------------+-------------------- | 1| 8085340880788646241| 00:40:20 | 2| | 00:03:45 | 3| 5731212217001535134| 00:01:53 | 4| | 00:00:12 | 5| 9150846928388977274| 00:00:09 | 6| 3422818749220588372| 00:00:08 | 7| 1237430309438971376| 00:00:06 | 8| 28942442626229688| 00:00:05 | 9| 4710212362688288619| 00:00:05 | 10|-5730801771815999400| 00:00:03 | 11| 8304755792398128062| 00:00:02 | 12|-6572922443698419129| 00:00:02 | 13|-1473395109729441239| 00:00:02 | 14| 2404820632950544954| 00:00:02 | 15| 180077086776069052| 00:00:01 | 16| 2369289265278398647| 00:00:01 +----------------------------------------------- | wait_event_type = IO| | wait_event = BufFileRead| | Total time = 00:00:38| ------------------------------------------------ | #| queryid| duration +-----+--------------------+-------------------- | 1| 28942442626229688| 00:00:38 +-----------------------------------------------
HISTÓRICO DE PROCESSOS BLOQUEADOS
Pedido: SELECT MIN(date_trunc('second',timepoint)) AS started , count(*) * interval '1 second' as duration , pid , blocking_pids , relation , mode , locktype FROM activity_hist.archive_locking al WHERE timepoint BETWEEN pg_stat_history_begin+(current_hour_diff * interval '1 hour') AND pg_stat_history_end+(current_hour_diff * interval '1 hour') AND NOT granted AND locktype = 'relation' GROUP BY pid , blocking_pids , relation , mode , locktype UNION SELECT MIN(date_trunc('second',timepoint)) AS started , count(*) * interval '1 second' as duration , pid , blocking_pids , relation , mode , locktype FROM activity_hist.history_locking WHERE timepoint BETWEEN pg_stat_history_begin+(current_hour_diff * interval '1 hour') AND pg_stat_history_end+(current_hour_diff * interval '1 hour') AND NOT granted AND locktype = 'relation' GROUP BY pid , blocking_pids , relation , mode , locktype ORDER BY 1
Um exemplo: -------------------------------------------------- -------------------------------------------------- ---------------------------------
| HISTÓRICO DE PROCESSOS BLOQUEADOS
+ ----- + ---------- + -------------------- + ---------- + -------------------- + -------------------- + -------- ------------ + --------------------
| # | pid | iniciado | duração | blocking_pids | relação | modo | locktype
+ ----- + ---------- + -------------------- + ---------- + -------------------- + -------------------- + -------- ------------ + --------------------
| 1 | 26224 2019-09-02 19: 32: 16 | 00: 01: 45 | {26211} | 16541 AccessShareLock | relação
| 2 26390 2019-09-02 19: 34: 03 | 00: 00: 53 | {26211} | 16541 AccessShareLock | relação
| 3 26391 2019-09-02 19: 34: 03 | 00: 00: 53 | {26211} | 16541 AccessShareLock | relação
| 4 26531 2019-09-02 19: 35: 27 | 00: 00: 12 | {26211} | 16541 AccessShareLock | relação
| 5 27284 2019-09-02 19: 44: 02 | 00: 00: 19 | {27276} | 16541 AccessShareLock | relação
| 6 27283 2019-09-02 19: 44: 02 | 00: 00: 19 | {27276} | 16541 AccessShareLock | relação
| 7 27286 2019-09-02 19: 44: 02 | 00: 00: 19 | {27276} | 16541 AccessShareLock | relação
| 8 27423 2019-09-02 19:45:24 | 00: 00: 12 | {27394} | 16541 AccessShareLock | relação
| 9 27648 2019-09-02 19: 48: 06 | 00: 00: 20 | {27647} | 16541 AccessShareLock | relação
| 10 27650 2019-09-02 19: 48: 06 | 00: 00: 20 | {27647} | 16541 AccessShareLock | relação
| 11 27735 2019-09-02 19: 49: 08 | 00: 00: 06 | {27650} | 16541 AccessExclusiveLock | relação
| 12 28380 2019-09-02 19: 56: 03 | 00: 01: 56 | {28379} | 16541 AccessShareLock | relação
| 13 28379 2019-09-02 19: 56: 03 | 00: 00: 01 | 28377 16541 AccessExclusiveLock | relação
| | | | | 28376 |
HISTÓRICO DE PROCESSOS DE BLOQUEIO
Pedidos: SELECT blocking_pids FROM activity_hist.archive_locking al WHERE timepoint BETWEEN pg_stat_history_begin+(current_hour_diff * interval '1 hour') AND pg_stat_history_end+(current_hour_diff * interval '1 hour') AND NOT granted AND locktype = 'relation' GROUP BY blocking_pids UNION SELECT blocking_pids FROM activity_hist.history_locking WHERE timepoint BETWEEN pg_stat_history_begin+(current_hour_diff * interval '1 hour') AND pg_stat_history_end+(current_hour_diff * interval '1 hour') AND NOT granted AND locktype = 'relation' GROUP BY blocking_pids ORDER BY 1
Um exemplo: -------------------------------------------------- -------------------------------------------------- -------------------------------------------------- -----------------------
HISTÓRICO DE PROCESSOS DE BLOQUEIO
+ ---- + ---------- + ---------- + -------------------- + - --------- + -------------------- + ------------------- - + ------------------------------ + ----------------- -----------------------
| # | pid | nome de usuário | application_name | datname | iniciado | duração | estado | consulta
+ ---- + ---------- + ---------- + -------------------- + - --------- + -------------------- + ------------------- - + ------------------------------ + ----------------- -----------------------
| 1 | 26211 tuser | psql | tdb1 2019-09-02 19: 31: 54 | 00: 00: 04 | ocioso |
| 2 26211 tuser | psql | tdb1 2019-09-02 19: 31: 58 | 00: 00: 06 | ocioso na transação | começar;
| 3 26211 tuser | psql | tdb1 2019-09-02 19: 32: 16 | 00: 01: 45 | ocioso na transação | tabela de bloqueio wafer_data;
| 4 26211 tuser | psql | tdb1 2019-09-02 19: 35: 54 | 00: 01: 23 | ocioso | confirmar;
| 5 26211 tuser | psql | tdb1 2019-09-02 19: 38: 46 | 00: 00: 02 | ocioso na transação | começar;
| 6 26211 tuser | psql | tdb1 2019-09-02 19: 38: 54 | 00: 00: 08 | ocioso na transação | tabela de bloqueio wafer_data;
| 7 26211 tuser | psql | tdb1 2019-09-02 19: 39: 08 | 00: 42: 42 | ocioso | confirmar;
| 8 26211 tuser | psql | tdb1 2019-09-03 07: 12: 07 | 00: 00: 52 | ativo | selecione test_del ();
Desenvolvimento.
As consultas básicas mostradas e os relatórios recebidos já simplificam bastante a vida ao analisar incidentes de desempenho.
Com base em consultas básicas, você pode obter um relatório remotamente reminiscente do Oracle AWR.
Relatório de resumo de amostra + ------------------------------------------------- -----------------------------------
| RELATÓRIO CONSOLIDADO DE ATIVIDADES E DE ESPERA. Data: 09/03/2019 14:08
| ------------------------------------------------- -----------------------------------
| HOST: XXXX
| BEGIN_SNAPSHOT: 09/02/2019 14:08 END_SNAPSHOT: 09/03/2019 14:00
| ------------------------------------------------- -----------------------------------
| TAMANHO ATUAL DAS BASES DE DADOS:
| DATABASE: monitor
| TAMANHO (MB): 1370,00
| ------------------------------------------------- -----------------------------------
| CLUSTER TEMPO DE CPU: 19:44:22
| CLUSTER WAITINGS TIME: 78:49:16
|
| SQL DBTIME: 65:53:09
| TEMPO DE CPU DO SQL: 19:05:21
| TEMPO DE ESPERA DO SQL: 21:50:46
| SQL IOTIME: 20:53:00
| SQL TEMPO DE LER: 20:52:55
| SQL WRITE TIME: 00:00:05
|
| CHAMADAS SQL: 311293
-------------------------------------------------- -----------
| BLOCOS COMPARTILHADOS DO SQL LEIA: 13351563334
| HITS DE BLOCOS COMPARTILHADOS DO SQL: 2775427045
| BLOCOS COMPARTILHADOS DO SQL HITS / LEITOS%: 20.79
| BLOCOS COMPARTILHADOS DO SQL DIRTED: 21105
| BLOCOS COMPARTILHADOS DO SQL ESCRITO: 3656
|
| BLOCOS TEMPORÁRIOS DO SQL LEIA: 7464932
| BLOCOS TEMPORÁRIOS DO SQL ESCRITOS: 10176024
-------------------------------------------------- -----------
|
| ESTATÍSTICAS DE ESPERA
|
+ ------------------------------------------------- -----------------------------------
| AS 10 MELHORES ESPERANÇAS POR TEMPO TOTAL DE ESPERA PARA PROCESSOS DO SISTEMA
+ ----- + ------------------------------ + ------------ -------- + --------------------
| # | wait_event_type | wait_event | duração
+ ----- + ------------------------------ + ------------ -------- + --------------------
| 1 | Atividade | LogicalLauncherMain | 11:21:01
| 2 Atividade | CheckpointerMain | 11:20:35
| 3 Atividade | AutoVacuumMain | 11:20:31
| 4 Atividade | WalWriterMain | 11:19:35
| 5 Atividade | BgWriterMain | 10:14:19
| 6 Atividade | BgWriterHibernate | 01:06:04
| 7 Atividade | WalSenderMain | 00:04:05
| 8 Cliente ClientWrite | 00:04:00
| 9 IO BufFileWrite | 00:02:45
| 10 LWLock | buffer_mapping | 00:02:14
+ ----- + ------------------------------ + ------------ -------- + --------------------
| AS 10 MELHORES ESPERANÇAS POR TEMPO TOTAL DE ESPERA PARA PROCESSOS DE CLIENTES
+ ----- + ------------------------------ + ------------ -------- + -------------------- + ----------
| # | wait_event_type | wait_event | duração | % dbtime
+ ----- + ------------------------------ + ------------ -------- + -------------------- + ----------
| 1 | Bloqueio | transactionid | 11: 55: 37 | 18,1
| 2 IO DataFileRead | 07: 19: 43 | 12/12
| 3 Cliente ClientRead | 00: 46: 54 | 1,19
| 4 Bloqueio | relação | 00: 40: 37 | 1.03
| 5 LWLock | buffer_mapping | 00: 31: 08 | 0,79
| 6 LWLock | buffer_io | 00: 22: 12 | 0,56
| 7 Tempo limite | PgSleep | 00: 10: 58 | 0,28
| 8 Bloqueio | tupla | 00: 01: 30 | 0,04
| 9 IO BufFileWrite | 00: 01: 16 | 0,03
| 10 IO BufFileRead | 00: 00: 37 | 0,02
+ ----- + ------------------------------ + ------------ -------- + -------------------- + ----------
| TIPOS DE ESPERA POR TEMPO TOTAL DE ESPERA, PARA PROCESSOS DO SISTEMA
+ ----- + ------------------------------ + ------------ --------
| # | wait_event_type | duração
+ ----- + ------------------------------ + ------------ --------
| 1 | Atividade | 56:46:10
| 2 IO 00:05:13
| 3 Cliente 00:04:00
| 4 LWLock | 00:03:07
+ ----- + ------------------------------ + ------------ --------
| TIPOS DE ESPERANÇA POR TEMPO TOTAL DE ESPERA, PARA PROCESSOS DE CLIENTES
+ ----- + ------------------------------ + ------------ -------- + --------------------
| # | wait_event_type | duração | % dbtime
+ ----- + ------------------------------ + ------------ -------- + --------------------
| 1 | Bloqueio | 12: 37: 44 19.17
| 2 IO 07: 21: 40 | 11.17
| 3 LWLock | 00: 53: 26 | 1,35
| 4 Cliente 00: 46: 54 | 1,19
| 5 Tempo limite | 00: 10: 58 | 0,28
| 6 IPC 00: 00: 04 | 0 0
+ ----- + ------------------------------ + ------------ -------- + --------------------
| ESPERANDO PROCESSOS DE SISTEMA
+ ----- + ----------------------------- + ---------- + - ------------------ + ---------------------- + -------- ------------
| # | backend_type | dbname | wait_event_type | wait_event | duração
+ ----- + ----------------------------- + ---------- + - ------------------ + ---------------------- + -------- ------------
| 1 | iniciador de replicação lógica | | Atividade | LogicalLauncherMain | 11:21:01
| 2 checkpointer | | Atividade | CheckpointerMain | 11:20:35
| 3 lançador de vácuo automático | | Atividade | AutoVacuumMain | 11:20:31
| 4 walwriter | | Atividade | WalWriterMain | 11:19:35
| 5 escritor de antecedentes | | Atividade | BgWriterMain | 10:14:19
| 6 escritor de antecedentes | | Atividade | BgWriterHibernate | 01:06:04
| 7 walsender | | Atividade | WalSenderMain | 00:04:05
| 8 walsender | | Cliente ClientWrite | 00:04:00
| 9 trabalhador paralelo | tdb1 IO BufFileWrite | 00:02:45
| 10 trabalhador paralelo | tdb1 LWLock | buffer_mapping | 00:02:05
| 11 trabalhador paralelo | tdb1 IO DataFileRead | 00:01:10
| 12 trabalhador paralelo | tdb1 IO BufFileRead | 00:01:05
| 13 trabalhador paralelo | tdb1 LWLock | buffer_io | 00:00:45
| 14 trabalhador de autovacuum | tdb1 LWLock | buffer_mapping | 00:00:09
| 15 walwriter | | IO WALWrite | 00:00:08
| 16 walwriter | | LWLock | WALWriteLock | 00:00:04
| 17 escritor de antecedentes | | LWLock | WALWriteLock | 00:00:03
| 18 escritor de antecedentes | | IO WALWrite | 00:00:02
| 19 escritor de antecedentes | | IO DataFileWrite | 00:00:02
| 20 checkpointer | | IO ControlFileSyncUpdate | 00:00:01
| 21 trabalhador de autovacuum | tdb1 LWLock | buffer_io | 00:00:01
+ ----- + ----------------------------- + ---------- + - ------------------ + ---------------------- + -------- ------------
| ESPERANDO PARA SQL
+ ----- + ------------------------- + ---------- + ------ -------------- + -------------------- + -------------- ------ + ----------
| # | queryid | dbname | wait_event_type | wait_event | duração | % dbtime
+ ----- + ------------------------- + ---------- + ------ -------------- + -------------------- + -------------- ------ + ----------
| 1 | 389015618226997618 | tdb1 Bloqueio | transactionid | 09: 47: 43 | 14,87
| 2 389015618226997618 | tdb1 IO DataFileRead | 05: 47: 07 8,78
| 3 | tdb1 Bloqueio | transactionid | 02: 07: 54 | 3,24
| 4 | tdb1 IO DataFileRead | 01: 30: 24 | 2,29
| 5 8085340880788646241 | tdb1 Cliente ClientRead | 00: 40: 20 | 1.02
| 6 389015618226997618 | tdb1 LWLock | buffer_mapping | 00: 20: 41 | 0,52
| 7 389015618226997618 | tdb1 LWLock | buffer_io | 00: 17: 30 | 0,44
| 8 2649515222348904837 | tdb1 Tempo limite | PgSleep | 00: 10: 58 | 0,28
| 9 4710212362688288619 | tdb1 Bloqueio | relação | 00: 10: 44 | 0,27
| 10 9150846928388977274 | tdb1 Bloqueio | relação | 00: 10: 24 | 0,26
| 11 28942442626229688 | tdb1 Bloqueio | relação | 00: 07: 48 | 0,2
| 12 1237430309438971376 | tdb1 Bloqueio | relação | 00: 07: 32 | 0,19
| 13 | tdb1 LWLock | buffer_mapping | 00: 04: 32 | 0,11
| 14 | tdb1 LWLock | buffer_io | 00: 04: 13 | 0,11
| 15 | tdb1 Cliente ClientRead | 00: 03: 57 | 0,1
| 16 4710212362688288619 | tdb1 LWLock | buffer_mapping | 00: 02: 26 | 0,06
| 17 3167065002719415275 | tdb1 Bloqueio | relação | 00: 02: 20 | 0,06
| 18 5731212217001535134 | tdb1 Cliente ClientRead | 00: 01: 53 | 0,05
| 19 1237430309438971376 | tdb1 LWLock | buffer_mapping | 00: 01: 42 | 0,04
| 20 389015618226997618 | tdb1 Bloqueio | tupla | 00: 01: 30 | 0,04
| 21 8304755792398128062 | tdb1 Bloqueio | relação | 00: 01: 29 | 0,04
| 22 28942442626229688 | tdb1 IO BufFileWrite | 00: 01: 16 | 0,03
| 23 9150846928388977274 | tdb1 IO DataFileRead | 00: 01: 07 | 0,03
| 24 28942442626229688 | tdb1 LWLock | buffer_mapping | 00: 01: 03 | 0,03
| 25 9150846928388977274 | tdb1 LWLock | buffer_mapping | 00: 00: 44 | 0,02
| 26 28942442626229688 | tdb1 IO BufFileRead | 00: 00: 37 | 0,02
| 27 28942442626229688 | tdb1 LWLock | buffer_io | 00: 00: 25 | 0,01
| 28 1237430309438971376 | tdb1 IO DataFileRead | 00: 00: 24 | 0,01
| 29 28942442626229688 | tdb1 IO DataFileRead | 00: 00: 22 | 0,01
| 30 5731212217001535134 | tdb1 Bloqueio | relação | 00: 00: 20 | 0,01
| 31 4710212362688288619 | tdb1 IO DataFileRead | 00: 00: 19 | 0,01
| 32 9150846928388977274 | tdb1 Cliente ClientRead | 00: 00: 09 | 0 0
| 33 3422818749220588372 | tdb1 Cliente ClientRead | 00: 00: 08 | 0 0
| 34 1237430309438971376 | tdb1 Cliente ClientRead | 00: 00: 06 | 0 0
| 35 389015618226997618 | tdb1 LWLock | buffer_content | 00: 00: 05 | 0 0
| 36 4710212362688288619 | tdb1 Cliente ClientRead | 00: 00: 05 | 0 0
| 37 4710212362688288619 | tdb1 LWLock | buffer_io | 00: 00: 04 | 0 0
| 38 28942442626229688 | tdb1 Cliente ClientRead | 00: 00: 04 | 0 0
| 39 28942442626229688 | tdb1 IPC ParallelFinish | 00: 00: 03 | 0 0
| 40 389015618226997618 | tdb1 IO DataFileWrite | 00: 00: 02 | 0 0
| 41 -5730801771815999400 | tdb1 Cliente ClientRead | 00: 00: 02 | 0 0
| 42 2404820632950544954 | tdb1 Cliente ClientRead | 00: 00: 02 | 0 0
| 43 -6572922443698419129 | tdb1 Cliente ClientRead | 00: 00: 02 | 0 0
| 44 8304755792398128062 | tdb1 Cliente ClientRead | 00: 00: 02 | 0 0
| 45 -1473395109729441239 | tdb1 Cliente ClientRead | 00: 00: 02 | 0 0
| 46 | tdb1 LWLock | buffer_content | 00: 00: 01 | 0 0
| 47 180077086776069052 | tdb1 Cliente ClientRead | 00: 00: 01 | 0 0
| 48 | tdb1 IO DataFileWrite | 00: 00: 01 | 0 0
| 49 28942442626229688 | tdb1 IPC MessageQueueReceive | 00: 00: 01 | 0 0
| 50 2369289265278398647 | tdb1 Cliente ClientRead | 00: 00: 01 | 0 0
| 51 9150846928388977274 | tdb1 IO DataFileWrite | 00: 00: 01 | 0 0
+ ----- + ------------------------- + ---------- + ------ -------------- + -------------------- + -------------- ------ + ----------
|
| ESTATÍSTICAS SQL DO CLIENTE
|
+ ------------------------------------------------- -----------------------------------
| CLIENT SQL ordenado por tempo decorrido
+ -------------------- + ---------- + ---------- + ------ ---- + ---------- + ---------- + --------------------
| tempo decorrido | chamadas | % dbtime | % CPU | % IO | dbname | queryid
+ -------------------- + ---------- + ---------- + ------ ---- + ---------- + ---------- + --------------------
| 06: 43: 19 36 10,2 85 de setembro | 17,38 | tdb1 389015618226997618
| 02: 06: 53 | 715 3,21 | 0,85 | 0,06 | tdb1 1237430309438971376
| 01: 52: 07 720 2,84 | 1,19 | 0,08 | tdb1 4710212362688288619
| 00: 39: 03 | 357 0,99 | 1.02 0,33 | tdb1 28942442626229688
| 00: 22: 00 | 8 0,56 | 0,96 | 0 tdb1 2649515222348904837
+ -------------------- + ---------- + ---------- + ------ ---- + ---------- + ---------- + --------------------
| CLIENT SQL ordenado pelo tempo da CPU
+ -------------------- + ---------- + ---------- + ------ ---- + ---------- + ---------- + ---------- + ------------ --------
| tempo da CPU | chamadas | % dbtime | total_time | % CPU | % IO | dbname | queryid
+ -------------------- + ---------- + ---------- + ------ ---- + ---------- + ---------- + ---------- + ------------ --------
| 16: 14: 38 | 36 10,2 06: 43: 19 85 de setembro | 17,38 | tdb1 389015618226997618
| 00: 13: 38 | 720 2,84 | 01: 52: 07 1,19 | 0,08 | tdb1 4710212362688288619
| 00: 11: 39 | 357 0,99 | 00: 39: 03 | 1.02 0,33 | tdb1 28942442626229688
| 00: 10: 58 | 8 0,56 | 00: 22: 00 | 0,96 | 0 tdb1 2649515222348904837
| 00: 09: 44 | 715 3,21 | 02: 06: 53 | 0,85 | 0,06 | tdb1 1237430309438971376
+ -------------------- + ---------- + ---------- + ------ ---- + ---------- + ---------- + ---------- + ------------ --------
| CLIENT SQL ordenado pelo tempo de espera de E / S do usuário
+ -------------------- + ---------- + ---------- + ------ ---- + ---------- + ---------- + ---------- + ------------ --------
| tempo de espera | chamadas | % dbtime | total_time | % CPU | % IO | dbname | queryid
+ -------------------- + ---------- + ---------- + ------ ---- + ---------- + ---------- + ---------- + ------------ --------
| 05: 47: 09 | 36 10,2 06: 43: 19 85 de setembro | 17,38 | tdb1 389015618226997618
| 00: 02: 15 | 357 0,99 | 00: 39: 03 | 1.02 0,33 | tdb1 28942442626229688
| 00: 00: 24 | 715 3,21 | 02: 06: 53 | 0,85 | 0,06 | tdb1 1237430309438971376
| 00: 00: 19 | 720 2,84 | 01: 52: 07 1,19 | 0,08 | tdb1 4710212362688288619
| 00: 00: 00 | 8 0,56 | 00: 22: 00 | 0,96 | 0 tdb1 2649515222348904837
+ -------------------- + ---------- + ---------- + ------ ---- + ---------- + ---------- + ---------- + ------------ --------
| CLIENT SQL ordenado por buffers compartilhados lê
+ -------------------- + ---------- + ---------- + ------ ---- + ---------- + ---------- + ---------- + ------------ --------
| buffers lê | chamadas | % dbtime | total_time | % CPU | % IO | dbname | queryid
+ -------------------- + ---------- + ---------- + ------ ---- + ---------- + ---------- + ---------- + ------------ --------
| 2562353244 | 36 10,2 06: 43: 19 85 de setembro | 17,38 | tdb1 389015618226997618
| 11041689 | 357 0,99 | 00: 39: 03 | 1.02 0,33 | tdb1 28942442626229688
| 3303551 715 3,21 | 02: 06: 53 | 0,85 | 0,06 | tdb1 1237430309438971376
| 3242892 | 720 2,84 | 01: 52: 07 1,19 | 0,08 | tdb1 4710212362688288619
| 0 8 0,56 | 00: 22: 00 | 0,96 | 0 tdb1 2649515222348904837
+ -------------------- + ---------- + ---------- + ------ ---- + ---------- + ---------- + ---------- + ------------ --------
| CLIENT SQL ordenado pelo tempo de leitura do disco
+ -------------------- + ---------- + ---------- + ------ ---- + ---------- + ---------- + ---------- + ------------ --------
| tempo de leitura | chamadas | % dbtime | total_time | % CPU | % IO | dbname | queryid
+ -------------------- + ---------- + ---------- + ------ ---- + ---------- + ---------- + ---------- + ------------ --------
| 03: 37: 46 36 10,2 06: 43: 19 85 de setembro | 17,38 | tdb1 389015618226997618
| 00: 04: 07 | 357 0,99 | 00: 39: 03 | 1.02 0,33 | tdb1 28942442626229688
| 00: 00: 59 | 720 2,84 | 01: 52: 07 1,19 | 0,08 | tdb1 4710212362688288619
| 00: 00: 42 | 715 3,21 | 02: 06: 53 | 0,85 | 0,06 | tdb1 1237430309438971376
| 00: 00: 00 | 8 0,56 | 00: 22: 00 | 0,96 | 0 tdb1 2649515222348904837
+ -------------------- + ---------- + ---------- + ------ ---- + ---------- + ---------- + ---------- + ------------ --------
| CLIENT SQL ordenado pelas execuções
+ -------------------- + ---------- + ---------- + ------ ---- + ---------- + ---------- + ---------- + ------------ --------
| chamadas | linhas | % dbtime | total_time | % CPU | % IO | dbname | queryid
+ -------------------- + ---------- + ---------- + ------ ---- + ---------- + ---------- + ---------- + ------------ --------
| 720 720 2,84 | 01: 52: 07 1,19 | 0,08 | tdb1 4710212362688288619
| 715 715 3,21 | 02: 06: 53 | 0,85 | 0,06 | tdb1 1237430309438971376
| 357 0 0,99 | 00: 39: 03 | 1.02 0,33 | tdb1 28942442626229688
| 36 36 10,2 06: 43: 19 85 de setembro | 17,38 | tdb1 389015618226997618
| 8 8 0,56 | 00: 22: 00 | 0,96 | 0 tdb1 2649515222348904837
+ -------------------- + ---------- + ---------- + ------ ---- + ---------- + ---------- + ---------- + ------------ --------
| Lista completa de texto SQL
----------------------------------------------
...
Para ser continuado. O próximo passo é a formação do histórico de bloqueios (pg_stat_locks), uma descrição mais detalhada do processo de preenchimento de tabelas.