我有一个非常简单的数据库模式,其中以下列上具有多列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。我的CPU是Core I5 2500k四核,内存为8 GB。
这是该查询的explain analyze结果:
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
CREATE TABLE
和CREATE INDEX
语句吗?如果可行的话,您使用的填充表的语句也是非常好的参考。(从 psql 输出的\d "Order"
可以,但这会让人们更难复制您的结果并测试建议的更改。)我假设数据已经完全缓存,否则在28秒内通过1亿行将会非常困难。默认配置假定最小化缓存,因此将选择基于磁盘访问假设的计划,这会对随机索引访问产生影响。 - kgrittnint
或bigint
代替numeric
。我曾经看到这样做可以提高高达5%的性能。http://www.postgresql.org/docs/current/interactive/datatype-numeric.html 如果您不需要numeric
提供的小数位精度,那么基于整数的类型(9223372036854775807)的最大值可能对大多数情况都足够了。 - kgrittn