这是多列索引的合适方案吗?

时间:2011-09-25 04:50:12

标签: ruby-on-rails postgresql indexing multiple-columns

我的编程环境是Rails 2.3和PostgreSQL 8(Heroku上的共享数据库): 我读过这个 http://devcenter.heroku.com/articles/postgresql-indexes#multicolumn_indexes 在我开始以通用方式构建我的应用程序之前,互联网上的其他相关资源:

我的表有两列A和B,都是索引的。 (这些行在(A,B)对方面是唯一的) 但在我构建我的应用程序之后,我发现我只用两种类型的调用来查询表: myTable.find_by_A_and_B(a,b)和myTable.find_by_A(a)

我们预计表中会有10000多个条目,不同A和不同B的比例约为3:1。我们期望对于A中的每个唯一值,将有超过1000多行在B中具有不同的值;对于B中的每个唯一值,A中不会有超过300行具有不同的值。

我的问题是:对于myTable.find_by_A_and_B(a,b)调用,当前数据库设置(带有两个单独的索引)是否可以归类为“高效”(因为我不知道PostgreSQL的内部工作) )。是否只用一个(A,B)的多列索引替换这两个索引会显着提高速度吗?

谢谢。

P.S。在回应评论时,这里有更多信息: 根据此页面,http://devcenter.heroku.com/articles/database 它正在运行PostgreSQL 8.3

以下是myTable的迁移架构:

create_table :myTable do |t|
    t.string :b
    t.integer:a
    t.boolean :c, :default => false
end

add_index :mytable, :b 
add_index :mytable, :a

1 个答案:

答案 0 :(得分:1)

在PostgreSQL的最新版本中multi-column indexes可以有效地用于过滤其中一个列。这在第一列中效果最好,但对其他列也相当不错。

此外,10.000行对于PostgreSQL来说是小菜一碟。具有数百万行的表并不罕见。

假设我们在整数(int4)列上谈论btree索引(默认)...
... 答案是:只需在(a,b) 上使用一个多列索引。

由于磁盘上的page layout(类似于表和索引),每个索引行有相当多的开销。此外,由于数据对齐限制,一个索引(a,b)将使用与(a)上的索引完全相同的磁盘空间量 - 在MAXALIGN的计算机上= 8个字节(大多数64位操作系统) 因此,特别是如果您有大量写入或有限的磁盘空间和/或RAM,最好的办法是在(a,b)上使用一个多列索引。在大量编写的表上维护索引也需要付出相当大的代价。

编辑以回应有关问题的更新:

  • ainteger,我的答案大多有效。 (a,b)上的索引将是您需要的全部或大部分内容。

  • 摆脱b 上的单独索引,因为您显然对b没有疑问。

  • 由于btext,(a,b)上的多列索引无法像上述那样从数据对齐中获利,但仍然如此。 b的中等长度越大,您就越有可能从a的额外索引中获利。短b,它可能不付钱。否则我希望它能加快myTable.find_by_A(a)的速度。

  • 这可能比ab上的两个单独索引更快,但速度不是很大,因为Postgres可以在bitmap index scan中合并两个索引。自v.8.3起,这已有所改进。

  • 请注意text上的btree索引仅帮助查询'='(如果您在C语言环境中运行,则更多)。阅读有关operator classes

  • 的手册

您不必接受我的话,使用EXPLAIN ANALYZE进行一些测试。它非常简单且信息丰富,并且为10,000行创建索引只需要一秒左右。重复每个查询几次以填充缓存并获得可比较的结果。