【问题标题】:Rails ActiveRecord and PostgreSQL PartitioningRails ActiveRecord 和 PostgreSQL 分区
【发布时间】:2012-08-29 10:45:50
【问题描述】:

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

我们正在使用PostgreSQL's table inheritance and partitioning 来加快速度:

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

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

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

这里有更多细节:

数据库:

  • 表格:dashboard.impressions(id、host、data、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

【问题讨论】:

    标签: ruby-on-rails ruby-on-rails-3 postgresql partitioning


    【解决方案1】:

    我不使用 Rails,所以我无法在 ActiveRecord 方面提供帮助,但如果您无法让 ActiveRecord 做您想做的事情,我可以提供一个纯 Pg 后备解决方案。它会花费您一点点插入性能,因此教 ActiveRecord 将插入到正确的位置会更好。

    我个人只是通过pg gem 直接执行INSERTs 并完全绕过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';
    

    【讨论】:

    • 我们最终使用了pg gem 并以这种方式管理插入/更新 - 尽管该功能在我们的测试中也运行良好。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-02-13
    • 1970-01-01
    • 1970-01-01
    • 2015-01-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多