Кластерные индексы для неидентичных столбцов для ускорения массовых вставок? - PullRequest
8 голосов
/ 17 сентября 2010

Мои два вопроса:

  • Могу ли я использовать кластерные индексы для ускорения объемных вставок в большие столы?
  • Могу ли я тогда еще эффективно использовать отношения внешнего ключа, если мой Столбец IDENTITY не является кластеризованным индекс больше?

Чтобы уточнить, у меня есть база данных с парой очень больших (от 100 до 1000 миллионов строк) таблиц, содержащих данные компании. Обычно в такой таблице содержатся данные о 20-40 компаниях, каждая из которых имеет свой собственный «чанк», помеченный как «CompanyIdentifier» (INT). Кроме того, в каждой компании имеется около 20 отделов, каждый из которых имеет свой собственный «подраздел», помеченный «DepartmentIdentifier» (INT).

Часто случается, что целый «кусок» или «подчанк» добавляется или удаляется из таблицы. Первой моей мыслью было использование разбиения таблиц на эти блоки, но, поскольку я использую SQL Server 2008 Standard Edition, я не имею на это права. Тем не менее, большинство моих запросов выполняются на «чанке» или «чанке», а не на таблице в целом.

Я работал над оптимизацией этих таблиц для следующих функций:

  1. Запросы, которые выполняются на подразделах
  2. «Бенчмаркинг» запросов, которые выполняются для всей таблицы
  3. Вставка / удаление больших фрагментов данных.

Для 1) и 2) Я не столкнулся с большим количеством проблем. Я создал несколько индексов для ключевых полей (также содержащих CompanyIdentifier и DepartmentIdentifier, где это полезно), и запросы выполняются нормально.

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

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

Кажется, я заметил, что при добавлении кластерного индекса, определенного в CompanyIdentifier + DepartmentIdentifier, загрузка новых "кусков" в таблицу происходит быстрее. Прежде чем я отказался от этой стратегии в пользу добавления кластеризованного индекса к столбцу IDENTITY, несколько статей указывали мне на то, что кластерный индекс содержится во всех других индексах, и поэтому кластерный индекс должен быть как можно меньше. Но теперь я думаю о возрождении этой старой стратегии, чтобы ускорить вставки. Мой вопрос, будет ли это разумным, или я пострадаю от снижения производительности в других областях? И это действительно ускорит мои вставки или это только мое воображение?

Я также не уверен, действительно ли в моем случае нужен столбец IDENTITY. Я хотел бы иметь возможность устанавливать отношения внешнего ключа с другими таблицами, но могу ли я использовать для этого что-то вроде схемы CompanyIdentifier + DepartmentIdentifier + [uniquifier]? Или это должен быть фрагментарный номер IDENTITY по всей таблице?

Большое спасибо за любые предложения или объяснения.

Ответы [ 6 ]

3 голосов
/ 30 сентября 2010

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

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

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


Обновление : После года опыта работы с этим дизайном я могу сказать, что для этого подхода необходимо запланировать регулярную перестройку всех индексов (мы делаем это один раз в неделю). В противном случае индексы очень скоро фрагментируются и производительность теряется. Тем не менее, мы находимся в процессе перехода к новой структуре базы данных с секционированными таблицами, что в принципе лучше во всех отношениях - за исключением стоимости лицензии Enterprise Server, но мы уже забыли об этом. По крайней мере, у меня есть.

1 голос
/ 30 сентября 2010

Посмотрите на System.Data.SqlClient.SqlBulkCopy API.Учитывая ваши требования для записи значительного числа строк в и из базы данных, это может быть то, что вам нужно?

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

1 голос
/ 17 сентября 2010

Можно ли использовать кластерные индексы для ускорения массовых вставок в большие таблицы?

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

Могу ли я тогда эффективно использовать связи с внешним ключом, если мой столбец IDENTITY больше не является кластерным индексом?*

Абсолютно.Кстати, кластерный индекс не является серебряной пулей и может быть медленнее, чем ваш обычный индекс.

1 голос
/ 17 сентября 2010

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

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

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

В вашем решении вы помещаете поле [uniquifier], но зачем это делать, если вы можете указать личность, которая будет делать именно это? Он будет уникальным, физически упорядоченным, небольшим (для внешних ключей в других таблицах означает меньший индекс), а в некоторых случаях быстрее.

Не можете ли вы попробовать это, эксперимент? У меня похожая ситуация здесь, когда у меня 4 миллиарда строк, постоянно вставляется все больше (до 100 в секунду), таблица не имеет первичного ключа и кластерного индекса, поэтому предложения в этой теме ОЧЕНЬ интересны и для меня.

0 голосов
/ 02 декабря 2010

(Учитывая, что вы уже выбрали ответ и дали себе баллы, это предоставляется в качестве бесплатной услуги, благотворительной акции!)

Немного знаний - опасная вещь.Есть много вопросов, которые необходимо рассмотреть;и они должны рассматриваться вместе.Взятие любого отдельного вопроса и его изучение в отдельности - очень фрагментированный способ администрирования базы данных: вы навсегда найдете новую истину и измените все, что думали раньше.Перед тем как приступить к работе, прочитайте этот ▶ вопрос / ответ context для контекста.

Не забывайте, что в наши дни любой, у кого есть клавиатура и модем, может получить их"документы" опубликованы.Некоторые из них работают на РС, проповедуя последние «улучшения»;другие публикуют яркие отчеты о функциях, которые они никогда не использовали или использовали только один раз, в одном контексте, но они публикуют, что это работает в любом контексте.(Посмотрите на ответ Спенса: он полон энтузиазма и «продан», но под пристальным вниманием утверждения ложны; он не плохой человек, просто типичный для масс в мире РС и как они действуют; как они публикуются.)

  • Примечание: я использую термин MicroSofties для описания тех людей, которые верят в гейтсовское представление о том, что любой неквалифицированный человек может управлять базой данных;и что MS все исправит.Он не предназначен как оскорбление, скорее нежность, из-за веры в магию и приостановки законов физики.

Кластерные индексы

Были разработаны для реляционных баз данных настоящими инженерами (Sybase, до того, как MS приобрела код), у которых больше мозгов, чем у всех MS вместе взятых.Реляционные базы данных имеют реляционные ключи, а не Id iot ключи.Это многостолбцовые ключи, которые автоматически распределяют данные и, следовательно, загружают вставку, например.вставка счетов-фактур для различных компаний все время (хотя в нашем обсуждаемом случае «кусков» это не так).

  • , если у вас есть хорошие реляционные ключи, CI предоставляют запросы диапазона (ваши (1) и(2)) и другие преимущества, которых у NCI просто нет.

  • Начиная со столбцов Id, до моделирования и нормализации данных, серьезно затрудняет процессы моделирования и нормализации..

  • Если у вас есть Id iot база данных, то у вас будет больше индексов, чем нет.Содержимое многих баз данных MS не является «реляционным», обычно они представляют собой просто ненормализованные системы хранения, с гораздо большим количеством индексов, чем было бы в нормализованной базе данных.Поэтому есть большой толчок, множество «улучшений» MS, чтобы попытаться немного ускорить эти аборты.Исправьте симптом, но не приближайтесь к проблеме, вызвавшей его.

  • В SQL 2005 и снова в 2008 году MS облажалась с CI, и в результате они теперьлучше в некоторых отношениях, но хуже в других отношениях ;универсальность CI была потеряна.

  • Неправильно, что NCI несут CI (CI является базовой структурой с единым хранилищем; NCI являются вторичными и зависят от CI;Вот почему, когда вы воссоздаете CI, все NCI автоматически воссоздаются).NCI имеют CI Key на уровне листа.

  • У Microsoft есть свои проблемы, которые меняются в основных выпусках (но не устраняются):

    • и в MS это неэффективно, поэтому индекс NCI size большой;в корпоративных СУБД, когда это эффективно сделано, это не рассматривается.

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

    • Общий совет, согласно которому CI должен быть столбцом Id iot, полностью и полностью неверен.Наихудшим кандидатом для ключа CI является монотонно увеличивающееся значение (IDENTITY, DATETIME и т. Д.).Зачем ?потому что вы гарантировали, что все одновременные вставки будут бороться за текущее местоположение вставки, последнюю страницу в индексе.

    • Реальная цель создания разделов (которую MS предоставила через 10 лет после поставщиков Enterprise), чтобы распространить эту нагрузку.Конечно, тогда они должны предоставить метод распределения Разделов, если предположить, что ничего, кроме Реляционного Ключа;но для начала, теперь ключ Id iot распределен по 32 или 64 разделам, обеспечивая лучший параллелизм.

  • CI должен быть уникальным.Реляционные БД требуют уникальных ключей, так что это легко.

    • Но для любителей, которые вылили нереляционное содержимое в базу данных, если они не знают этого правила, но они знают, что КИ распространяет данные (немного знанийопасная вещь), они сохраняют свой Id iot ключ в NCI (хорошо), но они создают CI на почти, но не совсем уникальном ключе.Смертельный.CI должны быть уникальными, это требование дизайна.Дублирующиеся (помните, мы говорим здесь ключ CI) строки вне страницы, расположенные на страницах переполнения и (затем) последней странице;и представляют собой метод плохой фрагментации цепочки страниц.

    • Обновление, поскольку этот вопрос подвергается сомнению в другом месте. Я уже говорил, что MS продолжает изменять методы безустранение проблемы.

      • Онлайн-руководство MS Online с их красивыми картинками (не техническими диаграммами) говорит нам, что в 2008 году онизаменил (заменил один на другой) Страницы переполнения восхитительным «Уникализатором».

      • Это полностью удовлетворяет требованиям MicroSofties.Неуникальные КИ не являются проблемой.Это обрабатывается магией.Дело закрыто.

      • Но в заявлениях нет логики или полноты, и квалифицированные люди зададут очевидные вопросы: где находится этот «Уникализатор»?На каждом ряду или только на строках, нуждающихся в «Уникализации».DBBC PAGE показывает, что это на каждом ряду.Поэтому MS только что добавила 4-байтовый секретный столбец (включая обработку служебных данных) к каждой строке вместо нескольких страниц переполнения только для неуникальных строк.Это MS идея инженерии.

      • Окончание обновления

    • В любом случае, точка остается,что неуникальные КИ имеют существенные накладные расходы (теперь больше, чем раньше), и их следует избегать.Вам лучше добавить 1- или 2-байтовый столбец самостоятельно, чтобы добиться уникальности..

  • Таким образом, без изменений с начала (1984 г.) лучшим кандидатом на КИ является многостолбцовый уникальный реляционный ключ (я не могу сказать, что вашконечно, но это, безусловно, выглядит так).

  • И помещать любые монотонно увеличивающиеся ключи (IDENTITY, DATETIME) в NCI.

  • Помните также, что CI - это единая структура хранения,который устраняет (иначе) кучу;CI B-Tree состоит в браке с рядами на уровне листьев;запись уровня листа - это строка.Это гарантирует меньше чтения при каждом доступе.

    • Так что невозможно, чтобы куча NCI + могла быть быстрее, чем CI.Другой распространенный в мире MS миф, противоречащий законам физики: навигация по B-Tree и запись в то место, где вы уже находитесь, должна быть быстрее, чем дополнительно запись строки в отдельное хранилищесостав.Но MicroSofties действительно верят в магию, они приостановили законы физики.
      .
  • Есть много других функций, которые вам нужно изучить и использовать, я упомяну по крайней мере FILLFACTOR и RESERVEPAGEGAP, чтобы придать этому посту некоторую полноту. Не используйте эти функции, пока не поймете их. Все функции производительности имеют стоимость, которую вы должны понимать и принимать.

  • CI также самонастраиваются как на уровне страницы, так и на уровне экстента, не теряется место. PageSplits - это то, что нужно отслеживать (только для случайных вставок), и это легко модулируется с помощью FILLFACTOR и RESERVEPAGEGAP.

  • И прочитайте SO-сайт для кластерных индексов, но имейте в виду все вышесказанное, особенно. первые два абзаца.

Ваш конкретный случай

  • Во что бы то ни стало, избавьтесь от своих суррогатных ключей (Id в столбцах) и замените их настоящими естественными реляционными ключами. Суррогаты - это всегда дополнительный ключ и индекс; это цена, которую нельзя забывать или воспринимать легкомысленно.

  • CompanyIdentifier + DepartmentIdentifier + [uniquiefier] - это именно то, о чем я говорю. Теперь обратите внимание, что они уже INT и очень быстрые, поэтому очень глупо добавлять ЦИФРОВЫЙ (10,0) Id ключ. Используйте 1- или 2-байтовый столбец для уникальности.

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

  • CompanyIdentifier + DepartmentIdentifier + [uniquifier] является идеальным кандидатом (не зная ничего о вашей БД, кроме той, которую вы опубликовали) для CI, в контексте того, что вы периодически выполняете массовое удаление / вставку. Подробно выше.

    • Вопреки тому, что говорили другие, это хорошо, и не фрагментирует CI. Допустим, у вас есть 20 компаний, и вы удаляете 1, что составляет 5% данных. Весь этот PageChain, который был достаточно смежным, теперь переходит в FreePageChain, смежный и нетронутый. Чтобы быть точным, у вас есть одна точка фрагментации, но не фрагментации в смысле обычного использования слова. И угадайте, что, если вы развернетесь и выполните массовую вставку, как вы думаете, куда пойдут данные? Это точно такое же физическое местоположение, как и в удаленных строках. И FreePageChain перемещается к PageChain, экстенту и странице одновременно.
      .
  • но что настораживает, так это то, что вы не знали о требовании уникальности CI. Грустно, что MicroSofties пишут мусор, но не то, почему / на чем основано каждое упрощенное правило; не основная информация. Точный признак неуникальных CI: таблица будет очень быстрой сразу после DROP / CREATE CI, а затем замедлится со временем. Хороший уникальный CI будет держать скорость, и для его замедления потребуется год (2 года на моих больших, активных банковских базах данных).

  • 4 часа - это очень длительное время для 1 миллиарда строк (я могу воссоздать CI для 16 миллиардов строк с ключом из 6 столбцов за 3 минуты на корпоративной платформе). Но в любом случае это означает, что вы должны запланировать его как регулярное еженедельное или требовать обслуживания.

  • почему вы не используете опцию WITH SORTED_DATA? Разве ваши данные не были отсортированы до удаления? Эта опция переписывает CI Non-leaf страницы, но не листовые страницы (содержащие строки). Это можно сделать только в том случае, если он уверен, что данные были отсортированы. Не используя эту опцию перезаписывает каждую страницу в физическом порядке.

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

0 голосов
/ 17 сентября 2010

Я немного поиграл с некоторыми вещами из etl. я регулярно вставлял jsut в таблицу, затем удалял и читал индексы до и после вставки, пробовал операторы слияния, а потом наконец пробовал ssis. Я продан на ssis. Буквально вчера мне удалось сократить процесс etl (~ 24 миллиона записей, ~ 6 ГБ) с ~ 1-1 1/2 часа на один прогон до ~ 24 минут, просто позволив ssis обрабатывать вставки.

Я считаю, что с расширенными услугами вы сможете использовать ssis.

...