sql - where 和 order by 子句的多列索引(postgres)
问题描述
考虑这样的查询:
select ... from table where a = 1 and b > 2 order by c asc
这个查询的理想索引是什么?我应该使用一个索引(a,b,c)还是两个单独的(a,b)和(c)?
提前致谢。
解决方案
你可能不能同时做好这两件事。相等不是问题,但你不能干净地将不等与排序结合起来。您希望返回多少行?如果b>2
非常有选择性地留下几行进行排序,那么显然你想要(a,b)
获得选择性是有用的,而对剩余的几行进行排序不会花费很长时间。另一方面,如果b>2
只排除几行,那么(a,c)
(可能在末尾有更多列以允许仅索引扫描)避免大的慢速排序,同时删除少数失败的行b“硬方式”不会需要很长时间。
您可以同时构建两者并让计划者进行调用,尽管这样做远非完美。
可以在所有三列上使用 GiST 索引来同时实现不等式过滤和排序,但 GiST 索引的开销比 BTree 索引高得多,而且构建和维护速度较慢,因此不太可能值得一试,尽管如果您使用 LIMIT 可以使其更具吸引力。您还需要以扭曲的方式编写查询,作为 KNN 查询(由btree_gist扩展辅助):
where a = 1 and b > 2 order by c <-> impossibly_low_value
还有其他高级可能性。如果你比较 b 的东西总是>2
,那么你可以使用部分索引(a,c) where b>2
或表达式索引(a,(b>2),c)
。您也许还可以在 b 上进行有用的分区。如果 b 有少量不同的值,您可以对每个合格的不同值的查询结果进行 UNION ALL 并使用索引 on (a,b,c)
,获得有效的合并追加:
(select * from foo where a=1 and b=3 order by c asc)
union all
(select * from foo where a=1 and b=4 order by c asc)
order by c asc;
推荐阅读
- reactjs - 将选定的组件传递到表单反应的下一步
- javascript - 我在 Node.js `Uncaught SyntaxError: Invalid or unexpected token` 中收到以下错误
- python - Pycharm从终端创建文件时添加强制BOM
- python-3.x - 将带小数的浮点数转换为不带小数点的字符串 Python 3.7
- groovy - 易于阅读的单行测试字符串包含具有通配符模式的任意顺序的子字符串
- tidb - 如何设置每个 TIKV 的内存容量?
- mapping - 在给定十进制纬度和经度坐标的情况下查找子区域的纬度和经度限制
- gitlab - Gitlab中的自动数据库重新索引不起作用
- javascript - Javascript + Vue window.open 被阻止弹出
- php - 在条件下用逗号或“&”符号分隔值