Производительность базы данных: фильтрация по столбцу против отдельной таблицы - PullRequest
9 голосов
/ 27 октября 2010

Мне было интересно, как лучше всего подойдет следующая ситуация:

У меня есть таблица заказов в базе данных, которая, очевидно, содержит все заказы. Но это буквально ВСЕ заказы, включая полные / законченные, которые помечены как «завершенные». Из всех открытых ордеров я хочу вычислить некоторые вещи (например, количество открытых позиций, открытые позиции и т. Д.). Что было бы лучше с точки зрения производительности:

Сохранить 1 таблицу заказов со ВСЕМИ заказами, включая завершенные / заархивированные, и выполнять вычисления, отфильтровывая флаг «завершить»?

Или я должен создать другую таблицу, например, 'Orders_Archive', чтобы таблица Orders содержала только открытые ордера, которые я использую для расчетов?

Есть ли (явная) разница в производительности в этих подходах?

(Б.Т.В., я нахожусь на базе данных PostgreSQL.)

Ответы [ 4 ]

7 голосов
/ 27 октября 2010

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

Наиболее распространенные подходы:

  • Все в одной таблице, пометьте ордера как «завершенные» в зависимости от ситуации. Плюсы: простейшее решение (как по кодам, так и по структуре), хорошая гибкость (например, легко "воскрешать" заказы). Минусы: таблицы могут быть довольно большими, проблема как для запросов, так и, например, резервное копирование.
  • Архив старых вещей на отдельную таблицу. Решает проблемы с первого подхода, за счет большей сложности.
  • Использовать таблицу с разделением на основе значений. Это означает, что логически (для приложения) все находится в одной таблице, но за кулисами СУБД помещает вещи в отдельные области в зависимости от значения (й) в некоторых столбцах. Вы, вероятно, использовали бы «полный» столбец или «дату завершения заказа» для разделения.

Последний подход объединяет хорошие части первых двух, но требует поддержки в СУБД и более сложен в настройке.

Примечание:

Таблицы, в которых хранятся только «заархивированные» данные, обычно называют «архивными таблицами». Некоторые СУБД даже предоставляют специальные механизмы хранения для этих таблиц (например, MySQL), которые оптимизированы для обеспечения быстрого поиска и хорошей эффективности хранения за счет медленных изменений / вставок.

6 голосов
/ 27 октября 2010

Или я должен создать другую таблицу, например, 'Orders_Archive', чтобы таблица заказов содержала только открытые ордера, которые я использую для расчетов?

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

Есть ли (явная) разница в производительности в этих подходах?

Да.Бонус.Вы можете реструктурировать свою историю так, чтобы она больше не была в 3NF (для обновления), а в схеме Star (для отчетов).Преимущества огромны.

Купите книгу Kimball's Data Warehouse Toolkit, чтобы узнать больше о проектировании звездообразной схемы и перенести историю из активных таблиц в складские таблицы.

4 голосов
/ 29 октября 2010

Никогда не разделяет или не разделяет текущие / архивированные данные. Это просто неверно. Его можно назвать «хранилищем данных» или «корзиной с рыбой», но это неправильно, излишне, и создает проблем, которых не было в противном случае. Результат:

  • каждый, кто запрашивает данные, должен искать их в двух местах, а не в одном
  • и хуже, добавьте агрегированные значения вручную (в Excel или что-то еще)
  • вы вводите аномалии в ключе, целостность теряется (что в противном случае было бы уникальным из-за одного ограничения в БД)
  • когда необходимо изменить Завершенный заказ (или многие), вы должны выловить его из «склада» и положить обратно в «базу данных»

Если и только если ответ в таблице является медленным, то устраните это и увеличьте скорость. Только. Ничего больше. Это (во всех случаях, которые я видел) является ошибкой индексации (отсутствующий индекс или неправильные столбцы или неправильная последовательность столбцов - все ошибки). Как правило, все, что вам нужно, - это столбец IsComplete в индексе, а также все, что пользователи используют для поиска чаще всего, для включения / исключения открытых / завершенных заказов.

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

Как в прошлом году, так и в этом, как часть обычного задания производительности, я объединил такие разделенные таблицы с миллиардами строк (и мне пришлось решать все проблемы с дублирующимися строками, которые якобы «не существовали», да, верно, 2 дня только за это). Сводные таблицы с исправленными индексами были быстрее, чем разделенные таблицы; оправдание, что «миллиарды строк замедлили работу таблицы» было полностью ложным. Пользователи любят меня, потому что им больше не нужно использовать два инструмента и запрашивать две «базы данных», чтобы получить то, что им нужно.

1 голос
/ 28 октября 2010

Поскольку вы используете postgresql, вы можете воспользоваться частичным индексом . Предположим, что для незавершенного заказа вы часто используете orderdate , вы можете указать индекс следующим образом:

create index order_orderdate_unfinished_ix on orders ( orderdate )
  where completed is null or completed = 'f';

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

Когда вы разделяете данные на ORDERS и ORDERS_ARCHIVE, вам придется корректировать существующие отчеты. Если у вас много отчетов, это может быть больно.

См. Полное описание частичного индекса на этой странице: http://www.postgresql.org/docs/9.0/static/indexes-partial.html

РЕДАКТИРОВАТЬ: для архивации я предпочитаю создать другую базу данных с идентичной схемой, а затем перенести старые данные из транзакции БД в эту архивную БД.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...