我有一个带有索引的表格:
create index on foo (a, b, c);
当搜索 a 和 b 时,Postgres 可以使用索引快速查找行:
test=# explain analyze select a from foo where a = 3 and b = 4;
Index Only Scan using foo_a_b_c_idx on foo (cost=0.43..486.83 rows=120 width=4) (actual time=0.141..23.981 rows=59049 loops=1)
Index Cond: ((a = 3) AND (b = 4))
Heap Fetches: 59049
Total runtime: 25.894 ms
当搜索b和c时,速度要慢得多,因为它必须线性扫描整个索引(或表):
test=# explain analyze select a from foo where b = 4 and c = 5;
Index Only Scan using foo_a_b_c_idx on foo (cost=0.43..121987.32 rows=120 width=4) (actual time=7.377..159.793 rows=59049 loops=1)
Index Cond: ((b = 4) AND (c = 5))
Heap Fetches: 59049
Total runtime: 160.735 ms
然而,在这两种情况下,查询计划看起来是相等的(都称为“索引扫描”,带有一些“索引条件”)...是否可能告诉我们访问是否可以在对数时间或线性时间内完成(而不必查看每个索引定义)?
其他数据库系统更明确地说明了它们如何使用索引。在MS SQL中,第一个查询将是“索引搜索”(快速),而第二个查询将是“索引扫描”(慢)。在Sqlite中,第一个查询将是“使用覆盖索引搜索表foo”(快速),而第二个查询将是“使用覆盖索引扫描表foo”(慢)。
b,c
不在索引的前沿,因此Postgres需要扫描更多的索引块以检查行是否符合条件。如果您确实需要第二个查询与第一个一样快,那么您需要在(b,c,a)上建立第二个索引。您还可以运行explain(analyze true,verbose true,buffers true)
,它将向您显示有关Postgres正在执行的IO数量的更多详细信息。 - user330315Buffers: shared hit=228 read=18541 written=1
这行有所不同吗?(顺便问一下,你知道这个网站吗:http://explain.depesz.com?) - user330315