Хранение MongoDB вместе с функциями MySQL XPath - PullRequest
4 голосов
/ 02 июля 2011

У меня есть: большой набор данных сложных документов с древовидной структурой данных (каждый документ может иметь свое собственное дерево данных, которое может отличаться от документа к документу).Backend реализован с использованием Django 1.3 и MySQL.

Мне нужно:

  • хранить эти документы с использованием масштабируемого и быстрого хранилища
  • фильтровать документы по некоторым предопределенным запросам
  • поиск по данным в ограниченном подмножестве полей документа
  • дополнительная функция: поиск документов с использованием любого возможного запроса и извлечение любой возможной информации из дерева данных.Эта дополнительная функция является требованием заказчика, и пользователям, не имеющим технических навыков, должно быть удобно ее использовать.На данный момент у нас есть соглашение о том, что XPath достаточно.

Примечание: Не требуется часто менять документы.90% времени будет уделено операциям чтения.

Примечание: Мне редко нужны все возможные поля из дерева данных.Данные нужны примерно за 90% времени, это около 10% всего дерева данных.Единственный случай, когда нужны все данные, это дополнительная функция , описанная выше.Однако практически это не популярная функция системы.

Примечание: Дерево данных, которое поставляется с каждым документом, является представлением некоторого пользовательского формата, который не может быть изменен.Я могу только выбрать нужные фрагменты данных из дерева и преобразовать их в читаемую форму (а также записать их обратно, используя этот пользовательский формат).

В настоящее время я использую:

  • MySQL для хранения дерева данных для каждого документа в виде XML
  • некоторые предварительно выбранные данные из XML в виде дополнительных столбцов в той же таблице для ускорения поиска
  • все остальные фактически необходимые поля извлекаются из XML намуха во время каждого запроса с использованием функции MySQL extractvalue () (более 10 вызовов extractvalue () в каждом запросе SQL)
  • все поиск и фильтрация выполняются с использованием запросов XPath и extractvalue () к сохраненному XML

Проблема в том, что это временное решение очень плохое с точки зрения производительности.На наборе 100k + записей мне нужно подождать несколько минут, чтобы выполнить один запрос с ~ 10 вызовами extractvalue () в одном запросе.

Решения, которые я вижу в данный момент:

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

Плюсы:

  • Использование проверенной технологии (MySQL)
  • Большинство поисков будет выполнено против предварительновыбранные поля не используют очень медленную функцию extractvalue ()
  • В этом подходе я проверил поиск запросов XPath на наборе данных 100k +, и кажется, что производительность вызова 1 extractvalue () не слишком медленная (<1 с для запроса)по сравнению с 10+ одновременными вызовами extractvalue () в текущем временном подходе </li>

Минусы:

  • В связи с тем, что каждый документ может иметь свое собственное дерево данных, а также различный наборИз предварительно выбранных полей мне нужно создать несколько таблиц для хранения этих наборов данных и объединить эти таблицы в зависимости от типа документа
  • Предварительно выбранные поля могут быть списками, а не только отдельными значениями, поэтому каждоесписок должен иметь отдельную таблицу
  • Требуется синхронизация предварительно выбранных полей и XML

2) Использовать MySQL для XPathпоиск (т. е. дополнительная функция ), используйте MongoDB для всех других поисков.MongoDB хранит все необходимые предварительно выбранные поля, MySQL хранит только XML.

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

Плюсы:

  • 90% необходимых запросов должны быть быстрыми
  • Я мог бы хранить любые вложенные данные противкаждый документ.Деревья данных могут отличаться от документа к документу.Не нужно объединять множество столов.
  • MongoDB, похоже, имеет очень удобные инструменты для его использования из Python

Минусы:

  • Непроверенная технология (по крайней мере, для меня).У меня нет опыта работы с MongoDB, однако я проконсультировался с некоторыми программистами, использующими его, и кажется, что он выглядит многообещающе.
  • MongoDB не имеет функций, подобных XPath (а , похоже, их не будет в ближайшее время), поэтому я должен продолжать использовать MySQL для XPath (а также в решении 1) ).Как разработчик, я не хочу изобретать новый пользовательский язык запросов, поэтому XPath выглядит хорошим компромиссом.
  • Таким образом, требуется синхронизация между MySQL и MongoDB

Мои вопросы:

  • Могут ли быть некоторые скрытые или неочевидные проблемы с решением 2) ?
  • Я все еще беспокоюсь о производительности с extractvalue ().С точки зрения моего клиента, можно заменить подход XPath на какой-то аналогичный, однако я понятия не имею об этом с инструментами, доступными для MySQL или MongoDB.Могут ли быть какие-либо подобные решения, такие как XPath?

Буду благодарен за любые отзывы, мысли и комментарии по написанному выше.

Ответы [ 2 ]

0 голосов
/ 30 августа 2011

Это очень широкий вопрос, но я хотел бы рассмотреть несколько вещей: хранилища данных XML, такие как MarkLogic и eXist, - они очень хороши в оптимизации запросов к данным с древовидной структурой.

Вы также можете рассмотреть возможностьвладеть базовым поисковым индексом, таким как MySQL или, возможно, Lucene / Solr, если вы хотите улучшить возможности полнотекстового поиска (фразы, синонимы рядом с запросами и т. д.).

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

0 голосов
/ 03 июля 2011

Так что, если я правильно понял вопрос, вы хотите

  1. найти данный узел в дереве, данный какой-то путь через часть дерево к этому узлу плюс дополнительный запрос выражения.
  2. затем верните этот узел и все под ним.

С материализованными путями подход вы можете сделать выше. Главное, что нужно настроить, - это если путь к документу "a..b..c..d..e" и вы хотите найти документы с путем "..b..c..d. Как быстро это сделать. Если мы начинаем с самого верха, это легко. Однако здесь мы не. Возможно, имеет смысл использовать комбинированный подход, когда в документе есть материализованный путь для узла плюс массив предков узла, что-то вроде:

{ path : ",a,b,c,d,e,", 
  ancestor : ['a','b','c','d','e']
}

Мы могли бы индексировать по предкам, которые создадут индекс мультиключа. Затем мы выполняем запрос, подобный следующему, чтобы найти узлы на пути "... b, c, d ..." с некоторой эффективностью:

find( { path : /,b,c,d,/, ancestor : 'd', <more_query_expressions_optionally> } )

В приведенном выше примере будет использоваться индекс предка, и нужно проверять только документы, написанные "d". Можно попробовать следующее, что может быть даже лучше, в зависимости от того, насколько умен оптимизатор запросов:

find( { path : /,b,c,d,/, ancestor : { $all : ['a','d'] }, ... } )
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...