我将分层数据存储在表中。当通过其分层路径(grantParent/parent/resource)访问资源时,我需要使用 CONNECT BY 查询来定位资源。
注意:SQL 命令是从 EnterpriseDB 导出的,但它也应该在 Oracle 中工作。
表结构:
CREATE TABLE resource_hierarchy
(
resource_id character varying(100) NOT NULL,
resource_type integer NOT NULL,
resource_name character varying(100),
parent_id character varying(100)
)
WITH (
OIDS=FALSE
);
数据:
INSERT INTO "resource_hierarchy" (resource_id,resource_type,resource_name,parent_id) VALUES ('36d27991', 3, 'areaName', 'a616f392');
INSERT INTO "resource_hierarchy" (resource_id,resource_type,resource_name,parent_id) VALUES ('a616f392', 3, 'townName', 'fcc1ebb7');
INSERT INTO "resource_hierarchy" (resource_id,resource_type,resource_name,parent_id) VALUES ('fcc1ebb7', 2, 'stateName', '8369cc88');
INSERT INTO "resource_hierarchy" (resource_id,resource_type,resource_name,parent_id) VALUES ('8369cc88', 5, 'countryName', null);
现在,当我收到类似的路径时
countryName/stateName/townName/areaName
我正在执行一个查询,例如,
select LEVEL,* from resource_hierarchy
WHERE resource_name = (
CASE LEVEL
WHEN 1 THEN 'areaName'
WHEN 2 THEN 'townName'
WHEN 3 THEN 'stateName'
WHEN 4 THEN 'countryName'
ELSE ''
END
)
connect by prior parent_id = resource_id
start with resource_name = 'areaName';
我的预期结果是:
LEVEL resource_id resource_type resource_name parent_id
-------------------------------------------------------------
1 36d27991 3 areaName a616f392
2 a616f392 3 townName fcc1ebb7
3 fcc1ebb7 2 stateName 8369cc88
4 8369cc88 5 countryName <null>
这个查询工作正常,但我不确定它是否会运行得更快,当我的表很大时,有数十万个条目。
你能根据我的要求优化这个查询吗?
编辑:
对上述查询的解释:我定义了两个索引 - 一个在 resource_id(主键)上,另一个在 parent_id
Sort (cost=66.85..66.86 rows=1 width=694)
Sort Key: connectby_cte.siblingssortcol
CTE prior
-> Recursive Union (cost=0.00..65.83 rows=31 width=151)
-> WindowAgg (cost=0.00..3.12 rows=1 width=83)
-> Seq Scan on resource_hierarchy (cost=0.00..3.11 rows=1 width=83)
Filter: ((resource_name)::text = 'areaName'::text)
-> WindowAgg (cost=0.33..6.21 rows=3 width=151)
-> Hash Join (cost=0.33..6.15 rows=3 width=151)
Hash Cond: ((resource_hierarchy_1.resource_id)::text = (prior.parent_id)::text)
Join Filter: connectby_cyclecheck(prior.recursionpath, (resource_hierarchy_1.parent_id)::text)
-> Seq Scan on resource_hierarchy resource_hierarchy_1 (cost=0.00..2.89 rows=89 width=83)
-> Hash (cost=0.20..0.20 rows=10 width=286)
-> WorkTable Scan on prior (cost=0.00..0.20 rows=10 width=286)
-> CTE Scan on prior connectby_cte (cost=0.00..1.01 rows=1 width=694)
Filter: ((resource_name)::text = CASE level WHEN 1 THEN 'areaName'::text WHEN 2 THEN 'townName'::text WHEN 3 THEN 'stateName'::text WHEN 4 THEN 'countryName'::text ELSE ''::text END)