Postgres在递归CTE中没有利用索引(jsonb)

时间:2016-01-07 12:42:56

标签: sql json postgresql common-table-expression

我的表中有一个JsonB字段,它包含分层信息。 MyTable(id uuid,索引jsonb,内容bytea)

现在如果我创建一个CTE说

WITH RECURSIVE hierarchy(pid, id, content) AS (
  --load first parents
  SELECT t.indexes ->> 'parentId' as pId, t.id, t.content FROM MyTable c
  JOIN MyTable t ON t.indexes ->> 'Id' = c.indexes ->> 'parentId' 
  WHERE c.Id = ANY('{..Some UUIDS}')
  UNION
  SELECT t.indexes ->> 'parentId' as pId, t.id, t.content
  FROM hierarchy h, MyTable t
  WHERE t.indexes ->> 'Id' = h.pid
) SELECT id, content from hierarchy

现在,从300K记录表中的2个节点构建父树的示例运行大约需要10秒。

现在,如果我创建一个索引

CREATE INDEX MyIndex ON MyTable
USING btree
((indexes ->> 'parentId')

这将时间缩短到4.5秒。

我找到了一种方法来包装SELECT t.indexes - >> 'parentId'在一个函数中然后引用CTE和索引中的函数。这大大减少了运行时间到0.01秒。不幸的是,该函数必须标记为IMMUTABLE,如果索引值发生更改,或者添加了新行,则索引不会更新。

我在这里错过了一个选项来帮助cte识别初始索引,还是我必须设置触发器来重建更改函数索引?

对json值索引的分析表明,recusive部分使用带有索引扫描和排序的合并连接。与不可变函数索引一样,有一个带有工作表扫描和索引扫描的嵌套循环。没有......

联合部分的指数函数分析

          ->  Nested Loop  (cost=0.42..371393.38 rows=8079403 width=1219) (actual time=0.012..0.013 rows=1 loops=5)
                Output: (t_1.indexes ->> 'parentId'::text), t_1.id, t_1.content
                ->  WorkTable Scan on hierarchy h  (cost=0.00..179.80 rows=8990 width=32) (actual time=0.000..0.000 rows=1 loops=5)
                      Output: h.pid, h.id, h.content
                ->  Index Scan using "MyFunctionIndex" on "TEST"."MyTable" t_1  (cost=0.42..30.06 rows=899 width=1219) (actual time=0.010..0.010 rows=1 loops=5)
                      Output: t_1.id, t_1.content, t_1.indexes
                      Index Cond: ("TEST"."MyFunction"(t_1.id) = h.pid)

联合部分的指数分析

          ->  Merge Join  (cost=770.60..290937.50 rows=8079403 width=1219) (actual time=360.467..360.476 rows=1 loops=5)
                Output: (t_1.indexes ->> 'parentId'::text), t_1.id, t_1.content
                Merge Cond: ((t_1.indexes ->> 'Id'::text) = h.pid)
                ->  Index Scan using "MyIndex" on "TEST"."MyTable" t_1  (cost=0.42..127680.55 rows=179742 width=1219) (actual time=0.019..288.168 rows=60478 loops=5)
                      Output: t_1.id, t_1.sourceid, t_1.content, t_1.indexes
                ->  Sort  (cost=770.18..792.65 rows=8990 width=32) (actual time=0.010..0.011 rows=1 loops=5)
                      Output: h.pid
                      Sort Key: h.pid
                      Sort Method: quicksort  Memory: 25kB
                      ->  WorkTable Scan on hierarchy h  (cost=0.00..179.80 rows=8990 width=32) (actual time=0.001..0.001 rows=1 loops=5)
                            Output: h.pid

0 个答案:

没有答案