PostgreSQL查询不使用索引

时间:2012-05-13 19:06:32

标签: postgresql indexing

我有一个非常简单的数据库模式,它在以下列上有一个多列b-tree索引:

PersonId, Amount, Commission

现在,如果我尝试使用以下查询选择表:

explain select * from "Order" where "PersonId" = 2 AND "Commission" > 3

Pg正在扫描索引并且查询非常快,但是如果我尝试以下查询:

explain select * from "Order" where "PersonId" > 2 AND "Commission" > 3

即使存在索引,它也会执行顺序扫描。甚至这个查询

explain select * from "Order" where "Commission" > 3 

执行顺序扫描。 有人在乎解释原因吗? : - )

非常感谢。

更新

该表包含1亿行。我创建它只是为了测试PostgreSQL对MS SQL的性能。该表已经是VACUUMED。我正在运行Core I5 2500k四核CPU和8 GB内存。

以下是此查询的解释分析结果:

explain ANALYZE select * from "Order" where "Commission" BETWEEN 3000000 AND 3000010  LIMIT 20 


Limit  (cost=0.00..2218328.00 rows=1 width=24) (actual time=28043.249..28043.249 rows=0 loops=1)
  ->  Seq Scan on "Order"  (cost=0.00..2218328.00 rows=1 width=24) (actual time=28043.247..28043.247 rows=0 loops=1)
        Filter: (("Commission" >= 3000000::numeric) AND ("Commission" <= 3000010::numeric))
Total runtime: 28043.278 ms

1 个答案:

答案 0 :(得分:6)

简短的回答是,在比较各种可用计划时,根据您配置的成本核算因素和可用的最新统计数据,预计顺序扫描最快。根据您提供的少量信息,计划员似乎很可能做出了正确的选择。如果您有三个单列索引,则可能能够使用位图索引扫描,尤其是当要选择的行少于表中行的10%时。

请注意,对于您描述的索引,需要从"PersonId" > 2的所有行扫描整个索引;除非你有很多"PersonId"的负值,否则很可能是表格的大部分内容。

另请注意,如果您有一个小表 - 比如几千行或更少,通过索引访问行很少比扫描那几行快。计划对数据量敏感,而您使用少量行获得的计划不太可能与您获得大量行的计划相同。

如果实际上没有选择最快的计划,那么您需要调整成本因素以更好地模拟机器成本的可能性很大。另一种可能性是您需要在autovacuum设置中更积极,以确保可以获得最新的统计信息,或者您可能需要配置更细粒度的统计信息。

如果您显示表格描述(包括索引),查询的EXPLAIN ANALYZE输出以及硬件描述,人们将能够提供更具体的建议。