【问题标题】:postgres index not used未使用 postgres 索引
【发布时间】:2016-10-21 12:09:19
【问题描述】:

Postgres 9.5

我有一张表,其中包含 jsonb 列之一;

CREATE TABLE public.test
(
  objectstate jsonb
)

并对其进行索引:

CREATE INDEX "test.type"
  ON public.test
  USING btree
  ((objectstate ->> 'type'::text) COLLATE pg_catalog."default");

我也有返回依赖类型的函数……它更复杂,所以我举个例子……

CREATE OR REPLACE FUNCTION testfunc(sxtype text)
  RETURNS text AS
$BODY$
BEGIN
  return '{type1, type2}';
END;
  $BODY$
  LANGUAGE plpgsql VOLATILE
  COST 100;

现在我得到了什么:

select testfunc('type1') 给我'{type1, type2}'

下一个语法运行良好,并且使用索引:

  select * from test where objectstate->>'type' = ANY('{type1, type2}'::text[])

但是一旦我尝试将它们组合起来,索引就不会使用

select * from test 
where objectstate->>'type' = ANY((select testfunc('type1'))::text[])

奇怪的是下一个查询再次使用语法! (但我不能在任何地方都使用这种解决方法)

select * from test 
where objectstate->>'type' = ANY((select testfunc('type1'))::text[]) 
order by objectstate->>'type'

解释分析给了我:

"Seq Scan on test  (cost=0.26..530872.27 rows=2238634 width=743) (actual time=1107.155..7992.825 rows=129 loops=1)"
"  Filter: ((test ->> 'type'::text) = ANY (($0)::text[]))"
"  Rows Removed by Filter: 4063727"
"  InitPlan 1 (returns $0)"
"    ->  Result  (cost=0.00..0.26 rows=1 width=0) (actual time=0.718..0.718 rows=1 loops=1)"
"Planning time: 0.319 ms"
"Execution time: 7992.870 ms"

以及何时应用订单:

"Index Scan using "test.type" on test  (cost=0.70..545058.44 rows=2238634 width=743) (actual time=0.645..0.740 rows=129 loops=1)"
"  Index Cond: ((objectstate ->> 'type'::text) = ANY (($0)::text[]))"
"  InitPlan 1 (returns $0)"
"    ->  Result  (cost=0.00..0.26 rows=1 width=0) (actual time=0.617..0.617 rows=1 loops=1)"
"Planning time: 0.300 ms"
"Execution time: 0.782 ms"

任何想法如何强制 postgres 在不应用 order by 的情况下使用索引?

【问题讨论】:

    标签: postgresql indexing


    【解决方案1】:

    可能不是答案,但似乎您可以将函数定义从 VOLATILE 更改为 IMMUTABLE

    CREATE OR REPLACE FUNCTION testfunc(sxtype text)
      RETURNS text AS
    $BODY$
    BEGIN
      return '{type1, type2}';
    END;
      $BODY$
      LANGUAGE plpgsql IMMUTABLE
      COST 100;
    

    使用 VOLATILE 函数 Postgres 不会应用优化,因为 VOLATILE 函数可能会更改数据并且函数的结果是不可预测的。更多文档https://www.postgresql.org/docs/9.5/static/sql-createfunction.html

    【讨论】:

    • 看来我找到了你的提示的解决方案..... select * from test where objectstate->>'type' = ANY(testfunc2('system-protodefinition')::text[] ) 使用索引.....谢谢!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多