База данных: Лучшая практика - старые данные? - PullRequest
2 голосов
/ 22 декабря 2009

У меня есть база данных автомобильных объявлений.

По истечении 90 дней классифицированный листинг больше не будет отображаться (срок годности истекает); однако я хочу сохранить данные в архиве.

Вопрос : С точки зрения передового опыта проектирования баз данных, а также производительности запросов, лучше сохранить старый список A) в той же таблице, что и текущий список, или B) , переместить список с истекшим сроком в таблицу с истекшим сроком и удалить этот список из текущей таблицы листинга?

Другими словами,

Опция A) :

table_classified_listing:
car_id
expired = true | false
...

Опция B) :

// only current listing in this table (expired = false)
table_classified_listing:
car_id
...

// only expired listing in this table (expired = true)
expired_table_classified_listing:
car_id
...

UPDATE

Меня беспокоит вариант A, что в моей базе данных MySQL - когда я запускаю EXPLAIN, он говорит, что он использует expired в качестве основного ключа для индексации. Однако, что более важно для моей эффективности поиска запросов, так это использование поля price, поскольку я выполняю поиск на основе price > X. Поэтому я и решил выбрать вариант B.

Ответы [ 9 ]

6 голосов
/ 22 декабря 2009

Вариант A) таким образом, вы располагаете все свои данные в одном месте и можете легче создавать запросы для создания отчетов, составления списка исторических записей пользователей и т. Д. Любые проблемы со скоростью должны быть уменьшены индексом базы данных в этом столбце. Вариант Б): преждевременная оптимизация .

4 голосов
/ 22 декабря 2009

Общие советы (вы должны заполнить пробелы ;-)):

  • Производительность будет существенной только в некоторых случаях (более миллиона записей, огромный размер строки ...).

  • Будете ли вы запрашивать две таблицы с помощью 'союзов' или идентичных запросов? Если вы не будете запрашивать таблицы, используя одни и те же запросы, я предлагаю другие таблицы (возможное увеличение производительности при увеличении количества записей, но в основном Значение усиление).


Проблема дублирования в том, что это может увеличить работу (написание запросов, их тестирование ...). Но все технологии (особенно современные) позволяют уменьшить или отменить дублирование.

Например, с ORM у вас может быть абстрактная сущность, которая отображается на общие поля, но нет таблицы, и два подкласса, которые отображаются на ваши таблицы. Нет дублирования информации столбца. И ORM также может создавать ваши сценарии базы данных, поэтому у вас их даже нет (хотя вы, конечно, должны проверять их вручную на производственную базу данных).


ОБНОВЛЕНИЕ после обновления в вопросе:

Вы можете создавать нужные индексы, не волнуйтесь. Если производительность, которую вы ищете для запроса данных, срок действия которых не истек, превышает цену X, создайте индекс (срок действия, цена), и у вас все в порядке: -)

3 голосов
/ 22 декабря 2009

Не используйте B, это в основном разделяет атрибуты.

Я бы использовал вместо этого два столбца даты. ValidFromDate и ValidToDate.

2 голосов
/ 22 декабря 2009

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

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

1 голос
/ 22 декабря 2009

Я бы держал их в одном столе. В противном случае, (а) у вас есть две таблицы с одинаковыми столбцами. В любое время, когда вы вносите изменения в данные, вы должны помнить об одинаковом изменении обеих таблиц. Рано или поздно кто-то забудет - или получит блестящее представление о том, что данные в одной таблице не нужны в другой - и теперь ваш дизайн усложняется. Довольно скоро вы пишете одну и ту же логику дважды: один раз для извлечения из «текущей» таблицы и еще раз для извлечения из «архивной» таблицы. Но затем кто-то вносит изменения в один кусок кода и забывает внести то же самое изменение в другой кусок кода. Тогда следующий человек, который придет, не может быть уверен, что они разные, потому что есть веская причина, почему они должны отличаться или кто-то просто забыл. И т. Д. (B) Кажется вероятным, что у вас будут запросы, которые захотят попасть в обе таблицы, например «скажи мне все объявления с запрашиваемой ценой свыше 20 000 долларов за последние 12 месяцев», где некоторые из них могут быть текущими, а другие - текущими. архив. Эти запросы теперь являются объединениями или сложными объединениями, вместо того, чтобы просто не включать флаг «expired is true» или «expired is false».

Что касается проблемы производительности, это просто: создайте многопольный ключ, включающий все, что вам нужно включить. expired + цена или expired + modelname кажутся вероятными ключами. Вы, вероятно, хотите сначала указать истекший срок действия, потому что большинство ваших запросов, вероятно, будут нуждаться в записях с истекшим сроком, но я просто предполагаю. Выбор того, на что стоит индексировать, является сложным решением, но когда есть очевидные общие запросы к нескольким полям, просто сделайте это.

1 голос
/ 22 декабря 2009

Вот что я понимаю:

  • Так как это классифицированные списки, данные "недолговечны" по своей природе, и истекает.
  • В результате объем просроченных данных может превысить «текущие» или не просроченные данные.

Если я правильно понял вышеизложенное, следующий вопрос: как часто используются ваши просроченные данные? и для чего он используется? Как указал @ghills, sql-союзы могут замедлить вас.

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

Если вы храните их в одной и той же таблице, «where expired = false» может в конечном итоге стать вашим постоянным компаньоном, и, поскольку селективность будет низкой (то есть множество строк с истекшим сроком), индексирование по столбцу «expired» не будет получено Вы много отдаете за доллар. (У Oracle есть индексы битовой карты, но здесь это может вообще не применяться).

1 голос
/ 22 декабря 2009

Существует также как минимум две дополнительные опции для общей проблемы сохранения старых данных:

  • Разделите данные по дате и откатите дату или отсоедините раздел. Также можно реализовать каждый раздел как отдельную таблицу, а затем объединить их с представлением union-all. В этом последнем случае вам, как правило, лучше с грубым разделением гранулярности (месяц вместо дня). MySQL должен поддерживать оба эти решения, а секционирование имеет дополнительное преимущество, заключающееся в улучшении производительности запросов, связанных с запросами больших частей данных вашей таблицы.
  • Экспортируйте все данные, которые вы хотите сохранить, обрежьте таблицу и перезагрузите ее. Серьезно - перезагрузка может быть намного быстрее, чем удаление, когда вы удаляете много данных. Многие базы данных не имеют достаточно данных для этого - по крайней мере, в течение нескольких лет, а затем их администраторы обнаруживают, что им нужно либо обновить оборудование, либо очистить данные за весь год. На данный момент эта стратегия часто является лучшей.

Вернуться к вашим двум предлагаемым решениям:

  • Хранить данные в одной таблице. С вашими объемами данных это, вероятно, лучший подход. Но - в какой-то момент вы, возможно, захотите удалить его (7 лет?), И в этот момент вы можете выполнить небольшую асинхронную работу, которая выполняет ручное удаление, может удалить разделы или экспортировать / перезагрузить.
  • Хранить архивные данные в другой таблице. Это становится наиболее полезным, если вы можете использовать другое (меньшее) оборудование для менее часто используемых архивных данных, например отдельный сервер, меньшее количество процессоров, другой набор более дешевых / медленных дисков, меньший буфер памяти и т. Д. MySQL не хватает настраиваемости, чтобы сделать что-то из этого. Другая причина заключается в том, что ваши запросы часто выполняют сканирование таблиц и, перемещая большую часть данных, вы можете значительно повысить производительность. И это может быть так. Вы используете MySQL - у которого есть заведомо незрелый оптимизатор / планировщик, и вы не используете разделение. Поэтому, когда индекс не может быть использован, вы собираетесь сканировать таблицу. Если вам нужны молниеносные запросы, небольшой сервер или много строк - тогда я бы сохранил старые данные в отдельной таблице. Но вот, возможно, лучший способ сделать это:
  • хранит данные в двух таблицах, но первая таблица содержит 100% ваших данных (новых и старых), а вторая таблица содержит только самые новые данные. Причина такого подхода заключается в том, что может быть множество подмножеств или агрегатов, которые вы, возможно, захотите сгенерировать - и теперь таблица с самыми новыми данными - только одна из многих. Эти подмножества / агрегаты не являются абсолютно необходимыми - вы всегда можете просто запросить основную таблицу. Тем не менее, аналитические запросы, как правило, довольно сложно обрабатывать базу данных - и эти таблицы могут сделать их очень быстро. И, честно говоря, любой процесс, на который стоит потратить время, стоит проанализировать.
1 голос
/ 22 декабря 2009

Лично я бы сказал, чтобы переместить все просроченные в отдельную таблицу. По мере роста базы данных вы будете стремиться к более высокой производительности ваших «живых» записей, потому что они, вероятно, будут наиболее частыми.

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

EDIT: Как кто-то еще упомянул один большой недостаток этого подхода, если вы планируете часто комбинировать живые данные и архивные данные. Если вы всегда будете ссылаться на них отдельно, то это здорово, но если нет, у вас будет много объединений и союзов, необходимых для объединения данных - что не идеально.

0 голосов
/ 22 декабря 2009

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

...