SQLite ERD (стоимость приведения против объединения) - PullRequest
2 голосов
/ 06 мая 2011

Я должен сохранить много (более 50 000 строк) document - key - value в базе данных SQLite.Меня беспокоит: эти значения могут быть текстовыми или числовыми (есть даты, строки, числа и т. Д.).Я должен запросить мою базу двумя способами:

  • все значения для документа ####
  • или с операторами сравнения

Я думал о 2возможные решения:

решение 1:
отдельная таблица:
key(text) | type(one of text/date/float) | value(text)

и использование явного приведения при необходимости сравнения (например,
SELECT * FROM mytable WHERE (CAST(value as float) < "2010-01-01 00:00:00") AND (type='date')
или
SELECT * FROM mytable WHERE (CAST(value as float) < 17.5) AND (type='float')

Что мне нравится в этом решении :

  • легко получить все значениядля

Что мне не нравится в этом решении :

  • Мне нужно сделать много (потенциально) дорогих приколов

решение 2:
три таблицы:

  • текстовые значения: key(text) | value(text)
  • значения с плавающей запятой: key(text) | value(float)
  • значения даты: key(text) | value(datetime)

Что мне нравится в этом решении :

  • больше не бросает

Что мне не нравится в этом решении :

  • получение всех значений имеет стоимостьиз 3 выбирает и объединение
  • Я считаю это менее элегантный

вопрос
Так возникает вопрос, какой изрешения вы мне порекомендуете?Зачем?у вас есть другое решение, чтобы предложить?

1 Ответ

0 голосов
/ 06 мая 2011

Исходя из моего опыта, сохранение значения в виде строки вполне приемлемо, и самое простое / прямое при условии, что ...
- Вам никогда не придется искать по самому значению (невозможно использовать индекс)
- Вы не обрабатываете огромные (тысячи / миллионы) или записи сразу


Опция трех таблиц и UNION имеет ограничение, которое вы, возможно, не заметили: столбец value в представлении UNIONed не может быть разных типов данных. Они либо будут получены неявным образом (на основе типа поля в первом SELECT из UNION), либо представление просто не будет создано.

Моим вариантом этой идеи было бы иметь три поля значений вместо одного. Затем вы можете добавить отдельный индекс для каждого, иметь только одну таблицу, избегать необходимости в CAST и других преимуществах. Все за счет небольшой дополнительной сложности в таблице (я бы предпочел это здесь, а не запросы, использующие ее в любом случае), но также и при значительном увеличении используемого пространства.

Key, Type, Value_INT, Value_FLOAT, Value_DATE


EDIT:

О, и последний вариант. Не храните значения как строки, но храните их как числа с плавающей точкой. Все три типа данных, которые вы упомянули, могут храниться как числа с плавающей запятой, что позволяет использовать индекс.

SELECT * FROM mytable WHERE (type='date') AND (value < CAST("2010-01-01 00:00:00" AS FLOAT))

или

SELECT * FROM mytable WHERE (type='float') AND (value < 17.5)

или

SELECT * FROM mytable WHERE (type='int') AND (value < 17)

...