views:

194

answers:

3

I have two tables with 10-20 million rows that have GUID primary keys and at leat 12 tables related via foreign key. The base tables have 10-20 indexes each.

We are moving from GUID to BigInt primary keys. I'm wondering if anyone has any suggestions on an approach. Right now this is the approach I'm pondering:

  1. Drop all indexes and fkeys on all the tables involved.
  2. Add 'NewPrimaryKey' column to each table
  3. Make the key identity on the two base tables
  4. Script the data change "update table x, set NewPrimaryKey = y where OldPrimaryKey = z
  5. Rename the original primarykey to 'oldprimarykey'
  6. Rename the 'NewPrimaryKey' column 'PrimaryKey'
  7. Script back all the indexes and fkeys

Does this seem like a good approach? Does anyone know of a tool or script that would help with this?

TD: Edited per additional information. See this blog post that addresses an approach when the GUID is the Primary: http://www.sqlmag.com/blogs/sql-server-questions-answered/sql-server-questions-answered/tabid/1977/entryid/12749/Default.aspx

+3  A: 

Your approach is how I would do it.

Do you really need bigint? a regular 4 byte int will go to 2 billion (2,147,483,647).

int, bigint, smallint, and tinyint

KM
We could hit that in 10 years or so.... is this simply a space issue or would an int provide drastically better performance on the indexes?
Tom DeMille
16 bytes for guid (uniqueidentifier), or 8 for bigint, or just 4 bytes for regular int. This isn't just space on disk, but also the in memory cache. Also,you'll get more keys on a page (faster lookup), and every index includes the PK, so the smaller the better.
KM
A: 

It certainly sounds like this strategy would work -- dropping the constraints, changing the column out from underneath them (type changes, name remains the same), and then recreating the constraints is fairly elegant.

Is the goal to ultimately drop the GUID columns? If so, you won't actually reclaim the space unless the tables are copied or rebuilt, so maybe the following adjustment:

...
4.Script the data change "update table x, set NewPrimaryKey = y where OldPrimaryKey = z
5.Drop the original primarykey to 'oldprimarykey'
6.Rename the 'NewPrimaryKey' column 'PrimaryKey'
7.Script back all the indexes and fkeys (building clustered indexes "rebuilds" tables)
8.For all tables that don't have clustered indexes, do something to make sure they get rebuilt and their space is reclaimed (such build and then drop a clustered index)

Needless to say, test it on a dev box before running on Production!

Philip Kelley
For backwards compat to some old emails with links we need to keep the old ID in the two base tables so if an old link comes in we can locate it, otherwise, on the related tables we can drop the old column
Tom DeMille
A: 

I'd also add:

Make sure you have a good current backup before starting. Change the server to run in single user mode (notify users of an outage period first). You do not want users to try to enter data while this is going on.

HLGEM