ОНОВЛЮЙТЕ з ПРИЄДНАЙТЕСЬ на 100-мм запису, як це зробити краще? (у T-SQL)


11

Мені потрібно оновити 100 мільйонів записів в одній таблиці, фактично нормалізуючи таблицю, замінивши значення varchar стовпця просто ідентифікатором. (Я кажу "заміна", але насправді я записую ідентифікатор в іншу колонку.)

Я намагаюся досягти - це нормалізувати набір даних. Ще не нормалізовані дані не мають індексації. Моя думка полягала в тому, що я не буду будувати індекси на необроблених значеннях, чекаючи, а замість цього індексуватимуть зовнішні ключі, які замінять значення varchar на значення tinyint після завершення оновлення.

UPDATE A
SET A.AutoClassID = B.AutoClassID
FROM AutoDataImportStaging.dbo.Automobile as A
JOIN AutoData.dbo.AutoClass as B on (A.AutoClassName = B.AutoClassName)

Фон

  • за допомогою MSSQL 2008 R2 на сервері Server 2008 R2
  • сервер має 8 ГБ оперативної пам’яті
  • сервер має один RAID10, 7200 RPM SATA (не чудово, я знаю, у виробництві це буде лише читання даних, а не запис даних; плюс недавній дефіцит HD зробив це необхідним для витрат)
  • сервер має подвійний чотирьохядерний процесор Xeon
  • машина не робить нічого іншого (наразі присвячена розробнику, лише цей процес)
  • простий журнал увімкнено (? - але чи все ще входить так, щоб він міг відкати?)
  • зауважте, що запит посилається на два різні БД, для чого це варто
  • "ширина" запису в таблиці, що оновлюється, становить 455 байт

Ресурси під час виконання

  • фізична оперативна пам’ять максується
  • диск вводу / виводу виводиться на максимум
  • Процесор майже нічого не робить (точка задушення - це введення / виведення)
  • тривалість роботи тривала 14 годин і підрахунок!

Я підозрюю, що мені потрібен індекс для необроблених даних, хоча я опускаю стовпець (AutoClassName) після оновлення нормалізації. Мені також цікаво, чи варто мені просто циклічно записувати таблицю за один раз замість ПРИЄДНАЙТЕСЯ, що здавалося смішним у той час, коли я починав це, але зараз, здається, це було б швидше.

Як я повинен швидше змінити свою методологію для своїх останніх оновлень щодо нормалізації (подібних до цієї)?

Відповіді:


7

Ви намагаєтесь зробити це як окрема (дуже велика) транзакція. Натомість робіть оновлення меншими партіями.

Ви також отримаєте користь від:

  • Тимчасовий індекс на AutoData.dbo.AutoClass.AutoClassName
  • Більше оперативної пам’яті. Лот більше оперативної пам'яті.

1
+1 Я погоджуюся з оновленням пакетів за допомогою TOPпункту. Це був би мій підхід.
Томас Стрінгер

Якщо я актуалізую TOP TOP, тоді мені знадобиться пункт WHERE (ДЕ AutoClassID NULL)? Чи не було б пункт WHERE не ввести новий показник ефективності (сканування таблиці, якого я зараз не роблю). Без сумніву, це зменшить проблему оперативної пам'яті, яку я маю з приєднанням.
Кріс Адранья

Моя відповідь давно назріла, але в моєму випадку SET ROWCOUNT виявився найбільш ефективним.
Кріс Адранья

10

Я б застосував інший підхід.

Замість того, щоб оновлювати існуючі таблиці, просто створіть нову таблицю, в якій є те, що вам потрібно.

Це майже напевно буде швидше:

SELECT DISTINCT
    AutoClassID,
    <Other fields>
INTO
    AutoDataImportStaging.dbo.Automobile
FROM
    AutoData.dbo.AutoClass

Як написано в даний час, відбувається багато логічних операцій:

  • Прочитайте всі значення A.AutoClassName
  • Прочитайте всі значення B.AutoClassName
  • Порівняйте значення A і B
  • З відповідного набору прочитайте всі значення B.AutoClassID
  • Оновіть існуючі значення A.AutoClassId на значення B.AutoClassId за допомогою будь-яких індексів

Це звучить як приємний, простий підхід, особливо з огляду на проблему вводу / виводу диска, яка у мене є. Дякую, що відповіли так швидко.
Кріс Адранья

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

5

Перекидання таблиці по одному рядку, не буде швидше!

Як підозрюється та підтверджено вами, це буде пов'язано з введенням-виведенням - наявність одного диска, читання, запису, журналів транзакцій та (будь-якого) робочого простору тимчасового режиму будуть конкурувати за той самий ввід.

Просте відновлення все ще запише транзакції, але журнал буде очищено контрольною точкою. Можливо, що початковий розмір журналу та параметри автоматичного зростання викликають деяке сповільнення вводу-виводу - журнал транзакцій повинен буде зростати, щоб уникнути зміни.

Ви спробували індексувати поле AutoClassName? Скільки існує різних значень автоматичного класу?

Можливо, вам доведеться проводити пакетне оновлення, виходячи з обмежень вашого вводу-виводу. Тож оновіть 1 мільйон, контрольно-пропускний пункт, повторіть….


Існує лише 15 різних значень автоматичного класу. Ваші коментарі підтверджують багато моїх підозр (і болю!). Дякую за відповідь.
Кріс Адранья

3

Створіть індекси для полів приєднання.

Ви завжди можете скидати індекси, коли закінчите.

Я був би дуже здивований, якби показники не суттєво покращили ефективність оновлення.


Я впевнений, що показники покращаться. Я думаю, питання полягає в тому, чи покращуються вони більше, ніж часу, необхідного для створення індексу (лише для одного використання). Напевно, так. :)
Кріс Адранья

3

Експортуйте так, як вам потрібно, створіть нову таблицю та імпортуйте назад. Як бонус, ви мали б копію даних як резервну копію, якщо трапляться чудеса.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.