Комментарии 47
честно — а если переписать это с T-SQL на какой-нибудь нормальный язык, хотя бы на Java — не будет ли короче, понятнее и быстрее?
т.е. понятно, что потребуются какие-нибудь инфраструктурные изменения, но СУБД h2database.com, например, предлагает писать триггеры не на SQL, а на Java, в любой современной невероятно удобной IDE.
А если и само приложение вдруг на Java, то такая связка будет работать _удивительно_ быстро из-за отсутствия межпроцессного взаимодействия.
// Нисколько не хочу обидеть MySQL + PHP. Наоборот, поздравляю с новым оператором goto =)
А если и само приложение вдруг на Java, то такая связка будет работать _удивительно_ быстро из-за отсутствия межпроцессного взаимодействия.
// Нисколько не хочу обидеть MySQL + PHP. Наоборот, поздравляю с новым оператором goto =)
Немного не понимаю какое ограничение может наложить использование триггеров написаных на Java.
Не вижу никаких сложностей.
doc.prototypes.ru/database/nestedsets/theory/
Есть определенная последовательность действий, которую я отработал еще 4 года назад.
А на каком уровне это реализовать и с помощью какого языка — вопрос исключительно религии разработчика ;-).
Не вижу никаких сложностей.
doc.prototypes.ru/database/nestedsets/theory/
Есть определенная последовательность действий, которую я отработал еще 4 года назад.
А на каком уровне это реализовать и с помощью какого языка — вопрос исключительно религии разработчика ;-).
Интересно при чем тут PHP?
Вопрос к автору (предыдущую статью не читал), а зачем этот гемор? По сути Nested Sets используется в тех случаях где изменения дерева происходят не часто, как по мне то использование триггеров в данном случае излишне…
Но за проделанную работу(код) спасибо, мало какие задачи встретятся…
Вопрос к автору (предыдущую статью не читал), а зачем этот гемор? По сути Nested Sets используется в тех случаях где изменения дерева происходят не часто, как по мне то использование триггеров в данном случае излишне…
Но за проделанную работу(код) спасибо, мало какие задачи встретятся…
Что лучше, держать этот геморрой у себя в приложении или прицепить этот триггер на таблицу в которой у нас дерево и забыть об этой болезни как о страшном сне?
Для уровня приложений у я использовал инструмент, который универсален для любой таблицы, но любая универсальность — это более сложная логика работы.
В триггере что я написал, подставляешь названия таблиц свои, названия полей, применяешь и забываешь.
Не представляешь как удобно теперь с таким деревом в консольке работать.
Для уровня приложений у я использовал инструмент, который универсален для любой таблицы, но любая универсальность — это более сложная логика работы.
В триггере что я написал, подставляешь названия таблиц свои, названия полей, применяешь и забываешь.
Не представляешь как удобно теперь с таким деревом в консольке работать.
На PHP NestedSets у меня заняло 25 строк. Ваше решение читать и понимать сложновато. Хотя некоторые преимущества, безусловно, присутствуют.
Вообще, я бы предложил таки посмотреть код и понять, что там происходит, но вкратце, объясню.
Большую часть кода триггер вычисляет координаты, т.к. решение смешанное, то в качестве конечной координаты может быть parent_id, как в рекурсивных деревьях, так и left_key для деревьев Nested Sets. Отсюда немного усложненная логика вычисления координат.
При известных координатах вообще-то достаточно двух запросов для каждого из действий. Причем для перемещения, реально выполняется только один запрос обновления, а два их только потому, что они разные для направления перемещения.
Большую часть кода триггер вычисляет координаты, т.к. решение смешанное, то в качестве конечной координаты может быть parent_id, как в рекурсивных деревьях, так и left_key для деревьев Nested Sets. Отсюда немного усложненная логика вычисления координат.
При известных координатах вообще-то достаточно двух запросов для каждого из действий. Причем для перемещения, реально выполняется только один запрос обновления, а два их только потому, что они разные для направления перемещения.
Ну написать один раз класс для работы с Nested Sets и потом использовать для любой таблицы…
Вопрос в том, что при использовании разных framework с разными «обертками» работы с БД этот класс придется постоянно перестраивать, если он будет участвовать в цепочке наследования или как плагин.
При работе с несколькими языками программирования — то же самое.
Еще раз повторюсь.
Я до недавнего времени использовал подобные классы как плагины, но я посчитал, что перевод этого алгоритма на более низкий уровень более оправдано, ввиду использования в работе новых технологий.
При работе с несколькими языками программирования — то же самое.
Еще раз повторюсь.
Я до недавнего времени использовал подобные классы как плагины, но я посчитал, что перевод этого алгоритма на более низкий уровень более оправдано, ввиду использования в работе новых технологий.
1. Короче не будет, понятнее будет еще меньше. Как раз цель в данном случае убрать вообще все непонятные действия с глаз долой, и работать без них.
2. Для Java решения нет, т.к. с ней не работал и надобности не было. Но есть решения для других языков:
Решение для Perl — phoinix.ucoz.ru/publ/5
Решение для PHP — phoinix.ucoz.ru/publ/6 (правда не до конца дописано, ввиду практической не надобности мне);
Была, конечно идея сделать модули не как додлнительный внешний инструментарий, а как встраиваемый, как прослойка интерфейсов («оберток») для работы с БД. Но таких «оберток» много больше и для каждой обертки делать решение — мягко скажем не рационально, а вот типов БД не так много, поэтому, ИМХО лучше эти вопросы решать на более низком уровне.
2. Для Java решения нет, т.к. с ней не работал и надобности не было. Но есть решения для других языков:
Решение для Perl — phoinix.ucoz.ru/publ/5
Решение для PHP — phoinix.ucoz.ru/publ/6 (правда не до конца дописано, ввиду практической не надобности мне);
Была, конечно идея сделать модули не как додлнительный внешний инструментарий, а как встраиваемый, как прослойка интерфейсов («оберток») для работы с БД. Но таких «оберток» много больше и для каждой обертки делать решение — мягко скажем не рационально, а вот типов БД не так много, поэтому, ИМХО лучше эти вопросы решать на более низком уровне.
Причем тут T-SQL?
Насколько я помню, T-SQL — процедурный диалект в MSSQL, то, что в MySQL, называется SQL/PSM, не?
Насколько я помню, T-SQL — процедурный диалект в MSSQL, то, что в MySQL, называется SQL/PSM, не?
Это ипостаси одной и той же сущности, так же как и PL/SQL.
Имеющие разный синтаксис и реализацию… и если уж написано на какойто конкретной ипостаси то нужно про нее и вести разговор… SQL/PSM это вродебы больше к PostgreSQL имеет отношение
Перед тем как писать хранимку стоит хорошо подумать, возможно решение на уровне приложения будет проще, и потери в скорости не будут критическими.
Через пять лет после имплементации nested sets я пришел к выводу, что реляционные базы данных плохо подходят для хранения иерархических структур. Кроме того, я ни разу не видел, реальной необходимости в nested sets, кроме как в академических задачах(более 500 уровней и миллионы узлов). Для всего остального хватит простого Adjacency List.
Как угробить очередной проект? Начните с реализации nested sets.
Как угробить очередной проект? Начните с реализации nested sets.
Да, если все-таки хочется выстрелить себе в ногу, то можно взять хотя бы алгоритм path enumeration. Все современные бд умеют оптимизировать запросы like.
Для postgres есть даже модуль специальный: www.sai.msu.su/~megera/postgres/gist/ltree/
Для postgres есть даже модуль специальный: www.sai.msu.su/~megera/postgres/gist/ltree/
Да даже like не нужен, если путь по колонкам распихать
«Достойное» решение.
Без комментариев.
Без комментариев.
Если не согласны, то уж постарайтесь аргументировать, а не только делать вид всезнающего.
Небольшая избыточность при распахивании пути по колонкам выдаёт большую скорость, так как поиск уже осуществляется по индексированным целочисленным полям, плюс ко всему появляются возможности работы с иерархией как в алгоритме NS. На практике глубина иерархии больше 10 редкость, вы либо создаёте 10 колонок, либо тратите процессорное время с вашим алгоритмом для NS. Всё же следует для каждой задачи применять соответствующее решение. За статью про NS спасибо, но его уже со всех сторон изжевали, хотелось бы увидеть что-то новое.
Небольшая избыточность при распахивании пути по колонкам выдаёт большую скорость, так как поиск уже осуществляется по индексированным целочисленным полям, плюс ко всему появляются возможности работы с иерархией как в алгоритме NS. На практике глубина иерархии больше 10 редкость, вы либо создаёте 10 колонок, либо тратите процессорное время с вашим алгоритмом для NS. Всё же следует для каждой задачи применять соответствующее решение. За статью про NS спасибо, но его уже со всех сторон изжевали, хотелось бы увидеть что-то новое.
Тут даже дело не только в cpu, а в том, что запросы с case/if/триггеры и прочими сложными вещами напрочь сносят возможные выигрыши от того, что все дерево выбирается сразу. На небольшом кол-ве уровней, это даже и медленнее, наверное.
А если добавить к Adjacency List кэширование, тогда у меня вообще ничего до базы не долетит.
Что в итоге?
Сложный алгоритм, непрозрачный код, ад в поддержке.
Я например, видел стопицот реализаций nested sets, но ни разу не видел unit tests на эти реализации.
А если добавить к Adjacency List кэширование, тогда у меня вообще ничего до базы не долетит.
Что в итоге?
Сложный алгоритм, непрозрачный код, ад в поддержке.
Я например, видел стопицот реализаций nested sets, но ни разу не видел unit tests на эти реализации.
p.s. Когда в пример приводят то, что многие операции в nested sets над деревом делаяются как o(1), то забывают что это важно только тогда, когда константные множители перестают играть роль.
Если вы не понимаете алгоритма, не используйте, я же вам его не навязываю.
> что запросы с case/if/триггеры и прочими сложными вещами напрочь сносят возможные выигрыши
Вот тут поподробней пожалуйста. Что сносит, в каких случаях и почему?
> что запросы с case/if/триггеры и прочими сложными вещами напрочь сносят возможные выигрыши
Вот тут поподробней пожалуйста. Что сносит, в каких случаях и почему?
Я писал реализацию этого дерева еще пять лет назад, в рамках дипломной работы в институте. И алгоритм я вспомню, если нужно, но я писал не об этом совершенно.
А о чем?
Я провожу сравнения?
Я проповедую новую религию?
Нет, я предлагаю готовую реализацию, для тех, кто использует данный алгоритм.
Вы то, что тут делаете?
Я провожу сравнения?
Я проповедую новую религию?
Нет, я предлагаю готовую реализацию, для тех, кто использует данный алгоритм.
Вы то, что тут делаете?
Ок. Хватит либеральничать :-) Ваш код никуда не годится из-за сложности поддержки, разработки и тестирования.
Сложность поддержки? Хм… если вы не будете менять поля используемые для Nested Sets, то вообще-то эти триггеры изменять не нужно.
Сложность разработки? Какой разработки?
Сложность тестирования? — Расхожее убеждение.
Вообще, если я использую в своих проектах этот алгоритм, то как минимум я знаю как он работает, если вы пять лет назад писали диплом на эту тему и не используете этот алгоритм в практике и не собираетесь, то вам этот код не годится. И что с того?
Сложность разработки? Какой разработки?
Сложность тестирования? — Расхожее убеждение.
Вообще, если я использую в своих проектах этот алгоритм, то как минимум я знаю как он работает, если вы пять лет назад писали диплом на эту тему и не используете этот алгоритм в практике и не собираетесь, то вам этот код не годится. И что с того?
У меня складывается чувство, что я своей статьей чем-то вас обидел, подорвал моральные устои.
Найдите пожалуйста, где я сказал, что Adjacency List — это говно, и не надо его никогда использовать, что LTree говно, или другие решения.
Единственно, на что я посетовал, так это на то что в MySQl реализация триггеров — говно, а MERGE иногда работает, мягко скажем, неадекватно.
Есть алгоритм Nested Sets, вот вам его реализация на уровне триггеров.
Кому надо — используйте, кому не надо, чего рассказывать о том, что это вам не понятно сложно и вообще говно.
А не провожу никаких сравнений, а вам лишь бы хуем померяться.
Диалог совершенно неконструктивен.
Найдите пожалуйста, где я сказал, что Adjacency List — это говно, и не надо его никогда использовать, что LTree говно, или другие решения.
Единственно, на что я посетовал, так это на то что в MySQl реализация триггеров — говно, а MERGE иногда работает, мягко скажем, неадекватно.
Есть алгоритм Nested Sets, вот вам его реализация на уровне триггеров.
Кому надо — используйте, кому не надо, чего рассказывать о том, что это вам не понятно сложно и вообще говно.
А не провожу никаких сравнений, а вам лишь бы хуем померяться.
Диалог совершенно неконструктивен.
Судя по тону, это я вас задел, а не наоборот :-) Я просто раскритиковал ваш код не с точки зрения самого кода, а с точки зрения его применимости и целеообразности вообще. Извините, что не приклонили колен перед великим изобретателем священного велосипеда! ^-)
Возможно и задели и не потому, что колен не преклонили.
А потому, что из-за того, что вы не понимаете алгоритма и никогда его не применяли, вы заранее утверждаете что это говно.
А потому, что из-за того, что вы не понимаете алгоритма и никогда его не применяли, вы заранее утверждаете что это говно.
Во-первых, применял. Потому что как в любом приличном институте диплом делается на реальную работу и у меня даже был акт внедрения. Использование же nested sets там было оправдано, потому что там было довольно большое дерево(не редко, более 10 уровней).
И тогда я не понимал, на самом деле того, о чем сейчас пишу, критикуя ваш подход. Теперь понимаю.
Во-вторых, по коду.
Вот вы можете если не написать, то хотя бы сформулировать набор критериев, который является достаточным для написания unit-test-ов, которое покроет ваше api?
(вопрос скорее риторический, так как unit test-ов на nested sets я не видел).
Кстати, а на чем их писать? :-)
global lock — отлично!
myisam only — да еще при такой сложной структуре, это crash и вы даже руками уже ничего не восстановите.
И тогда я не понимал, на самом деле того, о чем сейчас пишу, критикуя ваш подход. Теперь понимаю.
Во-вторых, по коду.
Вот вы можете если не написать, то хотя бы сформулировать набор критериев, который является достаточным для написания unit-test-ов, которое покроет ваше api?
(вопрос скорее риторический, так как unit test-ов на nested sets я не видел).
Кстати, а на чем их писать? :-)
global lock — отлично!
myisam only — да еще при такой сложной структуре, это crash и вы даже руками уже ничего не восстановите.
> так как unit test-ов на nested sets я не видел
— Ты видишь в поле суслика?
— Нет.
— Но тем не менее он там есть.
doc.prototypes.ru/database/nestedsets/theory/rules/
— Ты видишь в поле суслика?
— Нет.
— Но тем не менее он там есть.
doc.prototypes.ru/database/nestedsets/theory/rules/
Редкость не редкость, но когда у тебя 10 таких полей, и вдруг понадобилось еще 5, а в таблице уже более миллиона записей, и останавливать проект нельзя.
Как показывает практика, заведомое ограничение рано или поздно приводит к тому, что эти ограничения начинают существенно мешать.
Как показывает практика, заведомое ограничение рано или поздно приводит к тому, что эти ограничения начинают существенно мешать.
Понадобится — добавьте, для этого только ALTER сделать, а весь миллион записей не нужно инициализировать, установка значений только у добавляемых узлов будет происходить точно также, если бы добавление колонок не потребовалось.
Да и ещё раз говорю, для каждой задачи свой алгоритм и не надо делать из NS универсальное решение (судя по комментам) — он хорош только, когда требуется работать с очень глубокой иерархией и если её изменение — редкость. Но так получается, что веб движется в сторону абсолютной динамичности, данные постоянно обновляются, поэтому такое внимание к алгоритмам изменяющие данные. Как раз для этого и оказалось выгодней MP алгоритм реализовать с небольшой избыточностью, чтоб и изменение иерархии происходило быстро и поиск/чтение тоже.
Да и ещё раз говорю, для каждой задачи свой алгоритм и не надо делать из NS универсальное решение (судя по комментам) — он хорош только, когда требуется работать с очень глубокой иерархией и если её изменение — редкость. Но так получается, что веб движется в сторону абсолютной динамичности, данные постоянно обновляются, поэтому такое внимание к алгоритмам изменяющие данные. Как раз для этого и оказалось выгодней MP алгоритм реализовать с небольшой избыточностью, чтоб и изменение иерархии происходило быстро и поиск/чтение тоже.
Читаем статью еще раз. Вникаем в суть.
Я не предлагаю замены, я предлагаю расширение Nested Sets, что бы его можно было использовать как и Adjacency List.
Я не предлагаю замены, я предлагаю расширение Nested Sets, что бы его можно было использовать как и Adjacency List.
Вот ключевой момент всей дискусии. Никогда еще абстракция не добавляла надежности и устойчивости. Все абстракции «текут». Поэтому Nested Sets не будет обладать свойстами простоты и устойчивости Adjacency List. Теперь подумайте про myisam и «протечку» вашей абстракции, например.
Ну а что не так? Вам (да и мне) очень нравится как удобно в NS выборки делать и вы того же хотите добиться в управлении, так ведь? Вы скрыли логику в триггерах, но забыли главное — минимизировать нагрузку. Предложенный вами вариант не устраняет главного минуса NS.
> Я не предлагаю замены
А для чего статья? Кому она будет полезна, если этим не заменить другие алгоритмы? Не поленились бы хотябы написать, где это творение лучше всего использовать и привели бы сравнение с NS без триггеров.
Судя по всему вас в обще не интерисуют другие подходы. Как ещё объяснить резкую критику и сплошное минусование?
> Я не предлагаю замены
А для чего статья? Кому она будет полезна, если этим не заменить другие алгоритмы? Не поленились бы хотябы написать, где это творение лучше всего использовать и привели бы сравнение с NS без триггеров.
Судя по всему вас в обще не интерисуют другие подходы. Как ещё объяснить резкую критику и сплошное минусование?
а в postgres есть массивы))
А что используете вы, товарищ? Рекурсивные деревья?
PostgreSQL — тут не при чем, статья по нему по соседству.
ltree — не самое лучшее решение, особенно в части переноса веток, и подсчета.
PostgreSQL — тут не при чем, статья по нему по соседству.
ltree — не самое лучшее решение, особенно в части переноса веток, и подсчета.
Если речь идет о базе, то использую Adjacency List.
не совсем понял зачем поле tree и как с ним работать.
Зарегистрируйтесь на Хабре, чтобы оставить комментарий
Nested Sets + MySQL TRIGGER