代码之家  ›  专栏  ›  技术社区  ›  Churkin Anton

“fdw\U redis”扫描所有redis记录,而不是单次查询

  •  2
  • Churkin Anton  · 技术社区  · 7 年前

    我无法通过Redis转换信息->Postgresql 9.6

    我正在使用分机 fdw_redis 我和hiredis创建了外部表redis\u db0\u ch。

    当我进行简单查询时

    select "key", value from redis_db0_ch where "key"='Ch_152';
    

    使用“cli redis monitor”,我发现一切正常:对于1个sql查询,只需对redis进行一次qual

    “ZRANGE”“Ch\u 152”“0”“-1”

    但当我将sql查询包装到带有输入参数的函数中时:

    CREATE OR REPLACE FUNCTION "SMSCEngine".f_get_redis_test(input_param integer)
    RETURNS TABLE(_key text, _value text)
    LANGUAGE plpgsql
    AS $function$
    begin
    return query 
        select "key", value from redis_db0_ch where "key"='Ch_' || input_param;
    end;
    $function$
    

    sql查询变成:

    select * from "SMSCEngine".f_get_redis_test(152);
    

    “cli redis monitor”中的结果控制过度:5次都正常,但随后它开始扫描所有redis记录,忽略我的筛选器(其中“key”=“Ch\u”)

    “ZRANGE”“Ch\u 152”“0”“-1”//5次

    “扫描”“0”“匹配”“Ch\u*”“COUNT”“1000”//from 6次

    因此,会降低性能。 我猜这是postgres或extension中的优化方法。 我怎样才能修复它?

    1 回复  |  直到 5 年前
        1
  •  0
  •   Nick Barnes    7 年前

    这看起来像是 PL/pgSQL plan caching . 你是对的,这应该是一种优化技术,但正如你所看到的,它偶尔会做出一些相当可疑的决定。

    通常,可以通过以下方式运行查询来抑制此行为: EXECUTE ,这将迫使PL/pgSQL每次都重新规划它:

    CREATE OR REPLACE FUNCTION "SMSCEngine".f_get_redis_test(input_param integer)
    RETURNS TABLE(_key text, _value text)
    LANGUAGE plpgsql
    AS $function$
    begin
    return query
        execute 'select "key", value from redis_db0_ch where "key" = $1'
        using 'Ch_' || input_param;
    end;
    $function$
    

    然而,如果您的函数只是一个查询,那么可能根本不需要PL/pgSQL;你可以把它写进去 LANGUAGE sql ,据我所知,它没有这个问题:

    CREATE OR REPLACE FUNCTION "SMSCEngine".f_get_redis_test(input_param integer)
    RETURNS TABLE(_key text, _value text)
    LANGUAGE sql
    AS $function$
      select "key", value from redis_db0_ch where "key" = 'Ch_' || input_param
    $function$