Posgres Posgis查询忽略订单上的地理索引

时间:2016-04-21 13:12:10

标签: postgresql indexing

我们有一个充满属性位置的表,当查询区域多边形时,会非常非常快地返回结果(通过使用正确的lonlat索引)

但是......当我们在不同的属性(价格,也有自己的索引)上包含一个额外的“order by”参数时,postgres决定将价格索引特权优先于lonlat一个,并且查询运行几千个时间慢了。

  • 有没有办法同时使用这两个索引?
  • 如果没有,我们如何向postgres解释它选择了错误的?

有趣的是,我们已经尝试完全删除价格指数,然后查询返回到lonlat索引并且运行得非常快。不幸的是,价格指数在应用程序的其他部分是必不可少的。

由于

1 个答案:

答案 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

但这是一个你应该谨慎使用的本地技巧,太多的优化围栏会使你的应用程序对未来不太友好。