我有一个表,其中有许多不同类型的列,我用它来过滤和排序结果(这类似于带排序的分面搜索)。
让我们考虑2列:A
和B
。为每一列创建一个索引。
我们要查询A=value ORDER BY B LIMIT 10
。
如果计划程序将使用A
索引,则它必须扫描具有A=value
的所有行,并按B
对它们进行排序。
如果计划程序将使用B
索引,则它将扫描所有行,直到找到10个具有A=value
的行。
我们一共有2500000行,50000行有A=value
,所以每50行有一个A=value
,所以它认为只要扫描50*10=500行就可以找到10个A=value
行,但是它错了,因为两个字段之间有相关性,A=value
行分布不均匀,但它们位于B
索引的末尾,因此实际上需要扫描超过2000000行。
如果我们禁用B
索引,那么它是好的。但是,我们希望B
索引用于其他查询。
如何解决问题?
创建(A,B ASC)
索引不是一个好的解决方案。因为索引太多,而且A
可能是数组类型,不支持这样的索引。
1条答案
按热度按时间pgx2nnw81#
对于这个问题没有很好的通用解决方案。你可以通过在SQL中添加一些伪操作来强制它不使用B上的索引来进行逐案排序,比如:
或
PostgreSQL的未来版本总是有可能“看穿”这些伪操作并使用该索引。
如果B上的索引只需要支持相等比较,那么你可以把它变成一个HASH索引或GIN索引(通过btree_gin扩展),这不能用于排序,但仍然可以用于相等比较。