Я знаю, что пары с ключом не являются хорошим дизайном базы данных, не нормализуются и т. Д. Однако в этом случае я считаю, что это наиболее подходящее решение.Ключ-значение для метаданных/тегов в СУБД: эффективное хранилище
Мое оправдание для этого и некоторый фон: большой набор элементов вставляется в набор таблиц, и каждый элемент может быть помечен произвольными метаданными, которые пользователь может выбрать. Пользователь может выбрать метаданные, потому что они указывают, как они хотят классифицировать, сообщать и просматривать элементы позже. Для этой конкретной бизнес-проблемы не наше место (как разработчики систем) не сказать, что такое эти измерения. Между элементами не существует согласованного набора ключей, и в некоторых случаях присутствие определенного ключа будет использоваться в качестве условия фильтра.
Еще одна информация о фоновом режиме, записи будут INSERTed, но не UPDATEd. В конце концов они будут DELETEd (последовательно, в том же порядке, в который они были вставлены).
Вопрос «Эффективное хранение»: этим я имею в виду производительность запроса (чтения). будут использоваться следующие типы запросов:
- Получить элементы с заданным ключом, любое значение
- Получить элементы с заданным ключом и значением
- Получить элементы со всеми ключевыми названиями
- Получить элементы с все ключевые имена и значения
в принципе, что это лучший выбор учитывая эти варианты ?:
ВАРИАНТ 1
Items table:
item_id (integer, pk)
... item fields ...
ItemFacts table:
item_id (integer, fk)
key_name (nvarchar(64))
key_value (nvarchar(128))
ВАРИАНТ 2
Items table:
item_id (integer, pk)
... item fields ...
Facts table:
fact_id (integer, pk)
key_name (nvarchar(64))
key_value (nvarchar(128))
ItemFacts table:
item_id (integer, fk)
fact_id (integer, fk)
(Там может быть третий вариант, где ключевые имена вытянута в отдельную таблицу еще раз, чтобы уменьшить избыточность, так как может быть в целом загрузка использованных/возможных значений для заданного имени ключа, также может быть целесообразным)
Грубо говоря, будет много дублированных совпадений ключ/значение. Таким образом, должно быть повышение эффективности хранения. Я понимаю, что это немного открытый вопрос, но как насчет производительности чтения? Как насчет того, если я тоже буду вводить этот запрос :?
- Получить пункты, где значение для данного ключа начинается с «х»
Если я могу предоставить какие-либо дополнительные пояснения, пожалуйста, дайте мне знать.
(спасибо за ответ). Я рассмотрел различные решения NoSQL, однако есть связанные таблицы, и большинство элементов и связанных с ними данных хранятся реляционным способом; это просто требование фильтрации/запроса, которое приводит к тому, что этот материал метаданных «заперт». Я не думаю, что могу добиться необходимой эффективности, сначала запросив хранилище данных NoSQL, чтобы получить идентификаторы (например), а затем запросить RDBMS для этих идентификаторов. –
Я думаю, что вы недооцениваете, насколько плохие запросы к EAV сосут. Шутки в сторону. подумайте о машине EAV. И вы хотите, чтобы все синие, 4 двери с 6Cyl и менее 50 км. Выберите ID Где attr = «Цвет» и значение = «Синий» пересекаются, выберите Id, где attr = «Двери» и значение = 4 ... Ужасно медленное. хорошо, что у вас есть дескриптор запросов, которые вы хотите сделать. Я думаю, что дело только в том, чтобы построить тестовый пример. Возьмите один из ваших примеров, постройте его ... сгенерируйте его с данными и попробуйте свои запросы. –
Другая вещь, которую я не упомянул, - это масштаб. Я вижу проблемы уровня предприятия, когда читаю описание. Если вы делаете это для совместной черно-белой книги братства, где атрибут применяется к женщинам, тогда делайте все, что захотите. Ваш масштаб недостаточно велик. Если вы делаете это для крупной компании или обширной пользовательской базы, то да, начните волноваться. –