问题很简单。有什么方法可以动态限制Postgres数据库的最大行数?
我不认为有可能,直到我看到Heroku做到了。经过研究,我找到了一种使用触发器的方法:
CREATE OR REPLACE FUNCTION check_number_of_row()
RETURNS TRIGGER AS
$body$
BEGIN
-- replace 100 by the number of rows you want
IF (SELECT count(*) FROM your_table) > 100
THEN
RAISE EXCEPTION 'INSERT statement exceeding maximum number of rows for
this table'
END IF;
END;
$body$
LANGUAGE plpgsql;
CREATE TRIGGER tr_check_number_of_row
BEFORE INSERT ON your_table
FOR EACH ROW EXECUTE PROCEDURE check_number_of_row();
但这不是我所需要的。它将表的行数限制为STATIC的最大值,因此我将不得不遍历所有表,并且看起来很杂乱。而且我什至都没有想过动态设置此最大数量的方法。
我考虑过要进行每天/每周的cron工作,以检查所有数据库,计算总行数,并查看其是否在限制范围内,但是如果有更有效的方法,我会接受。
答案 0 :(得分:2)
由于SELECT count(*)
是一项非常昂贵的操作,因此我认为在每次数据更改时都运行它不是一个好主意。此外,行数不会告诉您表格的大小。
我的方法是像这样使用使用pg_total_relation_size()
的触发器:
CREATE OR REPLACE FUNCTION size_trig() RETURNS trigger
LANGUAGE plpgsql AS
$$BEGIN
IF pg_total_relation_size(TG_RELID) > (TG_ARGV[0])::bigint THEN
RETURN NULL;
ELSE
RETURN NEW;
END IF;
END;$$;
CREATE TRIGGER size_trig BEFORE INSERT ON big
FOR EACH ROW
EXECUTE PROCEDURE size_trig(819200);
这会将包括索引和TOAST表在内的表的总大小限制为100个块,并且相对便宜。
您仍然必须为要检查的所有表定义触发器,但是无法修改PostgreSQL。
您看到可以为每个表动态设置限制。您还可以提出一种使用查找表进行大小限制的解决方案。
答案 1 :(得分:1)
直到我看到Heroku做到了,我才认为这是不可能的。
这并不完全准确。 Heroku的爱好层的数据库行限制没有硬性限制。换句话说,当您在hobby-dev或hobby-basic中超过10k或10M行时,没有什么会立即停止写入。 Heroku通过电子邮件提供了一个7天的窗口,使计数不超过配额,否则将阻止写访问。如果您只是想抬起头来进行相应调整,那么他们已经有了一个不错的系统。
但是,关于您的问题,考虑到Heroku Postgres(尤其是对于业余数据库而言)已被相当严格地锁定,我认为您不会拥有实现所要执行的操作所需的控制级别,而又不会使其变得更混乱您有什么问题。