我知道索引在内部是B树或类似的树结构。假设索引是为3列构建的(a,b,c),我希望Postgres执行以下操作:
(a,b,c)
如果索引只有一列,则解决方案显而易见:
select * from table1 where a >= 10 order by a limit 10
但是,如果有更多的列,解决方案将变得更加复杂。对于2列:
select * from table1 where a > 10 or (a = 10 and b >= 20) order by a, b limit 10
3栏:
select * from table1 where a > 10 or (a = 10 and (b > 20 or b = 20 and c >= 30)) order by a, b, c limit 10
请注意查询:
select * from table1 where a >= 10 and b >= 20 and c >= 30 order by a, b, c limit 10
是 不正确的 ,因为它将例如过滤掉[a = 11,b = 10,c = 1]。
如何告诉Postgres我要执行此操作?
我是否可以确定,即使对于2+列的那些复杂查询,优化器也将始终理解他应该执行范围扫描? 为什么?
使用ROW值进行比较:
SELECT * FROM table1 WHERE (a,b,c) >= (10, 20, 30) ORDER BY a,b,c LIMIT 10;
(>=尽管您的描述显示了建议,但仍可使用它来匹配您的代码>。两种方法都可以。)
>=
>
(a,b,c)是的缩写ROW(a,b,c),真的。
ROW(a,b,c)
是的,Postgres知道可以为此使用匹配的多列B树索引(与其他RDBMS不同-或我听说过)。
“匹配” 意味着所有索引表达式,它们的序列和关联的顺序(ASC| DESC)都是相同的- 或整个索引行的排序顺序完全相反,因此Postgres可以以几乎相同的速度向后扫描索引。 对于给定的示例,这些索引匹配:
ASC
DESC
(a ASC, b ASC, c ASC) (a DESC, b DESC, c DESC)
但是这些 不是 :
(a ASC, b DESC, c ASC) (a ASC, c ASC, b ASC)
在一系列时间戳上优化查询(两列)