Структура таблиц БД: хранение списков значений наряду с обычными значениями

БД: MySQL.
Задача: хранить словаревидные данные в виде id:int->value:string.
Проблема: оказалось, что иногда нужно, чтобы одному id соответствовал список значений. При этом, если даже список состоит из одного элемента, все равно нужно отличать его от обычного значения.

Я вижу несколько вариантов решения, но ни один мне не нравится.

1) Хранить данные не в виде строки, а в каком-то формате: XML, JSON, etc. Тогда в одно строковое поле можно будет сохранить целый объект.
Вариант не нравится тем, что в итоге получаем денормализацию данных и проблемы, с ней связанные, например, невозможность оперировать значениями списка по отдельности стандартными средствами SQL. Чтение и изменение отдельных элементов прийдется реализовывать средствами приложения.

1.а) Хранить данные в одной строке с разделителем. Это частный случай варианта 1, и минусы те же самые.

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

3) Хранить все данные в одной таблице, просто не делать id строки словаря уникальным ключом, тогда можно будет добавлять несколько записей для одного id.
Не нравится тем, что тогда сложно определить, является ли элемент обычным элементом, или же частью списка. Добавление специального поля-флага а-ля is_list_element — костыль.
  • Вопрос задан
  • 14722 просмотра
Решения вопроса 1
Baileys
@Baileys
Ну как по мне то вариант2 (Создать отдельную таблицу для значений списков.) является оптимальным и стандартным. Обычно от него отходят только в нестандартных ситуациях. Не рекомендую выдумывать велосипед.
Ответ написан
Пригласить эксперта
Ответы на вопрос 4
@rPman
Описанное вами — это развитие реляционной модели в сетевую… в mysql как я знаю средств для этого нет, в postgresql есть поддержка массивов, только производительность не ля всех случаев оптимальна.

Ваша задача лучше всего решается все таки сериализацией. Проблема обновления данных при расширении функционала не на столько критична чтобы только на основании этого отказываться от сериализации.

Так же не стоит закрывать глаза штатную реализацию списков второй таблицей M-1.

И конечно же никто не мешает совместить оба подхода (хранить данные в 2 таблицах и кешировать дополнительными полями в главной, например информация о количестве элементов в списке, значение первого элемента,..)
Ответ написан
taliban
@taliban
php программист
На всякий случай, вдруг решите использовать первый вариант:
dev.mysql.com/doc/refman/5.1/en/xml-functions.html
Ответ написан
Комментировать
svfoster
@svfoster
Созадйте таблицу

ID ListID Value

где ID — уникальный номер записи в таблице (primary key), ListID — какойто ваш внутренний идентификатор, Value сами понимаете, что. Тогда вы сможете извлеч как одну строку, написав SELECT * From TableName Where ListID = 1 или несколько значений, которые уже и составят для вас список. Узнать, сколько у ваc значений с одним ListID так: SELECT Count( * ) From TableName Where ListID = 1; и не нужно дополнителных полей для отметки список это или нет.

Обратите внимание, что (по вашим вариантам) разделители или мультизначения тоже потом надо будет както обработать, потратив время, и (вероятно) еще раз сделать SELECT, затратив и на него дополнительное время и ресурсы. С моим вариантов у вас будет просто join если потрубется.

Не в коем случае не теряйте уникальный ключ в вашей таблиц, как вы хотите в 3!
Ответ написан
@edogs
Всё-таки если если «списковых» элементов относительно мало, то последний вариант имеет право на существование.
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы