MySQL - лучший метод для обработки этих иерархических данных?

StackOverflow https://stackoverflow.com/questions/3137674

  •  01-10-2019
  •  | 
  •  

Вопрос

Это следующее:
MySQL - можно ли получить все подпункты в иерархии?

У меня есть произвольная глубина Модель смещения соседних стол (я нахожусь в том смысле, что я могу преобразовать его в Вложенный установленный модель.

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

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


Прямо сейчас мне нужно иметь возможность вернуть список всех детей данного узла, изменить или удалять их. Эта иерархическая структура не будет изменяться все время после создания, но будет массовая сумма иерархических структур.

Три метода, которые я вижу:

  1. Создал сохраненную процедуру Что сделает рекурсивный запрос, который возвращает всех детей.

  2. Преобразовать в вложенную модель Который потребуется попасть в сложности и, возможно, создать сохраненную процедуру для добавления, редактирования и удаления в этом.

  3. Создайте таблицу предка описанный выше на вставке / удалении триггеров для обработки всех данных.

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

Это было полезно?

Решение

Квадра Запустил некоторые тесты производительности в модели вложенных множеств и модели списка соседних и документированных результатов и рекомендаций в своем блоге Список соседних против вложенных наборов: MySQL. Отказ Представительское резюме:

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

Вот заключение со своей статьи:

В MySQL модель вложенные наборы должны быть предпочтительными, если обновления иерархийской структуры нечастоны, и доступна для блокировки таблицы в течение длительности обновления (которая может занять минуты на длинном столе).

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

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

Это требует создания функции для запроса таблицы.

Остальная часть статьи показывает, как определить таблицу, внедрить запросы и дает измерения производительности. Использование пространственного индекса - это умная идея для улучшения производительности вложенной модели, которая может быть новой для вас.


Если вы также рассматриваете подходы без MySQL, тогда вы можете посмотреть на PostgreSQL Какая еще одна бесплатная база данных и открытая источника. PostgreSQL поддерживает рекурсивные запросы в виде Рекурсивное общие выражения таблицы которые делают запрос наширархических данных проще, чем в MySQL, а также дают лучшую производительность. Quassnoi также написал статью Список соседних против вложенных наборов: PostgreSQL это показывает детали.

Пока мы говорим о том, как смотреть на другие подходы, база данных Oracle стоит упомянуть. Oracle также имеет пользовательское расширение CONNECT BY которые делают запрос наширархических данных очень легко и быстро. Статья Quassnoi Список соседних против вложенных наборов: Oracle Снова охватывает детали производительности. Запрос, необходимый для того, чтобы все дети чрезвычайно просты в этом случае:

SELECT *
FROM yourtable
START WITH id = 42
CONNECT BY parent = PRIOR id

Другие советы

Я бы всегда пошел с Вложенный набор для простоты и обоснования сдвига. Я всегда предлагаю эта статья. Отказ Он показывает экскавацию запросов, которые необходимы для работы с такими иерахирхическими данными. Единственный недостаток, который я вижу, вот то, что он может становиться медленнее с вставкой / обновлением новых записей, когда иерахри достиг определенного уровня сложности, но чтение быстрее, чем многие другие решения, которые я видим.

Просто чтобы дать вам пример из статьи выше:

SELECT t1.name AS lev1, t2.name as lev2, t3.name as lev3, t4.name as lev4
FROM category AS t1
LEFT JOIN category AS t2 ON t2.parent = t1.category_id
LEFT JOIN category AS t3 ON t3.parent = t2.category_id
LEFT JOIN category AS t4 ON t4.parent = t3.category_id
WHERE t1.name = 'ELECTRONICS';

+-------------+----------------------+--------------+-------+
| lev1        | lev2                 | lev3         | lev4  |
+-------------+----------------------+--------------+-------+
| ELECTRONICS | TELEVISIONS          | TUBE         | NULL  |
| ELECTRONICS | TELEVISIONS          | LCD          | NULL  |
| ELECTRONICS | TELEVISIONS          | PLASMA       | NULL  |
| ELECTRONICS | PORTABLE ELECTRONICS | MP3 PLAYERS  | FLASH |
| ELECTRONICS | PORTABLE ELECTRONICS | CD PLAYERS   | NULL  |
| ELECTRONICS | PORTABLE ELECTRONICS | 2 WAY RADIOS | NULL  |
+-------------+----------------------+--------------+-------+
6 rows in set (0.00 sec)

SQL мудрый, я не думаю, что это может стать красивее и проще;)

Я понятия не имею в Хранимая процедура способ. Но так как он приводит рекурсию (в вашем случае), я не знаю, будет ли это быстро со многими уровнями в иерархии. Я предполагаю, что вы можете попробовать.

Может быть, вы должны рассмотреть возможность использования ориентированной на документацию базы данных, как Монгодб. Отказ Это может сделать вашу жизнь намного проще.

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

Поскольку клапаны памяти (Memcache, Redis, Etc) намного быстрее, чем SQL для простого id -> data Резолюции, я бы использовал их, чтобы кэшировать список идентификаторов прямых детей для каждого узла. Таким образом, вы можете получить достойную производительность через рекурсивный алгоритм для создания полного списка для любого узла.

Чтобы добавить / удалить новый узел, вам нужно только использовать его «прямой родительский кеш» O(1).

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

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

Как только у вас есть список детей, вы можете использовать SQL WHERE id IN( id1, id2, .... ) Синтаксис для запроса для того, что вы хотите.

Однажды я должен был хранить сложную иерархическую арбитра-глубинную материальную систему материальной системы в подобном SQL-аналогичном менеджеру баз данных, который не был на самом деле до задачи, и оно закончилось принуждать грязные и сложные обозначения, определения данных, запросы и т. Д. , После перезапуска с нуля, используя диспетчер БД, чтобы обеспечить только API для записи чтения и записи на простых индексированных клавишах и выполняя все фактические входные / манипулирование / отчетность во внешнем коде, конечный результат был быстрее реализовать, проще понять и проще поддерживать и улучшать. Самый сложный необходимый запрос был по существу выбрать от B.

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top