Как вы разрабатываете схему для эффективного запроса вложенных элементов в базе данных ключ-значение?
-
03-07-2019 - |
Вопрос
Я использую Mnesia с Erlang, но этот вопрос применим к любой базе данных типа ключ-значение, такой как couchdb и т.д.
Я пытаюсь освободиться от мыслительного процесса RDBMS, но я не могу понять, как эффективно реализовать такую схему.
Допустим, у меня есть запись пользователя, и у него есть много записей подпункта, в котором есть много записей подпункта B, так что:
User
-SubItem A
--SubItem B
...
Мне нужно выполнить запросы по подпункту B.Эффективно ли это делать, когда это это вложенное?Должен ли я просто нормализовать это, чтобы это было быстрее?
Я слышал о некоторых людях, использующих дублирование данных, поэтому данные являются одновременно вложенными и отдельными, это смешно или это действительно полезно в некоторых случаях?
Решение
Основной вопрос заключается в том, когда будет достигнута желаемая производительность достаточно хорош?
Сканирование таблиц пользовательского словаря не требует чрезмерных затрат, если вам действительно нужно детально изучить каждый подпункт B, а размер B доминирует над общим размером словаря.
Если этого недостаточно, нормализуйте его, чтобы вы могли избежать предварительного чтения всех данных пользователя и подпункта A при запросе подпункта B.Используйте составной ключ, такой как (userId, SubItemAId, SubItemBId) в словаре SubItem B, если таблица упорядочена, чтобы вы могли выполнять запросы диапазона.
Если это полностью снижает производительность вашего запроса User / SubItem A, то рассмотрите дублирование данных в качестве последнего средства, поскольку оно более подвержено ошибкам.
Другие советы
В CouchDB было бы тривиально создавать записи view для каждого из подпунктов.Это дало бы вам очень быстрый доступ к этим элементам.В зависимости от того, что вы также добавляете в записи просмотра, вы, вероятно, могли бы предоставить любую информацию, необходимую для обратной ссылки на родительские документы / подпункты.
Я не уверен насчет Mnesia, и я только начинаю работать с CouchDB, но я понимаю, что в CouchDB, поскольку вы создаете свои собственные пользовательские индексы ("представления"), вы можете прямолинейно создавать индекс для этих подпунктов.
Пример функции отображения:
function(doc) {
for(var i in doc.subitems_a) {
var subitem_a = doc.subitems_a[i];
for(var j in doc.subitems_a[item_a].subitems_b) {
var subitem_b = subitem_a.subitems_b[j];
emit(subitem_b, doc)
}
}
}
Фактически это индексированный список подпунктов Bs, и затем вы можете вырезать и соединять из этого списка по своему выбору.
На самом деле, я думаю, это зависит от базы данных, которую вы используете.В CouchDB одна вещь будет работать лучше, в то время как в Mnesia что-то другое было бы лучше.Следует ли вам разбивать данные на разделы и сегментировать их?По каким критериям вы должны это делать?Насколько большого дублирования данных достаточно?
Как сказал Джеффри Хантин, потребуется некоторое экспериментирование и анализ, чтобы найти правильное решение.Тем не менее, большинство существующих нереляционных баз данных предоставляют вам инструменты, необходимые для решения этой проблемы.Ваша задача - определить компромиссы между каждым из них и какой компромисс вы можете принять по сравнению с другими.