Можна зберігати максимальну кількість записів у postgresql?


9

В основному частина нашої таблиці Postgresql використовується для зберігання журналів доступу до сервера, і, як така, іноді під час виробництва це може бути досить великим. чи є спосіб встановити в postgresql максимальну кількість записів, яку може мати таблиця, і відтіснити найдавніший запис?

Відповіді:


12

Ви можете визначити тригер для підтримки потрібного номера рядка:

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();

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

EDIT: Якщо у вас справді великі журнали (скажімо, мільйон на місяць),найпростішим рішенням може стати розділення . Потім можна просто скинути непотрібні таблиці (сказати кудиmax(timestamp) < CURRENT_DATE - 1 year). Ви можете використовувати свою часову позначку (або похідну дату) як умову для розділення діапазону .

Але будьте обережні, перш ніж викидати старі журнали. Ви впевнені, що вони вам ніколи не знадобляться?


ми можемо виконувати його періодично, і ми впевнені, що вони нам не знадобляться, як тільки таблиця стане достатньо великою, щоб цього вимагати, я просто намагаюся максимально автоматизувати обслуговування БД:
Jharwood,

також я сподівався, що постгреси можуть сказати, хто з них сам старший, але якщо ні, як у нас немає ідентифікаторів, він може використовувати наше створене датою поле часової позначки "2012-06-22 17: 17: 52.692514"
Jharwood

@Jharwood - редагував мою відповідь. Скажіть, будь ласка, якщо вам потрібні додаткові деталі.
dezso

2
+1 на пропозицію про розділення. Якщо ви хочете переходити з підрахунком без надзвичайних накладних сканувань таблиці щоразу, ви можете використовувати pg_class.reltuples для приблизного, або ви можете використовувати тригери для підтримки рахунку в таблиці "керування".
kgrittn

4

Я створив більш загальну, незалежну від таблиці функцію.

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);

Функція приймає 4 параметри:

  • вкладка: назва таблиці
  • keyfld: числове, прогресивне ключове поле
  • нітрими: кількість елементів, які потрібно зберегти
  • rnd: випадкове число, від 0 до 1; чим він більший, тим частіша таблиця буде очищена (0 = ніколи, 1 = завжди, 0,1 = 10% разів)

Таким чином ви можете створити скільки тригерів ви хочете викликати одну і ту ж функцію.

Сподіваюсь, це допомагає.


0

Я створив цю програму і запускаю її з PG Agent (або робота Windows, або робота в cron). У мене може бути більше рядків, це просто не сприяє великій таблиці моїх журналів. Зберігає накладні витрати тригера.

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;
$$;
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.