【问题标题】:How to switch between an indexed and non-indexed operation depending on the input?如何根据输入在索引操作和非索引操作之间切换?
【发布时间】:2019-12-24 18:32:26
【问题描述】:

My previous question 发现我的性能问题的原因是因为在 Postgis 中使用索引距离运算符在返回许多行的大区域上非常慢。

因此,理想的解决方案似乎是选择任意英里的距离量,然后在该范围内(例如,低于 75 英里)使用索引距离运算符 (ST_DWithin),然后当距离超出该范围(即 75 英里或以上)时,使用非索引距离运算符 (<->)

我当前的函数如下所示:

CREATE OR REPLACE FUNCTION public.usp_get_data(i_distance_choice integer, i_longitude double precision, i_latitude double precision)
 RETURNS TABLE(convo_id bigint)
 LANGUAGE SQL STABLE
AS $function$ 
    SELECT po.convo_id
    FROM post po
    WHERE ST_DWithin(po.geog, ST_SetSRID(ST_MakePoint(i_longitude, i_latitude), 4326)::geography, i_distance_choice * 1609.34)
    ORDER BY po.reply_count DESC, convo_id DESC
    LIMIT 10;
$function$;

所以看起来我需要一些条件。即如果i_distance_choice低于75,则使用ST_DWithin,如果是75或以上,则改为使用<->运算符。

有没有办法用 SQL 语言来做到这一点,或者我必须使用类似 plsql 的东西吗?或者有没有更好的方法可以通知 Postgres 不要将索引用于足够大的输入?这样条件就不需要了?

【问题讨论】:

  • 你又在用几何做这件事——更改为 ST_SetSRID(ST_MakePoint(i_longitude, i_latitude), 4326)::geography
  • 谢谢,已修复。

标签: sql postgresql indexing postgis


【解决方案1】:

我不认为它可以用纯 SQL 来完成。

将其转换为 PL/pgSQL 非常简单。

CREATE OR REPLACE FUNCTION public.usp_get_data(i_distance_choice integer, i_longitude double precision, i_latitude double precision)
 RETURNS TABLE(convo_id bigint)
 LANGUAGE plpgsql
 STABLE
AS $function$
    BEGIN
      IF i_distance_choice < 75 then
        return query SELECT po.convo_id
          FROM post po
          WHERE ST_DWithin(po.geog, ST_SetSRID(ST_MakePoint(i_longitude, i_latitude), 4326), i_distance_choice * 1609.34)
          ORDER BY po.reply_count DESC, convo_id DESC
          LIMIT 10;
      ELSE
        return query SELECT po.convo_id
          FROM post po
          WHERE po.geog<->ST_SetSRID(ST_MakePoint(i_longitude, i_latitude), 4326) < i_distance_choice * 1609.34
          ORDER BY po.reply_count DESC, convo_id DESC
          LIMIT 10;
      END IF;
    END
$function$

我验证它使用地理索引 (reply_count, convo_id) 索引在 75 及以上。

【讨论】:

  • 很遗憾,您必须复制整个查询(我发布的那个被删节了)。有没有办法避免这种情况?如果没有,那我就用这个。
猜你喜欢
  • 1970-01-01
  • 2020-04-09
  • 1970-01-01
  • 2012-06-22
  • 2021-11-09
  • 2013-11-10
  • 2021-09-23
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多