Флаг против разделения таблицы


10

Я разрабатываю таблицу предметов, которая (потенциально) будет содержать десятки миллионов записей. Некоторые элементы не будут доступны для использования, пока они не будут «одобрены» администратором. Под «использованием» я подразумеваю, что на такие элементы не будут ссылаться никакие другие таблицы, пока они не будут «одобрены». До 50% элементов могут быть «не одобрены» в любой момент времени. Записи могут стать «одобренными», но не наоборот.

Я рассматриваю два варианта дизайна:

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

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

Вопрос в том, должен ли я рассмотреть первый вариант (битовый флаг)? Есть ли какие-то преимущества в описанной ситуации?


1
Помните, что вы можете использовать отфильтрованные индексы, чтобы ускорить доступ к утвержденным записям. brentozar.com/archive/2013/11/…
mendosi

К сожалению, отфильтрованные индексы не используются в параметризованных запросах.
Дима

@ Дима, это не совсем так. Если в отфильтрованном индексе есть слово, WHERE status='A'а в запросе есть WHERE status = 'A' AND (... other columns and parameters here...), то этот индекс все еще может использоваться.
ypercubeᵀᴹ

Ответы:


6

Вы можете использовать оба способа с разделенными представлениями .

Вы создаете базовую таблицу для каждого статуса, поддерживаемого ограничениями, со взаимоисключающими значениями. Затем рассмотрим, какие объединения объединяют основные таблицы. На представление или на каждую базовую таблицу можно ссылаться явно. Если статус строки ОБНОВЛЕН через представление, СУБД УДАЛЕТ его из одной базовой таблицы и вставит в таблицу, соответствующую новому статусу. Каждая базовая таблица может быть проиндексирована независимо в соответствии со схемой ее использования. Оптимизатор разрешит ссылки индекса на одну соответствующую базовую таблицу, если это возможно.

Преимущества
а) более мелкие индексы. Тем не менее, сделайте математику на разветвлении индекса. При таком масштабе и разделении между значениями вашего состояния возможно, что индексы в таблицах разделения будут иметь такую ​​же глубину, как и в объединенной таблице.
б) код приложения не должен меняться. Данные продолжают появляться как единое целое.
c) будущие новые значения статуса могут быть включены путем добавления новой базовой таблицы с ограничением и повторного создания представления.

Стоимость - все это движение данных; две страницы и соответствующие индексы пишутся для каждого обновления статуса. Много IO, чтобы иметь дело с. Это большое движение также приведет к фрагментации.


5

таблица элементов, которая (потенциально) будет содержать десятки миллионов записей.

Это на самом деле не так уж много, учитывая, что SQL Server может эффективно обрабатывать. Конечно, я помню одно из моих ранних заданий, когда в одной из самых больших таблиц (система с одним экземпляром) было 2 миллиона строк, и это было больше всего, с чем я когда-либо имел дело. Затем у следующего задания было 17 производственных экземпляров с несколькими таблицами, имеющими сотни миллионов строк, и все они были объединены в хранилище данных с несколькими таблицами фактов, имеющими более 1 миллиарда строк. Не поймите меня неправильно, я не издеваюсь над десятками миллионов строк, я просто подчеркиваю, что с хорошей моделью данных и надлежащим индексированием (и ведением индекса) SQL Server может справиться с большим количеством проблем .

До 50% элементов могут быть «не одобрены» в любой момент времени.

Хм. Это не звучит правильно. Скорость «одобрения» записей будет вдвое меньше, чем получение новых записей? На каждые 2 новые записи только 1 будет «одобрено»? В вашем примере, состоящем из 2 миллионов строк и 1 миллиона для «утвержденных» и «неутвержденных», через несколько лет еще с 10 миллионами записей вы ожидаете 6 миллионов для «утвержденных» и «неутвержденных»? Или это то, что 1 миллион «неутвержденных» останется неизменным, так что с 10 миллионами новых заявок будет 11 миллионов «одобренных» и еще 1 миллион «неутвержденных»?

Записи могут стать «одобренными», но не наоборот.

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

Итак, давайте посмотрим на выбор:

Флаг (или, возможно, даже TINYINT«статус»)

  • Немного медленнее для запросов каждого статуса
  • Более гибкий с течением времени / простой для включения изменения, такого как третье состояние (например, «Архивировано»), только с новым значением состояния поиска. Нет новой таблицы (обязательно), какой-то новый код, только какой-то код обновлен.
  • Меньше работы (т. Е. Кода, тестирования и т. Д.) И меньше места для ошибок при обновлении одного TINYINTстолбца
  • Менее сложный = меньшие затраты на техническое обслуживание с течением времени, более короткое время обучения для новых сотрудников, чтобы выяснить,
  • (возможно) Меньшее влияние на журнал транзакций при обновлении одной таблицы
  • Просто нужна таблица поиска для «RecordStatus» и FK между двумя таблицами.

Две отдельные таблицы (одна для «утвержденных», одна для «не утвержденных»)

  • Чуть быстрее для запросов каждого статуса
  • Менее гибкий с течением времени / труднее включить изменение, такое как третье состояние (например, «Архивировано»); новое состояние, скорее всего, потребует другой таблицы и определенно нового и обновленного кода.
  • Больше работы (т.е. кода, тестирования и т. Д.) И больше места для перемещения записей об ошибках из таблицы «Неутверждено» в таблицу «Утверждено»
  • Более сложный = более высокие затраты на техническое обслуживание с течением времени, более длительное время обучения для новых сотрудников, чтобы выяснить,
  • (возможно) Большее влияние на журнал транзакций, так как одна таблица удалена, а другая вставлена
  • Не нужно беспокоиться об « обновлении идентификатора элемента »: в непризнанной таблице есть столбец идентификатора, который является IDENTITYстолбцом, а в утвержденной таблице есть столбец идентификатора, который не является IDENTITY(так как в этом нет необходимости). Следовательно, значения идентификаторов остаются согласованными при перемещении записей между таблицами.

Лично я бы склонялся к одной таблице с StatusIDколонкой для начала. Использование двух таблиц кажется слишком сложной, преждевременной оптимизацией. Этот тип оптимизации можно обсудить, если / когда число записей составляет несколько сотен миллионов, и индексация не обеспечивает какого-либо увеличения производительности.


Это таблица с быстро меняющимися данными: довольно часто заполняется множеством новых строк, довольно часто строки удаляются. Я пытался удалить все детали (например, деловое решение, кодирование клиента и т. Д.), Чтобы сосредоточиться только на одной теме. В основном у нас есть таблица старого дизайна с битовым флагом. И я на 100% знаю, что строки, в которых установлен флаг 1, никогда не используются ни в одной другой таблице. Поэтому я чувствую, что они происходят только там и могут быть перенесены на отдельный стол. Таблица сканируется практически по каждому запросу в БД. Таким образом, уменьшение его «веса» потенциально может уменьшить количество операций CPU / IO.
Дима

3
Другое преимущество разделенных таблиц: у вас могут быть FK, которые ссылаются только на «утвержденную» таблицу.
ypercubeᵀᴹ

Другая проблема с разделенными таблицами для одного объекта - это целостность ограничений. Ссылки из других таблиц не будут играть хорошо с движущейся записи. Это потребует написания кода для решения этих проблем, таких как зеркальные справочные таблицы для разделенной таблицы -> Очень хлопотно
user1567453
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.