我有一个Oracle表格表示父子关系,并且我想提高查找祖先记录的层次结构的查询性能。我与小数据集在这里测试,但真正的桌子大得多:具有分层关系的SQL查询中的性能问题
id name parent_id tagged
== ==== ========= ======
1 One null null
2 Two 1 1
3 Three 2 null
4 Four 3 null
5 Five null null
6 Six 5 1
7 Seven 6 null
8 Eight null null
9 Nine 8 null
PARENT_ID指回id在同一个表的外键关系。
我想编写一个查询,它返回每个叶子记录(那些没有后代的记录...在这个例子中是id 4和id 7),它有一个祖先记录tagged = 1
(通过parent_id关系回溯) 。
因此,对于上面的源数据,我想我的查询返回:
id name tagged_ancestor_id
== ==== ==================
4 Four 2
7 Seven 6
我目前的查询检索这些记录是:
select * from (
select id,
name,
connect_by_root id tagged_ancestor_id
from mytree
connect by prior id = parent_id
start with tagged is not null
) m1
where not exists (
select * from mytree m2 where m2.parent_id = m1.id
)
此查询工作正常在这个简单的小例如表格,但是在我的真实表格上它的表现非常糟糕,它有大约1100万条记录。查询需要一分钟才能运行。
connect by
子句中的两个字段都有索引。start with
子句中的“tagged”字段也有一个索引,我的表中有大约1,500,000条记录,在这个字段中有非空值。where
子句似乎不是问题,因为修改它以使用where name = 'somename'
而不是where not exists ...
返回特定名称(也是索引的)时,查询仍然需要大约相同的时间量。
那么,我可以使用什么策略来尝试使这些层次结构上的查询运行得更快?
如果您可以修改模式,则可以重新构建它以存储修改的预定义树遍历,但是需要添加2个附加列(左侧和右侧值)。几年前,我在一个我现在无法找到的教程中成功完成了这个任务。 (你应该得到一些额外的性能,但需要花费空间 – ozborn
我确实可以控制模式,因此如果增加一些列是最好的方法来改善这种性能,那么就可以了。我想我可以把一个标记为祖先在自己的领域,并做到这一点,但似乎这个查询可以做得更快。 –
这里是适当的维基百科参考:https://en.wikipedia.org/wiki/Nested_set_model我不知道我明白在其自己的领域藏匿一个标记的祖先会帮助你(除非你存储所有这些?),但我可能不理解你的问题...? – ozborn