Не изобретайте велосипед заново, особенно когда тот, который вы пытаетесь заменить, уже круглый.
Итак, давайте посмотрим, как существующее колесо сравнивается с тем, которое вы пытаетесь заново изобрести.
1) Существующее колесо (таблица со столбцами) У нас есть таблица Entity
, которая имеет такую структуру:
id INTEGER PRIMARY KEY
attr1 INTEGER
attr2 REAL -- this holds a date
attr3 TEXT
attr4 TEXT
2) Изобретенное колесо, таблица атрибутов. Скажем, мы создадим таблицу EntityAttributes
дляэто то, что мы будем хранить все атрибуты из Entity
в 1), но вопрос в том, как это должно выглядеть?Должны ли мы использовать TEXT
в качестве типа для всех значений атрибутов и обрабатывать обратное преобразование в приложении?Тогда таблица может выглядеть так:
entity_id INTEGER
attr_name TEXT
attr_value TEXT
PRIMARY KEY(entity_id, attr_name)
Это на самом деле не такая уж большая драма, поскольку внутренне Sqlite хранит все как TEXT, но когда дело доходит до любой нормальной СУБД, это огромные потери.
Альтернативой является использование таблицы сложных атрибутов, которая поддерживает несколько типов.Это может выглядеть так:
entity_id INTEGER
attr_name TEXT
attr_int INTEGER
attr_real REAL
attr_text TEXT
PRIMARY KEY(entity_id, attr_name)
Существует еще одна возможность - использовать основную таблицу для пары (entity_id, entity_name) с суррогатным ключом и таблицу для каждого типа данных (который имеет в качестве PK суррогат)значение ключа из таблицы основных атрибутов), но это становится слишком много для этого обсуждения.
Самое главное, чтобы увидеть, что с самого начала есть проблемы, которые нам нужно обойти, когда мы выбираем колесо.
Теперь давайте продолжим и поговорим немного о производительности.Все значения в строке обычно хранятся рядом (или близко) друг к другу, поэтому стоимость ввода-вывода обычно низкая.Этого нельзя сказать о нескольких строках, особенно если они не вставляются одна за другой.Вы всегда можете переиндексировать файл базы данных, чтобы оптимизировать доступ, но это не сильно поможет, если строки не создаются одна за другой.
Еще один недостаток вашего решения заключается в том, что ему действительно нужно больше памяти, чем естественному решению (немного, но еще больше).
Все хорошо до сих пор?Как насчет этого: у вас есть следующий простой SQL-запрос:
SELECT id, attr1, attr2
FROM Entity
ORDER BY attr1;
Попробуйте сделать то же самое, используя подход атрибута на строку, посмотрите, насколько это просто.И это только пример, на ум приходят многие другие.
По сравнению с традиционной СУБД решение таблицы атрибутов выглядит в вашем случае только хуже (на этот раз, потому что они лучше справляются с сохранением значений столбца строкивместе и для другого, потому что они поддерживают разные типы в отличие от Sqlite).При использовании хранилища данных Key-value, такого как Redis, это совсем другое дело.
В целом, можно многое сказать против подхода атрибута на строку и на самом деле не имеет никакого преимущества, если вы можете сделать то же самое, используя несколькоколонны.Таблица атрибутов полезна, когда она вам действительно нужна, на ум приходит что-то вроде неизвестного количества (динамических) атрибутов, но в вашем случае я бы остановился на естественном решении.