【发布时间】:2015-12-21 20:47:07
【问题描述】:
我有一个表示父子关系的 Oracle 表,我想提高在层次结构中搜索祖先记录的查询的性能。我在这里用小数据集进行测试,虽然实际表要大得多:
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
)
这个查询在这个简单的小示例表上运行良好,但在我的真实表上它的性能很糟糕,它有大约 11,000,000 条记录。查询需要一分钟多的时间才能运行。
-
connect by子句中的两个字段都有索引。 -
start with子句中的“tagged”字段也有索引,我的表中大约有 1,500,000 条记录,该字段中的值为非空值。 -
where子句似乎不是问题,因为当修改它以使用where name = 'somename'而不是where not exists ...返回特定名称(也被索引)时,查询仍然需要大约相同的时间.
那么,我可以使用哪些策略来尝试使此层次结构上的这些类型查询运行得更快?
【问题讨论】:
-
如果您可以修改您的架构,您可以重建它以存储修改后的前序树遍历,但您需要添加 2 个额外的列(左值和右值)。几年前,我按照我目前找不到的教程在 mysql 中成功地做到了这一点。 :( 你应该以空间为代价获得一些额外的性能。
-
我确实可以控制架构,因此如果这是提高此性能的最佳方法,那么添加一些列就可以了。我想我可以将一个标记的祖先存储在它自己的字段中并成为完成了,但似乎这个查询可以更快。
-
这里是适当的维基百科参考:en.wikipedia.org/wiki/Nested_set_model 我不确定我是否理解将一个标记的祖先存储在它自己的领域会如何帮助你(除非你存储所有它们?)但我是可能不明白你的问题...?
标签: sql oracle hierarchy connect-by