2010-08-10 13 views
5

Estoy tratando de entender cómo el guiado secuencial funciona mejor que un guid regular.Guía secuencial y fragmentación

¿Es porque con el guid regular, el índice usa el último byte del guid para ordenar? Dado que es aleatorio, causará mucha fragmentación y división de páginas, ya que a menudo moverá los datos a otra página para insertar nuevos datos.

Guid seinential es secuencial, causará mucho menos divisiones de página y fragmentación?

¿Es correcto mi entendimiento?

Si alguien puede arrojar más luces sobre el tema, lo apreciaré mucho.

Gracias

EDIT:

secuencial GUID = NEWSEQUENTIALID(),

GUID Regular = NEWID()

+0

Es posible que desee definir lo que quiere decir con "guid secuencial" y especialmente "guid regular". –

+2

@Greg: creo que se refiere a un "guiado secuencial" generado por NEWSEQUENTIALID() frente a un "guid regular" generado por NEWID() –

Respuesta

8

que te han dicho casi todo en su pregunta.

Con un GUID secuencial/clave principal, se agregarán nuevas filas juntas al final de la tabla, lo que simplifica las cosas para el servidor SQL. En comparación, una clave primaria aleatoria significa que se pueden insertar nuevos registros en cualquier lugar de la tabla; es muy probable que la última página de la tabla esté en la memoria caché (si es allí donde van todas las lecturas), sin embargo, la posibilidad de una página aleatoria en el medio de la tabla que está en la memoria caché es bastante baja, lo que significa que se requiere IO adicional.

Además de eso, al insertar filas en el medio de la tabla existe la posibilidad de que no haya espacio suficiente para insertar la fila adicional. Si este es el caso, entonces SQL Server necesita realizar costosas operaciones IO adicionales para crear espacio para el registro; la única forma de evitar esto es tener espacios dispersos entre los datos para permitir la inserción de registros adicionales (conocido como Factor de relleno), que en sí mismo causa problemas de rendimiento porque los datos se distribuyen en más páginas y, por lo tanto, se necesita más IO para acceder a toda la tabla.

+0

¡Gracias! Solo quería confirmar que lo entendí correctamente. – pdiddy

2

delego en la sabiduría de Kimberly L. Tripp sobre este tema:

Pero, un GUID que no es secuencial - como uno que h ya que es valora generado en el cliente (utilizando .NET) o generados por la función newid() (en SQL Server) puede ser un horrible mal elección - sobre todo debido a la fragmentación que crea en la tabla de base pero también debido a su tamaño . Es innecesariamente amplio (es 4 veces más ancho que una identidad basada en int - que le puede dar 2 mil millones (realmente, 4 mil millones) filas únicas). Y, si necesita más de 2 mil millones, siempre puede ir con un bigint (8-byte int) y obtener 263-1 filas.

Leer más: http://www.sqlskills.com/BLOGS/KIMBERLY/post/GUIDs-as-PRIMARY-KEYs-andor-the-clustering-key.aspx#ixzz0wDK6cece

+0

Con Sequential Guid, ya que es secuencial, técnicamente todas las páginas de índice nuevas serán, en teoría, secuenciales mejorando así el rendimiento. ¿Lo estoy entendiendo correctamente? Para guid regular, los registros estarán por todos lados, ya que son aleatorios, por lo tanto, hacer una declaración de selección regular con un rango puede ser lenta. – pdiddy

+0

@pdiddy - bueno, dado que los GUIDs "aleatorios" no son secuenciales, ¿por qué seleccionarías un rango de ellos? – JNK

+2

Tiene razón acerca de la naturaleza secuencial frente a la aleatoria, sin embargo, el verdadero dolor está en INSERT en lugar de en SELECT. –

0

Para visualizar la imagen completa util named ostress puede ser utilizado. P. ej.puede crear dos tablas: una con normales GUID como PK, otro con secuencial GUID:

-- normal one 
CREATE TABLE dbo.YourTable(
    [id] [uniqueidentifier] NOT NULL, 
    CONSTRAINT [PK_YourTable] PRIMARY KEY NONCLUSTERED (id) 
); 
-- sequential one 
CREATE TABLE dbo.YourTableSeq(
    [id] [uniqueidentifier] NOT NULL CONSTRAINT [df_yourtable_id] DEFAULT (newsequentialid()), 
    CONSTRAINT [PK_YourTableSeq] PRIMARY KEY NONCLUSTERED (id) 
); 

Luego, con un determinado util ejecuta un numbero de insertos con la selección de las estadísticas sobre el índice de fragmentación:

ostress -Slocalhost -E -dYourDB -Q"INSERT INTO dbo.YourTable VALUES (NEWID()); SELECT count(*) AS Cnt FROM dbo.YourTable; SELECT AVG_FRAGMENTATION_IN_PERCENT AS AvgPageFragmentation, PAGE_COUNT AS PageCounts FROM sys.dm_db_index_physical_stats (DB_ID(), NULL, NULL , NULL, N'LIMITED') DPS INNER JOIN sysindexes SI ON DPS.OBJECT_ID = SI.ID AND DPS.INDEX_ID = SI.INDID WHERE SI.NAME = 'PK_YourTable';" -oE:\incoming\TMP\ -n1 -r10000 

ostress -Slocalhost -E -dYourDB -Q"INSERT INTO dbo.YourTableSeq DEFAULT VALUES; SELECT count(*) AS Cnt FROM dbo.YourTableSeq; SELECT AVG_FRAGMENTATION_IN_PERCENT AS AvgPageFragmentation, PAGE_COUNT AS PageCounts FROM sys.dm_db_index_physical_stats (DB_ID(), NULL, NULL , NULL, N'LIMITED') DPS INNER JOIN sysindexes SI ON DPS.OBJECT_ID = SI.ID AND DPS.INDEX_ID = SI.INDID WHERE SI.NAME = 'PK_YourTableSeq';" -oE:\incoming\TMP\ -n1 -r10000 

Luego, en el archivo E: \ incoming \ TMP \ query.out, encontrará sus estadísticas. Mis resultados son:

"Normal" GUID: 
Records AvgPageFragmentation  PageCounts   
---------------------------------------------- 
1000  87.5      8      
2000  93.75     16     
3000  96.15384615384616  26     
4000  96.875     32     
5000  96.969696969696969  33     
10000  98.571428571428584  70     


Sequential GUID: 
Records AvgPageFragmentation  PageCounts   
---------------------------------------------- 
1000  83.333333333333343  6      
2000  63.636363636363633  11     
3000  41.17647058823529  17     
4000  31.818181818181817  22     
5000  25.0      28     
10000  12.727272727272727  55  

Como se puede ver con secuencialmente genera GUID que se inserta, el índice es mucho menos fragmentada como la operación de inserción conduce a la nueva asignación más raro página.