Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sqlite/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql 闭包表根节点查询性能(百万节点数为10秒)_Sql_Sqlite_Hierarchical Data - Fatal编程技术网

Sql 闭包表根节点查询性能(百万节点数为10秒)

Sql 闭包表根节点查询性能(百万节点数为10秒),sql,sqlite,hierarchical-data,Sql,Sqlite,Hierarchical Data,我目前有一个用于分层数据的闭包表,它有500万个节点,这导致闭包表中约7500万行。使用SqLite,由于闭包表的大小,我的查询时间呈指数增长 CREATE TABLE `Closure` (`Ancestor` INTEGER NOT NULL ,`Descendant` INTEGER NOT NULL ,`Depth` INTEGER, PRIMARY KEY (`Ancestor`,`Descendant`) ) CREATE INDEX `Closure_AncestorDescend

我目前有一个用于分层数据的闭包表,它有500万个节点,这导致闭包表中约7500万行。使用SqLite,由于闭包表的大小,我的查询时间呈指数增长

CREATE TABLE `Closure` (`Ancestor` INTEGER NOT NULL ,`Descendant` INTEGER NOT NULL ,`Depth` INTEGER, PRIMARY KEY (`Ancestor`,`Descendant`) )
CREATE INDEX `Closure_AncestorDescendant` ON `Closure` (`Ancestor` ASC, `Descendant` ASC);
CREATE INDEX `Closure_DescendantAncestor` ON `Closure` (`Descendant` ASC, `Ancestor` ASC);
CREATE TABLE `Nodes` (`Node` INTEGER PRIMARY KEY NOT NULL, `Root` BOOLEAN NOT NULL, `Descendants` INTEGER NOT NULL);
我的查询需要20分钟才能找到根节点,尽管只有5到6个节点满足查询要求

SELECT `Closure`.`Ancestor` FROM `Closure` 
LEFT OUTER JOIN `Closure` AS `Anc` ON `Anc`.`Descendant` = `Closure`.`Descendant` 
AND `Anc`.`Ancestor` <> `Closure`.`Ancestor` WHERE `Anc`.`Ancestor` IS NULL;

您正在开发的SQLite版本是否支持外键?如果是这样,那么闭包表设计应该有一个引用闭包表支持的层次结构表的FK。在TSQL中:

constraint fk_a FOREIGN KEY (ancestor) REFERENCES <hierarchy_tablename> (nodeid)
constraint fk_d FOREIGN KEY (descendant) REFERENCES <hierarchy_tablename> (nodeid)
不管闭包表有多大,它都会很快恢复。如果从中得到一个空集,那么给定的节点将无法再展开,因为它没有子节点。Exists在找到一个符合您的条件的实例时立即返回true,并且您只取前1,因此不会为传递的@Node的闭包表中的每一行返回一行

至于提高寻根性能,请尝试以下方法。这是我用来查找根的,但是我的闭包表只有~200000行。我比较了为每一个生成的计划,您的代码使用了一个散列,这可能会影响性能,因为设备上的处理器要求我在这里假设SQLite用于iPhone/iPad或设备上的某种小型发行版。下面使用更少的处理能力和对其计划中索引的更多读取,并利用层次结构与闭包表的关系。我不能肯定这会改善你的表现,但值得一试

select a.node_name, a.node_id
from test.hier a left outer join 
                 (select coo.descendant /* coo = CHILD OF OTHER */
                  from test.closure_tree coo right outer join test.closure_tree ro
                        on coo.ancestor <> ro.descendant /* ignore its self reference */
                        and coo.descendant = ro.descendant /* belongs to another node besides itself */)lo 
    on a.node_id = lo.descendant
where lo.descendant is null

闭包表的模式是什么?有索引吗?还有,你说的查找根节点是什么意思?对不起,这是一个输入错误。我的意思是找到根节点,它已经被纠正了。不管怎么说,我主要是重写了我的问题,因为我们知道了如何正确地编写索引,从而提高了除根查询和计数子体查询之外的每个查询的性能。外键似乎是个好主意,实际上我有一个平面表,其中列出了用于其他类型查找的所有节点,因此我可以将其外键关闭并使用该表进行删除。我喜欢你关于使用EXISTS的建议,下周将对其进行测试。SQLite不支持右外部联接,所以我们只是在节点的平面列表中添加了一个根列,并且由于它可以被索引,所以工作得非常好。
select top 1 'EXPANDABLE' as whatever
from closure C
where exists (select ancestor from closure where depth > 0 and ancestor = C.ancestor)
and ancestor = @Node
select a.node_name, a.node_id
from test.hier a left outer join 
                 (select coo.descendant /* coo = CHILD OF OTHER */
                  from test.closure_tree coo right outer join test.closure_tree ro
                        on coo.ancestor <> ro.descendant /* ignore its self reference */
                        and coo.descendant = ro.descendant /* belongs to another node besides itself */)lo 
    on a.node_id = lo.descendant
where lo.descendant is null