我们有一个充满属性位置的表,当查询区域多边形时,会非常非常快地返回结果(通过使用正确的lonlat索引)
但是......当我们在不同的属性(价格,也有自己的索引)上包含一个额外的“order by”参数时,postgres决定将价格索引特权优先于lonlat一个,并且查询运行几千个时间慢了。
有趣的是,我们已经尝试完全删除价格指数,然后查询返回到lonlat索引并且运行得非常快。不幸的是,价格指数在应用程序的其他部分是必不可少的。
由于
答案 0 :(得分:0)
关于规划这类错误有很多话要说。
首先,PostgreSQL可以使用这两个索引,但他选择不出于某种原因。也许获取索引页面和获取数据页面的成本非常低。
除此之外,他选择了一个非常糟糕的计划,因此您需要使用EXPLAIN ANALYZE
检查预期与实际行数。如果PostgreSQL对各种行计数错误,您可能需要使用VACUUM ANALYZE
刷新其表统计信息。
如果这仍然没有改变查询计划,您可以考虑调整the statistics collector(获取更多关于列的信息可能会起作用)
但最终你总是可以欺骗PostgreSQL用CTE做你想做的事情。 如文档中所述,Common Table Expressions是“优化围栏”。这意味着PostgreSQL不会尝试使用CTE重写子查询。
如果您的快速查询如下所示:
SELECT *
FROM gis_table
WHERE /* some latlong filter */
你的慢查询看起来像这样:
SELECT *
FROM gis_table
WHERE /* some latlong filter */
ORDER BY price
您可以使用
强制PostgreSQL行为WITH filtered_gis_table AS (
SELECT *
FROM gis_table
WHERE /* some latlong filter */
)
SELECT *
FROM filtered_gis_table
ORDER BY price
但这是一个你应该谨慎使用的本地技巧,太多的优化围栏会使你的应用程序对未来不太友好。