Rails ActiveRecord and PostgreSQL Partitioning



我有一个大型web应用程序,它每天在PostgreSQL中的分区表中写入数百万行(意味着每天的数据都有一个新表)。

我们使用PostgreSQL的表继承和分区来加快速度:

由于我们的数据库中有一年的数据,我们无法有效地使用插入触发器将内容路由到正确的表(函数的长度越来越长)。

长话短说,我们需要ActiveRecord来知道数据在哪个表上insertupdate。但是,不要更改用于选择和其他DB任务的表。

显然,为模型定义表名很简单,但是否可以仅为特定操作覆盖表名?

以下是更多细节:

数据库:

  • 表:dashboard.impressions(id、主机、数据、created_on等)
  • 表:data.impressions_20120801(继承自dashboard.impressions,约束created_on等于表日期)

Impression.create :host=>"localhost", :data=>"{...}", created_on=>DateTime.now应该写入data.impressions_20120801表,其中Impression.where(:host=>"localhost")应该在dashboard.impressions表上搜索,因为它包含所有数据。

编辑:我正在运行PostgreSQL 9.1和Rails 3.2.6

我不做Rails,所以我不能在ActiveRecord方面提供帮助,但如果你不能让ActiveRecord做你想做的事,我可以提供一个纯粹的Pg后备解决方案。这会花费你一点插入性能,所以教ActiveRecord在正确的位置插入会更好。

就我个人而言,我只想通过pggem直接执行INSERT,并完全绕过ActiveRecord。如果你不能做到这一点,或者ActiveRecord做了缓存,这意味着你不应该这样做,那么试试这个替代的分区触发器实现。

不要在触发器函数中显式列出每个分区,而是考虑插入EXECUTE ... USING,并使用命名方案生成分区名称。类似未经测试的东西:

CREATE OR REPLACE FUNCTION partition_trigger() RETURNS trigger AS $$
DECLARE
    target_partition text;
BEGIN
    IF tg_op = 'INSERT' THEN
        target_partition = ( ... work out the partition name ... )
        EXECUTE 'INSERT INTO '||quote_ident(target_partition)||' (col1,col2) VALUES ($1, $2)'
            USING (NEW.col1, NEW.col2);
    END IF;
    RETURN NULL;
END;
$$ LANGUAGE 'plpgsql';

最新更新