PostgreSQL: Último horário de acesso à tabela

10

Sou responsável por um grande banco de dados PostgreSQL, com poucas dezenas de tabelas. Eu suspeito que muitas dessas tabelas nunca são acessadas.

Qual é a melhor maneira de verificar quando foi a última vez que uma determinada tabela foi acessada? Pensei em adicionar um gatilho DELETE, INSERTe UPDATE, mas eu espero que haja uma maneira mais eficiente.

Adam Matan
fonte
Você não pode criar um gatilhoselect . Você já pensou em registrar ?
Jack diz que tente topanswers.xyz 29/08
Obrigado, corrigido. O log pode ser a solução, mas o banco de dados é muito usado e provavelmente precisará de muito espaço em disco.
Adam Matan

Respostas:

9

pg_catalog.pg_statio_all_tables é seu amigo. Tudo o que você precisa fazer é pesquisar periodicamente pg_statio_all_tables para as tabelas em questão. Alterando estatísticas ~ tabela ativa, estatísticas não alteráveis ​​~ tabela potencialmente não utilizada. Apenas tome cuidado para que ninguém faça isso select pg_stat_reset () ;no meio do seu monitoramento.

Por exemplo:

test_1=# create table test_stats (col1 integer);
CREATE TABLE

test_1=# select * from pg_catalog.pg_statio_all_tables 
         where schemaname not in ('pg_catalog', 'information_schema') 
         and relname = 'test_stats';
 relid | schemaname |  relname   | heap_blks_read | heap_blks_hit | idx_blks_read | idx_blks_hit | toast_blks_read | toast_blks_hit | tidx_blks_read | tidx_blks_hit 
-------+------------+------------+----------------+---------------+---------------+--------------+-----------------+----------------+----------------+---------------
 22957 | public     | test_stats |              0 |             0 |        [null] |       [null] |          [null] |         [null] |         [null] |        [null]
(1 row)

Inserções:

test_1=# insert into test_stats (col1) select generate_series( 1, 10000000);
INSERT 0 10000000

test_1=# select * from pg_catalog.pg_statio_all_tables
         where schemaname not in ('pg_catalog', 'information_schema') 
         and relname = 'test_stats';
 relid | schemaname |  relname   | heap_blks_read | heap_blks_hit | idx_blks_read | idx_blks_hit | toast_blks_read | toast_blks_hit | tidx_blks_read | tidx_blks_hit 
-------+------------+------------+----------------+---------------+---------------+--------------+-----------------+----------------+----------------+---------------
 22957 | public     | test_stats |          44260 |      10088481 |        [null] |       [null] |          [null] |         [null] |         [null] |        [null]
(1 row)

Selecione% s:

test_1=# select count (*) from test_stats where col1 between 10000 and 50000;
 count 
-------
 40001
(1 row)

test_1=# select * from pg_catalog.pg_statio_all_tables
         where schemaname not in ('pg_catalog', 'information_schema') 
         and relname = 'test_stats';
 relid | schemaname |  relname   | heap_blks_read | heap_blks_hit | idx_blks_read | idx_blks_hit | toast_blks_read | toast_blks_hit | tidx_blks_read | tidx_blks_hit 
-------+------------+------------+----------------+---------------+---------------+--------------+-----------------+----------------+----------------+---------------
 22957 | public     | test_stats |          85560 |      10091429 |        [null] |       [null] |          [null] |         [null] |         [null] |        [null]
(1 row)

Exclui:

test_1=# delete from test_stats where col1 between 10000 and 50000;
DELETE 40001

test_1=# select * from pg_catalog.pg_statio_all_tables
         where schemaname not in ('pg_catalog', 'information_schema') 
         and relname = 'test_stats';
 relid | schemaname |  relname   | heap_blks_read | heap_blks_hit | idx_blks_read | idx_blks_hit | toast_blks_read | toast_blks_hit | tidx_blks_read | tidx_blks_hit 
-------+------------+------------+----------------+---------------+---------------+--------------+-----------------+----------------+----------------+---------------
 22957 | public     | test_stats |         155075 |      10136163 |        [null] |       [null] |          [null] |         [null] |         [null] |        [null]
(1 row)

update-- 2011-09-01

Testes adicionais indicam que vacuumparece aumentar um pouco os valores em pg_statio_all_tables, o que é lamentável para o uso desejado. Embora vacuumnão utilize inútil pg_statio_all_tables, torna a interpretação dos resultados um pouco mais confusa.

Talvez um lugar melhor para monitorar seja pg_catalog.pg_stat_all_tables (pelo menos nas versões mais recentes do Pg). Eu estou olhando para a versão 8.4 e que tem contagens para tuplas inseridas, lidas, atualizadas e excluídas - o ISTR 8.2 não tem tudo isso e eu não conheço a 8.3, portanto YMMV, dependendo da versão da página que você está usando.

Uma terceira opção (para inserir, atualizar e excluir atividades) é observar os registros de data e hora do arquivo no diretório $ PGDATA / base / $ datid. O nome do arquivo deve ser mapeado para o oid da tabela, para que você possa usá-lo para identificar tabelas que não estão recebendo inserções, atualizações ou exclusões. Infelizmente, isso não trata das tabelas que ainda estão sendo selecionadas e o uso de espaços de tabela causará complicações adicionais (pois esses arquivos não estarão em $ PGDATA / base / $ datid). Os carimbos de data e hora não serão atualizados até que todas as alterações pendentes sejam liberadas, mas se o arquivo não for alterado há meses, as chances de uma alteração atualmente pendente provavelmente serão pequenas.

gsiems
fonte
3

Você pode obter algumas informações sobre a última alteração em uma tabela com xmin, por exemplo:

select max(xmin::text::bigint) from t;

Mas, você precisa estar ciente do módulo e dos xids envolventes e congelados . Não há como converter isso em um "horário", mas se você capturar o valor para suas tabelas agora e comparar posteriormente, poderá obter uma lista de tabelas que foram alteradas

Jack diz que tenta topanswers.xyz
fonte