我的表中有一个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