Какой из этих дизайнов таблицы лучше для производительности?


16

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

Вот что я знаю

  • Компания имеет более 2,5 миллионов счетов
  • Из них в настоящее время они работают в среднем 200 000 человек в месяц (что зависит от уровня персонала, который в настоящее время является низким)
  • У них есть 13 различных типов затрат, которые они хотели бы отслеживать, и они предупредили, что могут добавить больше в будущем
  • Они хотят, чтобы расходы отслеживались ежедневно
  • Затраты не распределяются по всему инвентарю. Они либо распределяются по количеству учетных записей, работающих в месяц (200 000), либо пользователи могут вводить идентификаторы учетных записей, чтобы применить стоимость к группе учетных записей, или они могут просто указать, к каким учетным записям применять стоимость.

Моей первой мыслью была нормализованная база данных:

AccountId
Дата
CostTypeId
Количество

Моя проблема с этим, сделать математику. Этот стол станет огромным быстро. Предполагая, что все 13 типов затрат применяются ко всем работающим учетным записям в текущем месяце, это 200k * 13 * N days in monthпримерно 75-80 миллионов записей в месяц или почти миллиард записей в год.

Моя вторая мысль была немного денормализовать

AccountId
Дата
Общая стоимость
CostType1
CostType2
CostType3
CostType4
CostType5
CostType6
CostType7
CostType8
CostType9
CostType10
CostType11
CostType12
CostType13

Этот метод более денормализован и может создавать до 6 миллионов записей в месяц ( 200k * N days in month), или около 72 миллионов в год. Это намного меньше, чем в первом методе, однако, если в будущем компания примет решение о новом типе затрат, потребуется добавить еще один столбец базы данных.

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

Меня больше всего интересуют отчеты об исполнении, как обобщенные, так и подробные отчеты. Работа, которая будет распределять расходы по счетам, будет выполняться ночью, когда никого нет рядом. Вторая проблема - размер базы данных. Существующая база данных уже почти 300 ГБ, и я считаю, что место на диске составляет около 500 ГБ.

База данных SQL Server 2005


Так что получите еще один диск. Диски дешевые. Вы можете иметь 2 ТБ на стоимость встречи, чтобы спорить об этом.

Ответы:


9

Миллиард записей в год - это немного.

С разделением (возможно для каждого типа затрат) и архивированием это можно сделать.

Количество элементов данных для хранения по- прежнему составляет 200k * 13 * N. В качестве столбцов вы получите меньше строк на страницу, и это займет больше места, чем в виде строк. Вы можете получить, если «CostType1» не является типом данных фиксированной длины, но он маргинальный.

"ПОЦЕЛУЙ" как говорится


3
@Rachel Я определенно рекомендую реализовать схему секционирования с таким большим набором данных. Если они сосредоточены на работе месяца и месяца и отчетности, то лучше выбрать ключ раздела, который может совпадать с этим мышлением. Кроме того, если вы правильно сконфигурируете свой раздел, вы можете легко переключать данные из таблицы в промежуточные таблицы, что приводит к большой загрузке и удалению больших массивов данных, что занимает секунды, а не часы.
Дэвид

6

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

Подумайте об этом так, хотя в таблице 80 миллиардов записей с надлежащей индексацией, те, которые вам действительно интересны в любой момент, будут физически сгруппированы на диске. Из-за того, как данные организованы на сервере SQL, данные, разделенные по границам индекса, могут также находиться в другой таблице, потому что не нужно читать всю таблицу, чтобы получить то, что ей нужно.

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


4

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

Например, общая стоимость обслуживания банкоматов была разделена между счетами, которые использовали банкоматы, на основе относительного объема использования. Таким образом, если на обслуживание банкоматов было потрачено 1 миллион долларов, и только 5 клиентов использовали его один раз каждый, а один клиент использовал его 5 раз, то один клиент обошелся банку в 0,5 миллиона долларов, а остальные клиенты - банку в 0,1 миллиона долларов каждый. Другие драйверы могут быть намного сложнее.

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


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

3

Независимо от выигрыша в производительности, я определенно предпочел бы вариант 1. Вариант 2, по моему мнению, ограбил бы Питера, чтобы заплатить Полу.


2

Я бы выбрал вариант 1, а затем, если бы скорость создания отчетов стала проблемой в будущем, я бы также добавил таблицу 2 и заполнил ее в базу данных отчетов с помощью какого-то автоматизированного процесса в течение ночи / вне периода.

Затем вы можете также рассмотреть возможность сворачивания ежедневной структуры таблицы-2 в последующие еженедельные, ежемесячные, квартальные, годовые сводки, если это будет оправдано

Но, как я уже сказал, я бы также решил хранить «сырые» данные в надлежащей (нормализованной) форме.


0

Учитывая объемы, которые вы упоминаете, я бы выбрал второй вариант, но без TotalCost. Можно сказать, что все еще нормализовано.


Изменить: в качестве альтернативы, в зависимости от ваших требований и размера AccountId, вы также можете рассмотреть следующее:

AccountDate
-----------
AccountId  
Date  
AcDtID (surrogate key)

Costs
-------
AcDtID
CostTypeId  
Amount  

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


Я имею TotalCostв виду, потому что большая часть отчетов суммируется, и я подумал, что было бы быстрее запросить одно значение, чем добавить 13 различных значений.

Возможно, но тогда вы действительно вводите транзитивную зависимость. Будут ли когда-нибудь обновляться эти записи? или только написано а потом только читать?

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

Тогда каждое обновление потребует 2 обновления, а поле TotalCost добавляет риск несоответствия.

Переходная зависимость, но не обязательно риск несогласованности - ограничение CHECK () может гарантировать, что TotalCost всегда является суммой затрат.
Майк Шеррилл 'Cat Recall'

0

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

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.