SQL Server вставляет производительность с и без первичного ключа

Сводка: у меня есть таблица, заполненная следующим образом:

insert into the_table (...) select ... from some_other_table

Выполнение вышеуказанного запроса с помощью нет первичного ключа на таблице составляет ~ 15 раз быстрее, чем запуск с первичного ключа, и я не понимаю, почему.

Детали. Я думаю, это лучше всего объяснить с помощью примеров кода.

У меня есть таблица:

create table the_table (
    a int not null,
    b smallint not null,
    c tinyint not null
);

Если я добавляю первичный ключ, этот запрос на ввод очень медленный:

alter table the_table
    add constraint PK_the_table primary key(a, b);

-- Inserting ~880,000 rows
insert into the_table (a,b,c)
    select a,b,c from some_view;

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

Дополнительная информация:

  • Оценочный план выполнения показывает 0% общего времени запроса, затраченного на вставку кластерного индекса.
  • Версия для разработчиков SQL Server 2008 R2, 10.50.1600

Любые идеи?

Ответ 1

Это хороший вопрос, но тоже довольно дерьмовый вопрос. Прежде чем вы спросите, почему индекс замедляет вставки, знаете ли вы, что такое индекс?

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

Поэтому, когда вы создаете кластерный индекс после заполнения таблицы, ваша "куча" имеет некоторую статистику для использования, и SQL может в основном оптимизировать несколько вещей. Этот процесс намного сложнее этого, но в некоторых случаях вы обнаружите, что создание кластерного индекса после того, как факт может быть намного медленнее, чем просто вставить в него. Это имеет отношение к ключевым типам, количеству столбцов, типам столбцов и т.д. Это, к сожалению, не тема, которая подходит для ответа, это больше всего и несколько книг. Посмотрев на таблицу выше, это ОЧЕНЬ простая таблица с ~ 7 байт строк. В этом случае create-index после вставки будет быстрее, но пачка в нескольких varchar (250) и т.д., И игра в мяч изменяется.

Если вы не знаете, кластерный индекс (если ваша таблица имеет один), это ваша таблица.

Надеюсь, что это поможет.

Ответ 2

На самом деле это не так ясно, как предлагает Рык.

На самом деле может быть быстрее добавить данные в таблицу с индексом, затем в кучу.

Прочитайте этот arctle - и насколько я знаю, его довольно хорошо рассмотрели:

http://www.sqlskills.com/blogs/kimberly/post/The-Clustered-Index-Debate-Continues.aspx

Помните, что он написан SQL Server MVP и региональным директором Microsoft.

Вставки быстрее в кластерной таблице (но только в "правой" кластеризованной таблице), чем по сравнению с кучей. Основная проблема здесь заключается в том, что поиск в IAM/PFS для определения места вставки в куче медленнее, чем в кластерной таблице (где известно местоположение вставки, определенное кластеризованным ключом). Вставки быстрее, когда они вставлены в таблицу, где определен порядок (CL), и где этот порядок постоянно увеличивается. У меня несколько простых чисел, но я думаю о создании сценария с более крупными/сложными сценариями и публикации. Простые/быстрые тесты на ноутбуке не всегда являются "захватывающими".

Ответ 3

Я думаю, что если вы создадите простой первичный ключ, кластерный и состоящий из одного столбца автоматического увеличения, то вставка в такую ​​таблицу может быть быстрее. Скорее всего, первичный ключ, состоящий из нескольких столбцов, может быть причиной замедления вставки. Когда вы используете составной ключ для первичного ключа, тогда вставленные строки не могут быть добавлены в конец таблицы, но, возможно, их нужно будет добавить где-то в середине существующего физического порядка строк в таблице, что добавляет время вставки и, следовательно, делает ВСТАВКИ медленнее. Поэтому для ускорения вставок используйте один автоинкрементный столбец в качестве значения основного ключа в вашем случае.