【问题标题】:Posgres Posgis query ignoring geo index on order byPostgres Postgis查询忽略按顺序排列的geog索引
【发布时间】:2016-04-21 13:12:09
【问题描述】:

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

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

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

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

谢谢

【问题讨论】:

    标签: postgresql indexing


    【解决方案1】:

    对于此类计划错误有很多话要说。

    首先,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
    

    但这是一个本地技巧,您应该谨慎使用,过多的优化栅栏会降低您的应用程序对未来的友好性。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-12-23
      • 1970-01-01
      • 2021-01-07
      • 1970-01-01
      • 2020-08-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多