เป็นไปได้ที่จะบันทึกจำนวนสูงสุดใน 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();

นี่อาจไม่ใช่ตัวเลือกที่มีประสิทธิภาพดีที่สุด แต่เมื่อคุณถึงขีด จำกัด แล้วจะไม่เกินตัวเลือก หากมีพื้นที่สำหรับความผันผวนคุณสามารถตรวจสอบหมายเลขแถวเป็นระยะและลบแถวที่เกินจากจุดเริ่มต้น

แก้ไข: หากคุณมีบันทึกที่มีขนาดใหญ่มาก (พูดหนึ่งล้านต่อเดือน) กว่าการแบ่งพาร์ติชันอาจเป็นวิธีที่ง่ายที่สุด จากนั้นคุณสามารถวางตารางที่ไม่จำเป็นออก (พูดตรงไหนmax(timestamp) < CURRENT_DATE - 1 year) คุณสามารถใช้การประทับเวลาของคุณ (หรือวันที่ได้มา) เป็นเงื่อนไขสำหรับช่วงแบ่งพาร์ทิชัน

แต่ต้องระวังก่อนที่จะทิ้งบันทึกเก่า ๆ คุณแน่ใจหรือไม่ว่าไม่ต้องการสิ่งเหล่านั้น


เราสามารถดำเนินการเป็นระยะ ๆ และเรามั่นใจว่าเราจะไม่จำเป็นต้องใช้พวกเขาเมื่อได้รับตารางขนาดใหญ่พอที่จะต้องใช้นี้ฉันแค่พยายามที่จะทำงานโดยอัตโนมัติการบำรุงรักษาฐานข้อมูลมากที่สุดเท่าที่เป็นไปได้ :)
Jharwood

นอกจากนี้ฉันหวังว่า postgres สามารถบอกได้ว่าอันใดที่แก่กว่าตัวเอง แต่ถ้าไม่ใช่เพราะเราไม่มี ID มันสามารถใช้วันที่ที่เราสร้างฟิลด์การประทับเวลา "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: ฟิลด์คีย์ตัวเลข, โปรเกรสซีฟ
  • nritems: จำนวนรายการที่จะเก็บ
  • rnd: สุ่มหมายเลขจาก 0 ถึง 1; ยิ่งมีขนาดใหญ่ขึ้นตารางที่ใช้บ่อยจะถูกทำความสะอาดมากขึ้น (0 = ไม่เคย 1 = เสมอ 0.1 = 10% ของจำนวนครั้ง)

วิธีนี้คุณสามารถสร้างจำนวนทริกเกอร์ที่คุณต้องการเรียกใช้ฟังก์ชันเดียวกัน

หวังว่านี่จะช่วยได้


0

ฉันสร้าง proc นี้และเรียกใช้จาก 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;
$$;

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.