Страница 1 из 1
Ускорение "дервьев"
Добавлено: 12 май 2006, 15:41
Zhur
Уважаемый Дмитрий.
Внимательно ознакомился со статьями о деревьях.
Решил использовать вариант, когда корневой узел имеет PARENT=ID, так как FK есть очень мощная штука, от которой отказываться я не могу.
Так же я сделал и компонентик для такого рода деревьев.
А проблемка следующая:
Как, в таком случае вытаскивать корневые узлы?
Если написать
то в плане такого запроса появляется NATURAL. Но ведь у меня в дереве 700000 узлов. Это недопустимо.
Может кто поможет ускорить такую выборку.
Добавлено: 12 май 2006, 15:53
kdv
Как, в таком случае вытаскивать корневые узлы?
дерево, как таковое, не может иметь "корней" в произвольных местах. Например, страничное B-дерево, на котором построены индексы в IB/FB, всегда имеет ОДНУ Root Page, на которой располагаются корневые элементы ключей индекса.
Соответственно, в имитации дерева корневые элементы должны иметь PARENT = 0 (или NULL).
скажем так, или я не совсем понял вопрос,

или НИ ОДИН элемент дерева не может иметь ID = PARENT.
PARENT - это ссылка на родителя. элемент не может быть сам себе родителем.
По поводу FK на PARENT->ID я в статье высказывался, аргументы не убедили?
Добавлено: 12 май 2006, 16:51
Zhur
Уважаемый Дмитрий.
Из второй статьи цитирую:
"Единственным пока заслуживающим внимания замечанием к первой части статьи является уточнение по поводу вторичного ключа, создаваемого по полю PARENT. Действительно, для корневых элементов можно создавать записи с PARENT=ID, при этом "исключая" возникновение ошибки нарушения вторичного ключа. Полезным свойством FOREIGN KEY в этом случае является то, что невозможно создать PARENT с несуществующим значением ID. Однако такой способ обхода проблемы отсутствия "родоначальника" не является лучшим. Поэтому при реализации вам придется ориентироваться на тот вариант, который больше подходит для вашего случая."
Именно этот абзац меня и подкупил. А теперь вышекуазанный запрос хочу ка-нибудь ускорить.
Добавлено: 12 май 2006, 17:11
kdv
имелось в виду не равенство столбцов PARENT и ID у одной записи, а равенство PARENT какому-либо "вышестоящему" в дереве ID.
соответственно, дерево запросом
select * from tree where parent=id
вытащить невозможно, потому что таких записей ПРОСТО НЕ ДОЛЖНО СУЩЕСТВОВАТЬ.
если сильно хочется FK между PARENT и ID,
то столбец PARENT нужно указывать как допускающий NULL (не not null),
и соответственно корневые записи делать
ID PARENT
1 null
2 null
и т.д.
Добавлено: 12 май 2006, 17:52
Zhur
Понятно... тогда получается, что я этот абзац не так понял.
Хотя... черным по белому написано так:
"Действительно, для корневых элементов можно создавать записи с PARENT=ID"
Может стоит немного подправить это предложение? Хотя, если у корневой записи PARENT=ID, то это получается не логично, но является маленькой хитростью. В смысле, мы избавляемся от NULL, и не теряем FK. Правда корневые элементы долго выбирать.
Дмитрий, а почему, по Вашему мнению, не желательно использовать Parent не NOT NULL? Разве кроме небольшого усложнения математики это может привести к проблемам?
Добавлено: 12 май 2006, 19:10
kdv
Понятно... тогда получается, что я этот абзац не так понял.
да, мутновато там было написано, я надеюсь, что переписал начало второй статьи на более понятный вариант.
насчет корневой записи с PARENT = ID. Допустим, можно создать ОДНУ такую запись, где ID = 0 и PARENT = 0. Но тогда запросом
select * from objects where parent = 0 мы вытащим не только все корневые элементы, но и эту "центральную" запись. Тогда придется добавить
select * from objects where parent = 0 and id > 0, но в этом случае "зацепится" индекс по первичному ключу. Совсем решить эту проблему можно разве что запросом
select * from objects where parent = 0 and id+0 > 0
тогда "обобщенный" запрос для вытаскивания любого уровня дерева будет
select * from objects where parent = :param and id+0 > 0
почему, по Вашему мнению, не желательно использовать Parent не NOT NULL?
я очень сильно не люблю код, который "первые" элементы выбирает по одному условию, а остальные - по другому. В поправленном варианте статьи я это указал (where parent is null и where parent = :param). Отсюда и нелюбовь к null. Не упоминая, конечно, факт, что null нужно использовать только осознанно и по реальной необходимости, понимая 3-значную логику целиком и полностью.
кстати, лениво мне проверять, но что-то я не уверен, что запись с parent = 0 и id = 0 добавится в пустую таблицу с FK parent->id....
Добавлено: 15 май 2006, 15:03
Zhur
kdv писал(а):Спасибо, Дмитрий, за исчерпывающий ответ.