В какой момент я должен разделить или разбить очень большую, но простую таблицу

8

На нашем сайте есть несколько больших, но простых (INT, INT, DATE) таблиц для статистики. Каждая таблица имеет до 300 000 000 строк и увеличивается с каждым днем.

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

Однако...

Я пытаюсь согласовать этот совет с заявленной максимальной емкостью для SQL Server - размер базы данных составляет 524 272 терабайта, а строки таблицы ограничены только «доступным хранилищем».

Основываясь на этих рисунках, таблица, описанная выше, может легко иметь сантиллионы строк (от 10 до степени 303).

Ах, вы могли бы сказать, что есть разница между ВОЗМОЖНОСТЬЮ и ПРОИЗВОДИТЕЛЬНОСТЬЮ.

Но практически на каждый вопрос о производительности SQL Server ответ звучит так: «Это зависит от дизайна таблицы и дизайна запроса».

Вот почему я задаю этот вопрос. Дизайн стола не может быть намного проще. Также не могли запросы, которые являются простыми операциями count (*), основанными на индексируемом поле идентификатора.

Мартин Хансен Леннокс
источник
Разделение таблиц - это то, что вы планируете в своей структуре базы данных, до фактической записи данных, желательно. Гораздо сложнее и утомительнее сделать это после свершившегося факта.
1
Это зависит больше от вашего сценария: производительность в порядке? Можете ли вы заархивировать некоторые данные? Являются ли таблицы такими большими для эффективного резервного копирования / восстановления? Они сжаты? Было бы хорошо разделить с первого дня, но следующий лучший день - сегодня, если вы беспокоитесь о будущей производительности, если вы хотите следовать передовым методам.
LowlyDBA
2
Я думаю, что при таком объеме данных вам нужно разделить базу данных на архитектурный уровень, базу данных OLTP и базу данных OLAP. База данных вашего приложения «OLTP» должна содержать только минимальные данные, необходимые для приложения и бизнеса, а остальные должны быть сброшены в данные. склад "ОЛАП". Поскольку вопрос в том, когда вы должны начать разбивать свои таблицы, взгляните на эту статью Кендры ЛиттлHow To Decide if You Should Use Table Partitioning
M.Ali
3
Производительность никогда не будет танком, просто факт, что стол большой. Фактически, то, что является большим для многих, мало для некоторых. Понять, какие операции выполняются быстрее, а какие медленнее, путем разбиения. Разбиение не является быстрым переключателем. Это в основном медленный переключатель, и некоторые вещи становятся ослепительно быстрыми.
USR
4
Я настоятельно рекомендую обучающее видео MCM по разделению от Kimberly Tripp.
Пол Уайт 9

Ответы:

10

Есть причина, по которой общий совет заключается в том, что это зависит от дизайна таблицы и запросов к ней. Мой ответ на ваш другой пост в Stack Exchange говорит о многом. Сказать «запросы, которые являются простыми операциями count (*) на основе индексированного поля идентификатора», не дает много информации, поскольку ничего не говорит о мощности рассматриваемого набора строк. Вещи, которые вы можете сделать, чтобы смягчить (на настоящий момент) проблемы:

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

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

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

Бен Тул
источник
Спасибо Бен. Я начинаю понимать, что в игре больше переменных, чем я думал. И я признаю, что на практике «попробуй и посмотри» - самый разумный подход. Но так как SQL Server по сути является программой (хотя и очень сложной), то часть меня разочарована отсутствием предсказуемости.
Мартин Хансен Леннокс
1
@MartinHansenLennox и Бен: я определенно согласен с подходом «попробуй», а не просто слушаю советы или личные предположения. Но я бы порекомендовал в этом параграфе более четко указать, что это значит на самом деле попробовать. Это больше, чем просто загрузка и выполнение запросов. Тестирование должно включать постепенное добавление данных, чтобы увидеть, если / как все изменится по мере изменения статистики и фрагментации индексов и т. Д. И попытаться выполнить резервное копирование, восстановление, перестроение индексов и т. Д. Следует отметить, что секционированные индексы, начиная с 2012 г., больше не будут получить полное обновление статуса при восстановлении.
Соломон Руцкий
@MartinHansenLennox: Вы правы, что разочарованы подходом «попробуй и посмотри». SQL Server очень предсказуем, и, по крайней мере, теоретически можно проанализировать проблему, прежде чем пытаться ее решить. Однако количество базовых знаний, необходимых для этого, часто затрудняет это.
Томас Кейсер
7

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

Как отмечено в связанной статье, основное преимущество разделения заключается в том, что вы можете быстро перемещать данные с помощью переключения разделов . Например, вы можете архивировать «более холодные» данные для более медленного хранения и сохранять «горячие» данные в быстром хранилище. Через регулярные промежутки времени вы можете быстро архивировать данные, перемещая их в архивный раздел (ы) без необходимости ждать, пока ETL выполнит передачу. Однако, как отмечалось в одном из первых комментариев к вашему вопросу, прежде чем приступить к его реализации, необходимо тщательно продумать и спланировать его. Кроме того, в зависимости от используемой редакции SQL Server (Enterprise), вы можете использовать сжатие данных для сжатия отдельных разделов.

Что касается производительности, вы можете изменить эскалацию блокировки на AUTO(по умолчанию TABLE) следующим образом :

ALTER TABLE dbo.T1 SET (LOCK_ESCALATION = AUTO);
GO

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

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

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

swasheck
источник
2
«Разделение не для производительности запросов, это прежде всего для управления данными и администрирования» - кажется очевидным, когда вы это говорите, но я никогда не получал его раньше. Прекрасные ссылки, кстати, спасибо
Мартин Хансен Леннокс
Спасибо, что упомянули, что эта функция предназначена в первую очередь для управления, а не для повышения производительности. Я редко вижу это упоминание, и это довольно расстраивает.
Соломон Руцки
1
@MartinHansenLennox: для производительности также есть отличное использование секционирования. Например, если вы используете приемы разбиения хеша и для значений, которые имеют низкую мощность.
Томас Кейсер
7

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

Хорошее эмпирическое правило о том, какой большой размер раздела вы хотите: Примерно в два раза меньше размера DRAM, который у вас есть на коробке. Причина этой рекомендации:

  1. Вы можете перестроить индексы в разделе без разливов на tempdb. это НАМНОГО быстрее, чем если вы используете доступ к диску (даже с SSD).
  2. В то время как вы делаете эту перестройку, вы все равно можете держать весь раздел (как правило, самый последний) в DRAM, чтобы поддерживать производительность вашего запроса в хорошем состоянии.

Другими словами, вы хотите иметь достаточно DRAM для хранения двух разделов, а размер раздела зависит от того, на каком компьютере вы работаете. Большие машины могут комфортно обрабатывать большие перегородки.

Обратите внимание, что в этом руководстве также указан минимальный размер для tempdb: как минимум размера самого большого раздела (поэтому вы МОЖЕТЕ разлить там построение индекса, если при перестройке индекса недостаточно DRAM).

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

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

PS: Рад видеть, что вы не воспринимаете ответ как «все зависит», всегда спрашивайте метод, чтобы получить ответ.

Томас Кейсер
источник
Спасибо Томас, хороший совет, особенно ценю объяснения по поводу размера раздела.
Мартин Хансен Леннокс
7

Разделение таблиц, как и некоторые другие функции, довольно часто (или, возможно, даже чаще всего?) Используется не по назначению. Любой из предостережений я дал бы был хорошо изложен в @ swasheck в ответе .

Кроме того, альтернативой для рассмотрения является секционированные представления. Это способ хранить полностью отдельные таблицы, но связывать их вместе через UNION ALL в представлении. Каждая таблица требует CHECK CONSTRAINT, определяющей, какой диапазон данных содержит каждая таблица. Оптимизатор знает об этой конструкции и должен получать доступ только к базовым таблицам, которые требуются для запроса, используя представление (я не помню все требования, чтобы эта работа была запланирована, поэтому просмотрите ссылку CREATE VIEW внизу, но Я настроил его раньше, и было нетрудно заставить его работать как положено).

Определенно существуют некоторые ограничения, и основным недостатком является то, что он менее прозрачен по сравнению с разделением таблиц. Однако главное преимущество заключается в том, что это отдельные таблицы, и, следовательно, статистика является полностью отдельной, тогда как в случае Секционированной таблицы они предназначены для всей таблицы (даже если начиная с SQL Server 2014 вы можете обновить статистику по разделам).

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

Другим недостатком секционирования таблиц, которое слишком часто остается незамеченным / незамеченным, является то, что начиная с SQL Server 2012, вы больше не получаете «бесплатную» ОБНОВЛЕНИЕ СТАТИСТИКИ С FULLSCAN при перестроении многораздельных индексов. Вы по-прежнему получаете эту статистику обновления с перестроением по неразделенным индексам, какими будут индексы в таблицах в секционированном представлении :).

Для получения дополнительной информации о разделенных представлениях, пожалуйста, проверьте страницу MSDN для CREATE VIEW и найдите раздел «Разделенные представления» в разделе «Замечания».

Соломон Руцкий
источник
2
Отличный момент в ОБНОВЛЕНИИ СТАТИСТИКИ. Индексированные представления обходят множество проблем с разбиением, если вы можете справиться с воздействием оптимизатора.
Томас Кейсер