Как стать автором
Обновить

Комментарии 26

А в чем собственно преимущества перед вложенными множествами/интервалами?
При вставке не нужно пересчитывать всё «правое дерево», затрагиваются только ветки непосредственно переносящиеся.
Можно навесить на уже существующий AL.
Проще для понимания и проверки «на глаз».
Насчет первого пункта — во вложенных интервалах необходимости пересчитывать все «правое дерево» вроде как нету. Там другие беды, но не значительные.
В моей сфере применения способ я выбираю исходя из удобства и прозрачности для меня, а не способности вытаскивать критические нагрузки, т.к. сайты в основном слабо\средне нагруженные.
NS на чистом SQL довольно сложен, а хранимые процедуры на хостинге часто не поддерживаются.

AL даже при скриптовой обвязке в том же PHP прост как тапок, но хотелось как то «закешировать» результаты выборок.

Как доп. причину могу привести еще интересную статью по производительности NS и всех остальных. Думаю в моей реализации AL будет лишен многих недостатков.
А можно пример — какой хостер не поддерживает хранимые процедуры. Я правильно понимаю что это возможно только в том случае, когда MySQL старше 5-й версии?
В последнее время все клиентские и свои сайты держу на nic.ru
У них не поддерживается.
Я могу ошибаться, но для иерархических структур проще и удобнее использовать Nested Sets.
Хотя в случае частых изменений, производительность начинает хромать (по личному опыту).
Господа минусующие, объясните, пожалуйста, что я написал неверно?

Статья по хранению иерархических структур в реляционных БД.
По личному опыту, лучше всего подходит Nested Sets.
В чём я не прав? Объясните, прошу, а то ведь я и дальше буду ошибаться. А если вы не желаете помочь человеку исправиться, то в чём смысл оценивать его мнение?
Я не минусовал но всё же.

Первый комментатор спрашивал про те же Nested sets и было обсуждение чем, как и что лучше.
Да и в целом, зачем в статье о холодильниках писать безотносительно применения, что микроволновки лучше?
Поясните, пожалуйста, не совсем понял про «безотносительно применения».

Вы имеете в виду, что я не описал, почему для разогрева пищи микроволновка лучше, чем холодильник?
Т.е. чем именно NestedSets лучше, в каких случаях стоит использовать эту схему?

Если это так, то я написал — для частых изменений этот метод не лучший, т.к. постоянные обновления всего дерева снижают производительность, но чтение — напротив, очень выгодно, особенно если нужные выборки различного уровня (вся ветка, какие-то конкретные ноды и т.п.).

Я поясню ход своих мыслей по первому комментарию:
1. Я прочитал статью.
2. На мой взгляд, выбранный метод не оптимальный для хранения иерархии, особенно в случае преобладающего чтения.
3. Я решил предложить автору другой способ, которым лично пользовался и имею какой-то опыт (чтобы подсказать в случае возникновения каких-либо проблем).
4. Тем не менее, учитывая то, что данным вопросом не занимался уже полгода, написал, что я могу ошибаться (надеясь, что если это так, то мне подскажут, в чём я ошибаюсь).

Неужели это не правильно?

И в статье про холодильники нельзя упоминать другую бытовую технику, даже если она более оптимальна для целей, которые преследуются в статье?
Или моя ошибка в том, что я написал не в ту ветку?
Если внимательно прочитать первый абзац статьи, то можно понять, что автор знает что такое NS и по некоторой причине решил его не использовать, а поискать другие варианты. И впоследствии решил поделиться с общественностью.

«Безотносительно применения» — подразумевается, что в некоторых случаях NS абсолютно категорически непоправимо лучше, но чтобы оперировать некоторыми вещами нужно понимать где и как предполагается его использовать. Просто говорить что он абстрактно лучше в вакууме провоцирует на срач адептов разных религий.
Спасибо.
Всё понял, уяснил, впредь не буду повторять эту ошибку.

И извиняюсь, за некорректные комментарии.
Знаете что? Мне не нравится ваша модель. Но это скорее всего моя проблема — мне не нравится ни одна из моделей хранения иерархических структур в реляционных БД. ( Мне не нравится этот корабль, мне не нравятся эти матросы, мне вообще ничего не нравится!)
Чуть меньше остальных лично мне не нравится структура Nested Sets. С ней действительно «непонятно» работать руками. И не нужно! Я заставил ее работать через Zend_Db_Tree. Где-то здесь видел реализацию от Doctrine.

Да, кстати, Вы забыли упомянуть что внешние ключи (а вернее, каскадное удаление по внешнему ключу) в MySQL срабатывают только при engine=«InnoDB». Как минимум, это потеря полнотекстовых индексов.

И еще: добавление такой таблицы — это денормализация базы, что не всегда есть хорошо. Делай хорошо, а плохо само получится!
Если рассматривать класс для работы как черный ящик — хрен его знает что там внутри, лишь бы работало, то абсолютно неважно какую схему использовать — реализации есть подо всё.

Кому то нравятся холодильники с морозильной камерой внизу, а кому то наоборот. А кому то и холодильники вовсе не нравятся…
Мне всегда казалось, что аналогии лживы в IT не нужны — намного проще разобраться на примере обсуждаемых вещей, чем бросаться фразами вроде «Кто-то любит Любу, а по небу облака».

Вы наверное холодильник покупаете?
И да, как работает используемый мной класс я знаю на 110%, потому как допиливал его самостоятельно.
добавление такой таблицы — это денормализация базы, что не всегда есть хорошо

На это можно взглянуть по-другому: AL считаем основной таблицей, а МР — кэшем, который периодически перестраивается по данным AL. Вы ведь не станете утверждать что кэш (а это всегда дублирование информации) это плохо?
Кеш — это просто замечательно, кеш — это правильная денормализация. Но тогда необходимо выполнить еще несколько телодвижений
Таблицу в heap.
Для каждой записи указать expires.
Таблицу пересчитывать на лету.

И, естественно, для каждого телодвижения перепроверить — не дорогой ли кеш получится?
Expires тут не имеет смысла, т.к. он не протухнет пока не будут внесены изменения.

Что значит «пересчитывать на лету»? Кеш обновляется при изменениях, которые относительно редки.
>> добавление такой таблицы — это денормализация базы, что не всегда есть хорошо. Делай хорошо, а плохо само получится!
Очень, очень спорный тезис.

Бездумная нормализация так же плоха как бездумная денормализация. В общем случае нельзя сказать что если структура соответствует xNF, то она хороша. Это расхожее заблуждение, вызванное следованиям практикам, без понимания причин, эти практики обуславливающих.

Нормализация предназначена лишь для упрощения контроля целостности данных — не более, не менее. Денормализация структуры усложняет этот контроль, требует предприятия дополнительного комплекса мер, но может в значительной степени увеличить эффективность использования.
Абсолютно с Вами согласен!
У меня просто очередная «детская травма» — я на данный момент работаю над проектом, в котором под лозунгом «MySQL — это не реляционная СУБД» все таблицы необоснованно денормализованы (никто не проводил никакого профайлинга). И тем не менее, запросы остаются сложными, имеют вложенные подзапросы и несколько JOIN. А проект получился плохо расширяемым и поддерживаемым.

Параллельно второй проект (намного более нагруженный) с нормализованной базой (форму не скажу, но дублирования связей я все-таки избежал) и аккуратно проставленными индексами крутится себе и горя не знает. Расширяется и поддерживается легко и приятно.

Именно поэтому для меня лично необоснованная денормализация вызывает внутренний протест
оптимизировать время выполнения общей индексации

я бы предложил во время пересчета таблицы добавлять не по одной строке, а блоком по 20-100 строк. Где-то я читал, что в этом случае индексы пересчитываются чуть быстрее. Массив для вставки придется накапливать в памяти, но мне кажется он не очень тяжелый. Как альтернатива — можно отключать индексы (сам не пробовал, только читал)

Еще я бы внимательно пересмотрел индексы таблицы `pages_paths`.
1. Ключ `item_id_i` такой как он есть сейчас не нужен — MySQL прекрасно подхватит его из составного ключа `item_id_u`
2. Ключ `parent_id_i` я бы сделал составным (добавил поле item_id справа). Есть легенда, что в таком случае на некоторых сферических запросах в вакууме значения item_id при выборке будут браться прямо из ключа.
3. Почему Вы не проиндексировали поля, используемые для сортировок?

Естественно, вся эта оптимизация должна идти под постоянным контролем EXPLAIN на наиболее часто используемые запросы.

Да, и у Вашего решения есть 1 несомненный + — очень просто сделать выборку раскрытого по некоторой ветке иерархического дерева с сортировкой внутри уровня по названию page.title. В том же Nested Set, к примеру, приходится ручками перебирать.
Можно попробовать делать вставку разом, хотя не уверен что это даст сильный прирост по сравнению со вставкой уже подготовленного выражения. Нужно проверить.

Про отключение индексов я тоже читал, но изначально проводил все эксперименты вообще без индексов, так что не думаю что они сильно повлияют.

Насчет п.1 и п.2 не очень понял. Составной ключ вроде бы делается для поиска по всем входящим в него полям. Выборки из _paths будут идти либо по parent_id, либо по item_id. Уникальный ключ на три поля нужен для поддержки целостности.
Разве если прибить самостоятельные ключи parent_id и item_id общий уникальный ключ будет обеспечивать правильную индексацию обоих самостоятельных полей?

п.3 потому что забыл чтобы не усложнять наглядность.

А что мешает в случае с NS сделать вложенный запрос с выборкой и из неё уже высортировывать нужные порядки? что то типа SELECT * FROM (SELECT takoi VERY slozhnii select) t1 ORDER BY t1.title?
Составной ключ вроде бы делается для поиска по всем входящим в него полям.

Не совсем так. Здесь сказано:

MySQL использует многостолбцовые индексы таким образом, что запросы выполняются быстро, когда указывается известная часть для первого столбца в индексе в выражении WHERE, даже если не заданы величины для других столбцов.

Где-то я читал, что это справедливо не только для 1 столбца, но для любого количества первых (левых) столбцов индекса. Т.е. составной индекс на три поля a,b,c может использоваться на запросах WHERE a=:a, WHERE a=:a AND b=:b еtс. Но не может быть использован на запросах WHERE c=:c

Это значит, что ключ parent_id_i прибивать нельзя ни в коем случае! Я наоборот предложил его расширить. Но это нужно перепроверять — достаточно ли сферичны Ваши запросы, чтобы это имело смысл

По поводу сортировки по tiltle для NS — использовать такой запрос мешает:
— поломанная сортировка по leftKey — условие для вывода развернутого дерева (там же рекурсия, ёпт :)
— отсутствие уверенности, что MySQL обработает такие вложенные запросы быстрее, чем php отсортирует массив
Да и зачем здесь вообще вложенный запрос? только ради сортировки? так ее можно было бы указать и во внутреннем запросе. Но все равно, на выводящую функцию данные должны выводиться отсортированные по leftKey, иначе дерево за один проход не построишь
SELECT takoi VERY slozhnii select

если грубо — то SELECT * FROM tree WHERE leftKey > :lk AND rightKey < :rk ORDER BY leftKey
Да, индекс a,b,c также не будет использован при запросе типа WHERE b=:b.
А вообще — не надо меня слушать и верить мне. А надо почитать маны MySQL по индексам.
Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации

Истории