PostgreSQL查询不使用索引

PostgreSQL查询不使用索引,postgresql,indexing,Postgresql,Indexing,我有一个非常简单的db模式,它在以下列上有一个多列b树索引: PersonId, Amount, Commission 现在,如果我尝试使用以下查询选择表: explain select * from "Order" where "PersonId" = 2 AND "Commission" > 3 explain select * from "Order" where "PersonId" > 2 AND "Commission" > 3 Pg正在扫描索引,查询速度非常

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

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

explain select * from "Order" where "PersonId" = 2 AND "Commission" > 3
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 "PersonId" > 2 AND "Commission" > 3
即使索引存在,它也会进行顺序扫描。甚至这个问题

explain select * from "Order" where "Commission" > 3 
进行顺序扫描。 有人愿意解释原因吗-

多谢各位

更新

该表包含1亿行。我创建它只是为了测试PostgreSQL对MS SQL的性能。桌子已经用吸尘器吸光了。我正在运行核心I5 2500k四核cpu和8GB内存

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

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

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

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

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

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


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

请看那里,尤其是@Frank Heikens answer。因为索引列顺序很重要。阅读以下内容:您可以向我们展示CREATETABLE和CREATEINDEX语句吗?如果可行的话,您用来填充表的语句也会非常有用\psql的d顺序输出就可以了,但它使人们更难复制您的结果并测试建议的更改。我假设数据是完全缓存的,否则要在28秒内通过1亿行将非常困难。默认配置假设最小缓存,因此将选择基于磁盘访问假设的计划,该计划将对随机索引访问进行加权。此外,如果您想要更好的性能,可以使用int或bigint而不是numeric。我已经看到这在性能上有5%的差异。如果您不需要数字可用的小数位数,则基于整数的类型9223372036854775807的最大值可能足以用于大多数目的。@kgrittn我首先使用红门的SQL数据生成器在SQL Server中生成数据,然后使用navicat premium将数据传输到PostgreSQL。我还使用navicat管理工具创建索引,这就是为什么我手头没有任何DDL脚本:+1。谢谢你的回答。我根据你的推荐更新了我的帖子: