У меня в настоящее время есть таблица закрытия, используемая для иерархических данных, которая имеет 5 миллионов узлов, что приводит к ~ 75 миллионам строк в таблице закрытия.При использовании 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;
20 минутслишком долго, сейчас я сохраняю bool, если узел является корнем, и изменяю столбец Nodes
. Root
, когда узел перемещается. Я не совсем доволен дублирующимися данными, но моим временем запросатеперь для каждого запроса используются однозначные миллисекунды.
У меня также есть много запросов, требующих знания количества потомков в данном узле (в основном, если потомки> 1, чтобы знать, можно ли виртуализировать этот объект /развернуто в виде дерева).Раньше я делал запросы каждый раз, когда мне это было нужно, но по гигантской базе данных, как у меня, даже с индексами, запросы, казалось, занимали много времени (более 1 секунды), поэтому я также сократил их до столбца Nodes
. Descendants
, которыйЯ также обновляю каждый раз, когда узел перемещается.К сожалению, это еще одно дублирование данных, которое я хотел бы избежать.
Я использовал следующий запрос, как показано ниже.Если кто-нибудь может объяснить, как повысить производительность этого (учитывая, что у меня уже есть индекс, начинающийся с Ancestor), я был бы признателен.
SELECT COUNT(*) FROM `Closure` WHERE `Ancestor`=@Node