views:

228

answers:

4

I'm fairly well versed in SQL server performace but I constanly have to argue down the idea that GUIDs should be used as the default type for Clusterd Primary Keys.

Assuming that the table has a fairly low amount of inserts per day (5000 +/- rows / day), what kind of performace issues could we run into? How will page splits affect our seek performance? How often should I reindex (or should I defrag)? What should I set the fill factors to (100, 90, 80, ect)?

What if I were inserting 1,000,000 rows per day?

I apologize beforhand for all of the questions, but i'm looking to get some backup for not using GUIDs as our default for PKs. I am however completely open to having my mind changed by the overwehlming knowledge from the StackOverflow user base.

+2  A: 

Drawbacks of using GUID as primary key:

  • No meaningful ordering, means indexing doesn't give performance boost as it does with an integer.
  • Size of a GUID 16 bytes, versus 2, 4 or 8 bytes for an integer.
  • Very difficult for humans to remember, so no good as a reference id.

Advantages:

  • Allow non-guessable primary keys that can therefore be less dangerous when displayed in a web page query string or in the application.
  • Useful in Databases that don't provide an auto increment or identity data type.
  • Useful when you need to join data between two disparate data sources across platforms or environments.

I thought the decision as to whether to use GUIDs was pretty simple, but maybe I'm unaware of other issues.

Ash
GUIDs are important as IDs when datasets or partial datasets may need to be merged from disparate sources.
Rex M
@Rex, good point, I've added this as an advantage.
Ash
At a former company: We ran childcare web-services and many of the companies which were all in seperate databases were merging and buying oneanoter out. The lead developer had decided on GUIDs for PK's which made the merging of the companies Extremely simple. It howerver went out of biz after not being able to pass benchmarks by LoadRunner (100% CPU on Index scans/seeks). Abysmal performance...
NTDLS
@NTDLS, yes, I would normally not make the non-clustered index a GUID, but certainly creating another column as a GUID, and using a clustered index on it, would be ok for that scenario.
Ash
Sorry reverse "clustered", "non-clustered" in my previous comemnt.
Ash
+1  A: 

With such a low inserts per day, I doubt that page splitting should be a significant factor. The real question is how does 5,000 compares with the existing row count, as this would be the main information needed to decide on an appropriate initial fill factor to deffer splits.

This said, I'm personally not a big fan of GUIDs. I understand that they can serve well in some contexts but in many cases they are just "in the way" [of efficiency, of ease of use, of ...]

I find the following questions useful to narrow down on deciding whether GUID should be used or not.

  • Will the PK be shared/published ? (i.e. will it be used beyond its internal use within SQL, will applications need these keys in a somewhat persistent fashion? Will users somehow see these keys?
  • Could the PK be used to help merge disparate data sources ?
  • Does the table have a primary -possibly composite- made from column(s) in the data ? What is the size of this possible this key
  • How do the primary keys sort? If composite, are the first few columns selective ?
mjv
+6  A: 

If you are doing any kind of volume, GUIDs are extremely bad as a PK bad unless you use sequential GUIDs, for the exact reasons you describe. Page fragmentation is severe:

                 Average                    Average
                 Fragmentation  Fragment    Fragment   Page     Average 
Type             in Percent     Count       Size       Count    Space Used

id               4.35           7           16.43      115      99.89
newidguid        98.77          162         1          162      70.90 
newsequentualid  4.35           7           16.43      115      99.89

And as this comparison between GUIDs and integers shows:

Test1 caused a tremendous amount of page splits, and had a scan density around 12% when I ran a DBCC SHOWCONTIG after the inserts had completed. The Test2 table had a scan density around 98%

If your volume is very low, however, it just doesn't matter that much.

If you do really need a globally unique ID but have high volume (and can't use sequential IDs), just put the GUIDs in an indexed column.

Rex M
This podcast contains a good conversation about the problems of non-sequential GUIDs as primary keys http://www.dotnetrocks.com/default.aspx?showNum=455.
I Have the Hat
Average space used seems down....
RCIX
A: 

Using a guid (unless it is a sequential GUID) as a clustered index is going to kill insert performance. Since the physical table layout is aligned according to the clustered index, using a guid which has a random sequencing order will cause serious table fragmentation. If you want to use a guid as a PK/Clustered index it must be a sequential guid using the newsequentialid() function in sql server. This will guarantee that the generated guids are ordered sequentially and prevent fragmentation.

Matt Wrock