6

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

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
4

1 回答 1

9

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

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

还要注意,如果你有一个很小的表——比如说几千行或更少,通过索引访问这些行很少会比只扫描那几行更快。计划对数据量很敏感,您获得的包含少量行的计划不太可能与您获得的包含大量行的计划相同。

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

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

于 2012-05-13T19:43:15.763 回答