É possível manter o número máximo de registros no postgresql?


9

Basicamente, parte da nossa tabela do Postgresql é usada para manter os logs de acesso ao servidor e, como tal, às vezes durante a produção, isso pode ficar muito grande. existe alguma maneira de configurar no postgresql para ter um número máximo de registros que uma tabela possa ter e empurrar o registro mais antigo?

Respostas:


12

Você pode definir um gatilho para manter o número da linha desejado:

CREATE OR REPLACE FUNCTION trf_keep_row_number_steady()
RETURNS TRIGGER AS
$body$
BEGIN
    -- delete only where are too many rows
    IF (SELECT count(id) FROM log_table) > rownum_limit
    THEN 
        -- I assume here that id is an auto-incremented value in log_table
        DELETE FROM log_table
        WHERE id = (SELECT min(id) FROM log_table);
    END IF;
END;
$body$
LANGUAGE plpgsql;

CREATE TRIGGER tr_keep_row_number_steady 
AFTER INSERT ON log_table
FOR EACH ROW EXECUTE PROCEDURE trf_keep_row_number_steady();

Provavelmente, essa não é a opção com melhor desempenho, mas quando você atingir o limite, nunca será excedido. Se houver espaço para flutuação, você poderá verificar o número da linha periodicamente e excluir linhas em excesso desde o início.

EDIT: Se você tiver logs realmente grandes (digamos um milhão por mês), o particionamento pode ser a solução mais fácil. Você pode simplesmente soltar as tabelas desnecessárias (digamos ondemax(timestamp) < CURRENT_DATE - 1 year). Você pode usar seu carimbo de data / hora (ou uma data derivada) como condição para o particionamento de intervalo .

Mas tenha cuidado antes de descartar logs antigos. Tem certeza de que nunca precisará disso?


podemos executá-lo periodicamente, e estamos certeza de que não vai precisar deles uma vez que a mesa fica grande o suficiente para exigir isso, eu só estou tentando automatizar a manutenção DB, tanto quanto possível :)
Jharwood

Também esperava que o postgres soubesse qual era o mais antigo, mas se não, como não temos IDs, ele poderia usar o campo de data e hora criado por data "2012-06-22 17: 17: 52.692514"
Jharwood

@Jharwood - editou minha resposta. Por favor, diga-me se você precisar de mais detalhes.
Dez

2
+1 na sugestão de particionamento. Se você quiser fazer uma contagem sem a sobrecarga extrema de varrer a tabela a cada vez, use pg_class.reltuples como uma aproximação ou use gatilhos para manter uma contagem em uma tabela de "controle".
kgrittn

4

Criei uma função independente de tabela mais genérica.

CREATE OR REPLACE FUNCTION keep_row_number_steady()
RETURNS TRIGGER AS
$body$
DECLARE
    tab text;
    keyfld text;
    nritems INTEGER;
    rnd DOUBLE PRECISION;
BEGIN
    tab := TG_ARGV[0];
    keyfld := TG_ARGV[1];
    nritems := TG_ARGV[2]; 
    rnd := TG_ARGV[3];

    IF random() < rnd
    THEN 
        EXECUTE(format('DELETE FROM %s WHERE %s < (SELECT %s FROM %s ORDER BY %s DESC LIMIT 1 OFFSET %s)', tab, keyfld, keyfld, tab, keyfld, nritems));
    END IF;
    RETURN NULL;
END;
$body$
LANGUAGE plpgsql;

CREATE TRIGGER log_table_keep_row_number_steady_trigger
AFTER INSERT ON log_table
FOR EACH STATEMENT EXECUTE PROCEDURE keep_row_number_steady('log_table', 'id', 1000, 0.1);

A função usa 4 parâmetros:

  • guia: nome da tabela
  • keyfld: campo-chave numérico e progressivo
  • nritems: número de itens a serem retidos
  • rnd: número aleatório, de 0 a 1; quanto maior, mais limpa a tabela (0 = nunca, 1 = sempre, 0,1 = 10% das vezes)

Dessa forma, você pode criar quantos gatilhos deseja chamar na mesma função.

Espero que isto ajude.


0

Eu criei este proc e o executei do PG Agent (ou trabalho do Windows ou trabalho cron, dependendo). Eu posso ter mais linhas, isso apenas mantém minha tabela de log não muito grande. Salva a sobrecarga de um gatilho.

CREATE or replace FUNCTION activitylogcleanup(_MaxRows int) RETURNS void
    LANGUAGE plpgsql
    AS $$
DECLARE
   minid    int;
BEGIN
    SELECT logid into minid FROM activitylogapplication 
     order by logid desc limit 1 OFFSET _MaxRows;

    if not found then 
        return;
    END IF; 

    Delete from activitylogapplication where logid < minid;
END;
$$;

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.