Подход к изменению первичного ключа с GUID на BigInt в связанных таблицах SQL Server

У меня есть две таблицы с 10-20 миллионами строк, которые имеют первичные ключи GUID и не менее 12 таблиц, связанных через внешний ключ. Базовые таблицы имеют по 10-20 индексов каждая.

Мы переходим от GUID к первичным ключам BigInt. Мне интересно, есть ли у кого-нибудь предложения по подходу. Прямо сейчас это подход, который я обдумываю:

  1. Отбросьте все индексы и fkeys для всех задействованных таблиц.
  2. Добавьте столбец NewPrimaryKey в каждую таблицу.
  3. Сделайте идентификатор ключа на двух базовых таблицах
  4. Скрипт изменения данных "обновить таблицу x, установить NewPrimaryKey = y, где OldPrimaryKey = z
  5. Переименуйте исходный первичный ключ в «oldprimarykey».
  6. Переименуйте столбец «NewPrimaryKey» в «PrimaryKey».
  7. Скрипт назад все индексы и fkeys

Это кажется хорошим подходом? Кто-нибудь знает инструмент или скрипт, который поможет с этим?

TD: Отредактировано в соответствии с дополнительной информацией. См. эту запись в блоге, в которой рассматривается подход, когда GUID является основным: http://www.sqlmag.com/blogs/sql-server-questions-answered/sql-server-questions-answered/tabid/1977/entryid/12749/Default.aspx


person Tom DeMille    schedule 28.04.2010    source источник
comment
По какому маршруту вы в итоге пошли? Вдобавок к тому, что вы сказали, приложение должно быть уверено, что PrimaryKey теперь является вашим новым типом данных, а не Guid.   -  person user420667    schedule 12.04.2017


Ответы (3)


Похоже, что эта стратегия определенно сработает — удаление ограничений, изменение столбца из-под них (тип меняется, имя остается прежним), а затем воссоздание ограничений — это довольно элегантно.

Является ли цель в конечном итоге удалить столбцы GUID? Если это так, вы фактически не освободите пространство, если таблицы не будут скопированы или перестроены, поэтому, возможно, будет следующая настройка:

...
4. Скрипт изменения данных "обновить таблицу x, установить NewPrimaryKey = y, где OldPrimaryKey = z
5. Перетащите исходный первичный ключ в 'oldprimarykey'
6. Переименуйте столбец 'NewPrimaryKey' в 'PrimaryKey'
7. С помощью скрипта верните все индексы и fkeys (построение кластеризованных индексов "перестраивает" таблицы)
8. Для всех таблиц, не имеющих кластеризованных индексов, сделайте что-нибудь, чтобы убедитесь, что они перестроены, и их пространство восстановлено (такая сборка, а затем удаление кластеризованного индекса)

Излишне говорить, что перед запуском в продакшен протестируйте его на dev-боксе!

person Philip Kelley    schedule 28.04.2010
comment
Для обратной совместимости с некоторыми старыми электронными письмами со ссылками нам нужно сохранить старый идентификатор в двух базовых таблицах, чтобы, если появится старая ссылка, мы могли найти ее, в противном случае в связанных таблицах мы можем удалить старый столбец. - person Tom DeMille; 28.04.2010

Ваш подход - это то, как я бы это сделал.

Вам действительно нужен bigint? обычный 4-байтовый int будет равен 2 миллиардам (2 147 483 647).

int, bigint, smallint и tinyint

person KM.    schedule 28.04.2010
comment
Мы могли бы достичь этого примерно через 10 лет... это просто проблема с пространством или int обеспечит значительно лучшую производительность для индексов? - person Tom DeMille; 28.04.2010
comment
16 байт для guid (uniqueidentifier), или 8 для bigint, или всего 4 байта для обычного int. Это не только место на диске, но и кеш-память. Кроме того, вы получите больше ключей на странице (более быстрый поиск), и каждый индекс включает ПК, поэтому чем меньше, тем лучше. - person KM.; 28.04.2010

Я бы еще добавил:

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

person HLGEM    schedule 28.04.2010