Наскільки я можу сказати, ви можете оптимізувати об'ємну вставку так само, як і звичайну вставку. Зазвичай план запитів для простої вставки не є надто інформативним, тому не турбуйтеся про відсутність плану. Я перегляну кілька способів оптимізації вставки, але більшість з них, ймовірно, не застосовуються до вставки, яку ви вказали у питанні. Однак вони можуть бути корисними, якщо в майбутньому вам потрібно буде завантажувати більшу кількість даних.
1. Вставте дані в порядку кластеризації клавіш
SQL Server часто сортує дані, перш ніж вставляти їх у таблицю з кластерним індексом. Для деяких таблиць та додатків ви можете покращити продуктивність, сортуючи дані у плоському файлі та повідомляючи SQL Server, що дані сортуються за ORDER
аргументом BULK INSERT
:
ЗАМОВЛЕННЯ ({стовпчик [ASC | DESC]} [, ... n])
Визначає спосіб сортування даних у файлі даних. Ефективність масового імпорту покращується, якщо дані, що імпортуються, сортуються відповідно до кластерного індексу на таблиці, якщо такі є.
Оскільки ви використовуєте IDENTITY
стовпець як кластерний ключ, вам не потрібно про це турбуватися.
2. Використовуйте, TABLOCK
якщо можливо
Якщо ви гарантовано матимете лише один сеанс, вставляючи дані у свою таблицю, ви можете вказати TABLOCK
аргумент BULK INSERT
. Це може зменшити суперечки щодо блокування та може призвести до мінімальної реєстрації в деяких сценаріях. Однак ви вставляєте в таблицю з кластерним індексом, яка вже містить дані, тому ви не отримаєте мінімальний журнал без прапора 610 сліду, про який згадується пізніше у цій відповіді.
Якщо TABLOCK
це неможливо, оскільки ви не можете змінити код , не втрачається вся надія. Подумайте про використання sp_table_option
:
EXEC [sys].[sp_tableoption]
@TableNamePattern = N'dbo.BulkLoadTable' ,
@OptionName = 'table lock on bulk load' ,
@OptionValue = 'ON'
Інший варіант - включити прапор трассингу 715 .
3. Використовуйте відповідний розмір партії
Іноді ви зможете налаштувати вставки, змінивши розмір партії.
ROWS_PER_BATCH = рядки_per_batch
Позначає приблизну кількість рядків даних у файлі даних.
За замовчуванням всі дані у файлі даних надсилаються на сервер у вигляді однієї транзакції, а кількість рядків у партії невідомо оптимізатору запитів. Якщо ви вказали ROWS_PER_BATCH (зі значенням> 0), сервер використовує це значення для оптимізації операції масового імпорту. Значення, вказане для ROWS_PER_BATCH, має бути приблизно таким же, як і фактична кількість рядків. Для отримання інформації про міркування щодо ефективності див. "Зауваження" далі в цій темі.
Ось цитата з подальшої статті:
Якщо кількість сторінок, що підлягають розмиттю в одній партії, перевищує внутрішній поріг, може відбутися повне сканування буферного пулу, щоб визначити, які сторінки підлягають розмиттю, коли пакет розпочинається. Це повне сканування може пошкодити ефективність масового імпорту. Ймовірний випадок перевищення внутрішнього порогу відбувається, коли великий пул буфера поєднується з повільною підсистемою вводу / виводу. Щоб уникнути переповнення буфера на великих машинах, або не використовуйте підказку TABLOCK (яка видалить масові оптимізації) або використовуйте менший розмір партії (що зберігає масові оптимізації).
Оскільки комп'ютери різняться, радимо протестувати різні розміри партій із завантаженням даних, щоб з’ясувати, що найкраще підходить для вас.
Особисто я просто вставив би всі 695 рядків однією партією. Настроювання розміру партії може істотно змінитись, якщо вставляти багато даних.
4. Переконайтеся, що вам потрібен IDENTITY
стовпець
Я нічого не знаю про вашу модель даних або вимоги, але не потрапляйте в пастку додавання IDENTITY
стовпчика до кожної таблиці. У Аарона Бертран є стаття про це під назвою Шкідливі звички до удару: розміщуючи стовпець ІДЕНТИМЕТІЙНОСТІ на кожен стіл . Щоб було зрозуміло, я не кажу, що ви повинні видалити IDENTITY
стовпець із цієї таблиці. Однак якщо ви визначите, що IDENTITY
стовпець не потрібний, і видаліть його, це може покращити продуктивність вставки.
5. Вимкнути індекси або обмеження
Якщо ви завантажуєте велику кількість даних у таблицю порівняно з тим, що у вас вже є, можливо, буде швидше відключити індекси або обмеження перед завантаженням та включити їх після завантаження. Для великих обсягів даних SQL Server, як правило, більш неефективно будувати індекс відразу, замість того, як дані завантажуються в таблицю. Схоже, ви вставили 695 рядків у таблицю з 11500 рядками, тому я б не рекомендував цю техніку.
6. Розгляньте TF 610
Trace Flag 610 дозволяє мінімально входити в деякі додаткові сценарії. Для вашої таблиці з IDENTITY
кластеризованим ключем ви отримуватимете мінімальний журнал для будь-яких нових сторінок даних, якщо ваша модель відновлення проста чи об’ємна. Я вважаю, що ця функція за замовчуванням не ввімкнена, оскільки може погіршити продуктивність у деяких системах. Вам потрібно буде ретельно перевірити, перш ніж увімкнути цей прапор слідів. Рекомендована посилання Microsoft як і раніше є Посібником з продуктивності завантаження даних
Вплив вводу / виводу мінімальної лісозаготівлі під прапором 610 сліду
Коли ви здійснюєте транзакцію масового завантаження, яка була мінімально зареєстрована, усі завантажені сторінки повинні бути видалені на диск до завершення фіксації. Будь-які розмиті сторінки, що не потрапили в результаті попередньої операції контрольної точки, можуть створити велику кількість випадкових вводу-виводу. Порівнюйте це з операцією з повністю зареєстрованим журналом, яка створює послідовний введення / вивід у записі журналу замість цього і не вимагає завантаження сторінок на диск на час фіксації.
Якщо ваш сценарій завантаження - це невеликі операції вставки на btrees, які не перетинають межі контрольної точки, і у вас є повільна система вводу / виводу, використання мінімальної реєстрації може фактично уповільнити швидкість вставки.
Наскільки я можу сказати, це не має нічого спільного з прапором 610 слідів, а з мінімальним самим веденням журналу. Я вважаю, що раніше цитата про ROWS_PER_BATCH
налаштування була такою ж концепцією.
На закінчення, напевно, ви не можете багато що зробити, щоб настроїти своє BULK INSERT
. Мене б не хвилювало число прочитаних, яке ви спостерігали зі своєю вставкою. SQL Server повідомляє про читання кожного разу, коли ви вставляєте дані. Розглянемо наступне дуже просто INSERT
:
DROP TABLE IF EXISTS X_TABLE;
CREATE TABLE X_TABLE (
VAL VARCHAR(1000) NOT NULL
);
SET STATISTICS IO, TIME ON;
INSERT INTO X_TABLE WITH (TABLOCK)
SELECT REPLICATE('Z', 1000)
FROM dbo.GetNums(10000); -- generate 10000 rows
Вихід від SET STATISTICS IO, TIME ON
:
Таблиця "X_TABLE". Кількість сканувань 0, логічне зчитування 11428
У мене є 11428 повідомлень про читання, але це неприйнятна інформація. Іноді кількість повідомлених зчитувань може бути зменшена за допомогою мінімальної реєстрації, але, звичайно, різницю неможливо перевести безпосередньо на збільшення продуктивності.