Postgresql'de maksimum kayıt tutabilmek mümkün mü?


9

Temel olarak Postgresql tablonuzun bir kısmı sunucu erişim günlüklerini tutmak için kullanılır ve bazen üretim sırasında bu oldukça büyük olabilir. postgresql'de bir tablonun sahip olabileceği maksimum kayıt sayısına sahip olmak ve en eski kaydı çıkarmak için herhangi bir yol var mı?

Yanıtlar:


12

İstediğiniz satır numarasını korumak için bir tetikleyici tanımlayabilirsiniz:

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

Bu muhtemelen en iyi performans gösteren seçenek değildir, ancak sınıra ulaştığınızda hiçbir zaman aşılmayacaktır. Dalgalanma için boşluk varsa, satır numarasını periyodik olarak kontrol edebilir ve fazla satırları baştan silebilirsiniz.

EDIT: Eğer gerçekten büyük günlükleri (ayda bir milyon diyelim) bölümleme daha kolay bir çözüm olabilir. Daha sonra gereksiz tabloları bırakabilirsiniz (nerede olduğunu söyleyinmax(timestamp) < CURRENT_DATE - 1 year). Aralık etiketlemenin koşulu olarak zaman damganızı (veya türetilmiş bir tarihi) kullanabilirsiniz.

Ancak eski günlükleri atmadan önce dikkatli olun. Bunlara asla ihtiyacınız olmayacağından emin misiniz?


periyodik olarak uygulayabiliriz ve tablo bunu gerektirecek kadar büyük hale geldiğinde onlara ihtiyacımız olmayacağından eminiz, sadece DB bakımını olabildiğince otomatikleştirmeye çalışıyorum :)
Jharwood

Ayrıca ben postgres hangisinin kendisinin daha eski olduğunu söyleyebilir umuyordum, ama kimliğimiz yoksa bizim oluşturulmuş tarih zaman damgası alanımızı kullanabilir "2012-06-22 17: 17: 52.692514"
Jharwood

@Jharwood - cevabımı düzenledi. Daha fazla ayrıntıya ihtiyacınız varsa lütfen bana bildirin.
dezso

2
Bölümleme önerisinde +1. Her seferinde tabloyu taramanın aşırı yükü olmadan bir sayıyla gitmek istiyorsanız, yaklaşık bir denetim için pg_class.reltuples komutunu kullanarak bir "kontrol" tablosundaki sayımı korumak için tetikleyicileri kullanabilirsiniz.
kgrittn

4

Daha genel, tablodan bağımsız bir işlev oluşturdum.

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

İşlev 4 parametre alır:

  • sekmesi: tablo adı
  • keyfld: sayısal, aşamalı anahtar alanı
  • nritems: saklanacak öğe sayısı
  • rnd: rastgele sayı, 0'dan 1'e; daha büyükse, daha sık tablo temizlenir (0 = asla, 1 = her zaman, 0.1 =% 10 kez)

Bu şekilde, aynı işlevi çağırmak istediğiniz tetikleyicileri oluşturabilirsiniz.

Bu yardımcı olur umarım.


0

Ben bu proc oluşturulan ve PG Agent (veya bağlı windows iş veya cron iş) çalıştırın. Daha fazla satırım olabilir, bu sadece günlük tablomu çok büyük değil tutar. Bir tetikleyicinin ek yükünü kaydeder.

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

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.