2

Я использую Firebird 2.1, и я ищу лучший способ решить эту проблему.Вопрос по дизайну базы данных - это лучшее решение?

Я пишу приложение для календаря. Различные записи календаря пользователей хранятся в большой таблице календаря. Каждая запись календаря может содержать набор напоминаний - только одно напоминание/запись.

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

Мне нужно запросить напоминания на постоянной основе.

Какой из лучших вариантов?

A) Хранить информацию на напоминания в таблице календаря (в этом случае я собираюсь запросить сотни тысяч записей для IsReminder = 1)

B) Создайте отдельную таблицу Напоминания, которая содержит только ID записей календаря с установленными напоминаниями, затем запросите две таблицы с операцией JOIN (или, возможно, создайте представление на них)

C) Я могу хранить всю информацию о напоминаниях в таблице напоминаний, а затем запрашивать только эту таблицу , Недостатком является то, что некоторая информация должна дублироваться в обеих таблицах, например, чтобы показать напоминание, мне нужно знать и хранить время начала события в таблице напоминаний - таким образом, я поддерживаю две таблицы с одинаковыми значениями.

Как вы думаете?

И еще один вопрос: таблица календаря будет содержать календарь нескольких пользователей, разделенных только полем UserID. Поскольку может быть только 4-5 пользователей, даже если я помещу индекс в это поле, его избирательность будет очень плохой - что плохо для таблицы с сотнями тысяч записей. Есть ли обходной путь здесь?

Спасибо!

ответ

2

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

Если бы это был я, я бы пошел с выбором B. Я бы также сохранил любые атрибуты напоминания в таблице для напоминаний.

Будьте очень осторожны в том, идентифицируете ли вы событие EventId самостоятельно или (UserId, EventId). Если вы выберете последнее, вам нужно использовать составной первичный ключ для таблицы Event. Не беспокойтесь о сложных первичных ключах, особенно с Firebird.
Если вы объявите составной первичный ключ, имейте в виду, что объявление (UserId, EventId) не будет иметь таких же последствий, как объявление (EventId, UserId). Они логически эквивалентны, но структура автоматически создаваемого индекса будет отличаться в двух случаях.

Это, в свою очередь, повлияет на скорость запросов, таких как «найти все напоминания для данного пользователя».

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

И, если вы действительно хотите знать влияние на перфоманс, попробуйте все три способа, загрузите тестовые данные и выполните собственные тесты.

+0

Спасибо за исчерпывающий ответ :-) Если UserID не является частью составного первичного ключа, а просто поле с индексом, я полагаю, что его избирательность будет очень плохой, а скорость поиска будет медленной? – Steve

+0

@Steve: индексы были изобретены для быстрого выполнения запросов - если у вас есть поле с индексом, должно быть возможно писать запросы, используя этот индекс. –

+0

Doc, я читал, что селективность индекса Firebird является важным фактором. Если поле имеет низкую избирательность по индексу (только несколько разных значений), вы можете не увидеть увеличение скорости ... – Steve

0

Я думаю, вам нужно создать реалистичные, поддельные данные пользователя и измерить разницу с некоторыми типичными запросами, которые вы ожидаете запустить.

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

0

При выборе опции (A) вы должны

  • обеспечивают индекс «IsReminder» (или комбинированный индекс IsReminder, UserId, независимо подходит лучше всего для Ваших предполагаемых запросов)
  • убедитесь, что ваши запросы используйте этот индекс

Вариант B является предпочтительным по сравнению с A, если для каждого напоминания для хранения каждого запоминающего устройства имеется больше, чем булевский флаг (например, количество минут, в течение которых пользователь должен быть уведомлен перед событием). Тем не менее, вы должны угадать, как часто в вашей программе вам придется ПРИСОЕДИНИТЬСЯ к обеим таблицам.

Если вы можете, избегайте опции C. Если вы не хотите сравнивать все три случая, я предлагаю начать с A или B в соответствии с описанными обстоятельствами, и, вероятно, решение, которое вы выберете, будет достаточно быстрым, поэтому вам не нужно беспокоиться о других случаях.

+0

Doc, спасибо за информацию, но вы используете Firebird? Поскольку FB является особенным, когда дело доходит до индексов ... (см. Мой комментарий выше) – Steve

Смежные вопросы