2008-08-08 40 views
38

Tengo varias tablas cuyos únicos datos exclusivos son columnas uniqueidentifier (Guid). Debido a que las guías no son secuenciales (y están generadas por el lado del cliente, por lo que no puedo usar newsequentialid()), he hecho un índice no primario, no agrupado en este campo ID en lugar de dar a las tablas un primario agrupado llave.Tablas sin clave principal

Me pregunto cuáles son las implicaciones de rendimiento para este enfoque. He visto a algunas personas sugerir que las tablas deben tener una int interna de incremento automático ("identidad") como clave principal en clúster, incluso si no tiene ningún significado, ya que significa que el motor de la base de datos en sí puede usar ese valor para rápidamente busca una fila en lugar de tener que usar un marcador.

Mi base de datos se ha duplicado en varios servidores, por lo que me he alejado de las columnas de identidad en int, ya que son un poco complicadas para obtener la replicación correcta.

¿Cuáles son sus pensamientos? ¿Las tablas deben tener claves primarias? ¿O está bien no tener ningún índice agrupado si no hay columnas sensatas para indexar de esa manera?

+0

Como está haciendo la replicación, sus identidades correctas son algo de lo que no hay que preocuparse. Convertiría tu GUID en una clave principal pero no agrupada ya que no puedes usar newsequentialid. Eso me parece tu mejor opción. Si no lo convierte en PK, sino que pone un índice único en él, tarde o temprano puede hacer que las personas que mantienen el sistema no entiendan las relaciones FK introduciendo errores de forma adecuada. – HLGEM

Respuesta

32

Al tratar con índices, debe determinar para qué se va a usar su tabla. Si está insertando principalmente 1000 filas por segundo y sin hacer ninguna consulta, entonces un índice agrupado es un acierto para el rendimiento. Si realiza 1000 consultas por segundo, no tener índice generará un rendimiento muy malo. Lo mejor que se puede hacer al intentar ajustar consultas/índices es usar Query Plan Analyzer y SQL Profiler en SQL Server. Esto le mostrará dónde se está ejecutando escaneos de tabla costosos u otros bloqueadores de rendimiento.

En cuanto al argumento GUID vs ID, puede encontrar personas en línea que juran por ambos. Siempre me han enseñado a usar GUID a menos que tenga una buena razón para no hacerlo. Jeff tiene una buena publicación que habla sobre las razones para usar los GUID: http://www.codinghorror.com/blog/archives/000817.html.

Como con casi todo lo relacionado con el desarrollo, si busca mejorar el rendimiento no hay una única respuesta correcta. Realmente depende de lo que intenta lograr y cómo está implementando la solución. La única respuesta verdadera es probar, probar y probar nuevamente contra las métricas de rendimiento para garantizar que cumpla con sus objetivos.

[Editar] @Matt, después de investigar un poco más sobre el debate GUID/ID me encontré con esta publicación. Como mencioné antes, no hay una verdadera respuesta correcta o incorrecta. Depende de sus necesidades específicas de implementación. Pero estas son algunas razones muy válidas para utilizar GUID como clave principal:

Por ejemplo, no es un problema conocido como un "punto caliente", donde algunas páginas de datos en una tabla están bajo relativamente alta contención moneda. Básicamente, lo que sucede es que la mayor parte del tráfico en una tabla (y por lo tanto bloqueos a nivel de página) ocurre en un área pequeña de la tabla, hacia el final. Los nuevos registros siempre irán a este punto de acceso, porque IDENTITY es un generador de números secuencial. Estos insertos son problemáticos porque requieren un bloqueo de página Exlusive en la página a la que se agregan (el punto de acceso). Esto serializa eficazmente todas las inserciones en una tabla gracias al mecanismo de bloqueo de página. NewID(), por otro lado, no sufre hotspots. Los valores generados con la función NewID() solo son secuenciales para ráfagas cortas de insertos (donde la función se llama muy rápidamente, como durante una inserción de varias filas), lo que provoca que las filas insertadas se distribuyan aleatoriamente en todas las páginas de datos de la tabla de todos al final, eliminando así un punto de acceso de inserts.

Además, como las inserciones se distribuyen aleatoriamente, la posibilidad de divisiones de página se reduce considerablemente.Mientras que una página se divide aquí y no está demasiado mal, los efectos se suman rápidamente. Con IDENTIDAD, la página Factor de relleno es bastante inútil como mecanismo de ajuste y también podría establecerse al 100%: las filas nunca se insertarán en ninguna página, sino en la última. Con NewID(), puede utilizar Fill Factor como herramienta de habilitación del rendimiento. Puede establecer Factor de relleno en un nivel que se aproxima al crecimiento de volumen estimado entre reconstrucciones de índice, y luego programar las reconstrucciones durante las horas de menor actividad utilizando dbcc reindex. Esto efectivamente retrasa los resultados de rendimiento de las divisiones de página hasta las horas de menor actividad.

Si incluso piensa en, es posible que tenga que habilitar la replicación para la tabla en cuestión, entonces también podría hacer de PK un identificador único y marcar el campo guid como ROWGUIDCOL. La replicación requerirá un campo guid con un valor único con este atributo, y agregará uno si no existe ninguno. Si existe un campo adecuado, entonces solo usará el que está allí.

Sin embargo, otro gran beneficio para el uso de los GUID de PK es el hecho de que el valor es de hecho garantizada única - no sólo entre todos los valores generados por este servidor, pero todos los valores generados por todos computadoras - ya se trate de su servidor db, servidor web, servidor de aplicaciones o máquina cliente. Casi todos los lenguajes modernos tienen la capacidad de generar un guid válido ahora. En .NET puede usar System.Guid.NewGuid. Esto es MUY útil cuando se trata de conjuntos de datos de detalles maestros en caché en particular. No tienes que emplear esquemas de claves temporales locas solo para relacionar tus registros antes de que se cometan. Simplemente obtiene un nuevo Guid perfectamente válido del sistema operativo para el valor de la clave permanente de cada nuevo registro en el momento en que se crea el registro.

http://forums.asp.net/t/264350.aspx

+2

Lea Kimberly Tripp's [GUIDs como clave principal y/o clúster] (http://sqlskills.com/BLOGS/KIMBERLY/post/GUIDs-as-PRIMARY-KEYs-andor-the-clustering-key.aspx) y [Disco el espacio es barato, ¡eso es ** NO ** el punto!] (http://www.sqlskills.com/BLOGS/KIMBERLY/post/Disk-space-is-cheap.aspx) y muchas más de sus excelentes publicaciones en el blog - ella ** claramente ** muestra qué mala idea es una clave de agrupación en una columna GUID. Además, los hotspots son un mito que hace tiempo que se desacreditó, ya no es un problema en ningún momento después de SQL Server 6.5 .... –

+1

Fascinante. Examinaré la opción "divisiones de página e índices reconstruidos" si el rendimiento se convierte en un problema. Gracias por eso. –

0

Yo también siempre he escuchado que tener una int incremental automática es buena para el rendimiento incluso si no la usa realmente.

7

La clave primaria tiene tres propósitos:

  • indica que la columna (s) debe ser único
  • indica que la columna (s) debe ser no nulo
  • documentar la intención de que este sea el identificador único de la fila

Las dos primeras se pueden especificar de muchas maneras, como ya lo has hecho.

La tercera razón es buena:

  • para los seres humanos, por lo que se puede ver fácilmente su intención
  • para el equipo, por lo que un programa que pueda comparar o procesar su mesa de lo contrario puede consultar la base de datos para el la clave principal de la mesa

Una clave principal no tiene que ser un campo numérico de incremento automático, por lo que diría que es una buena idea especificar su columna guid como clave principal.

+0

Definitivamente no es una buena idea tener una columna guid como clave principal, porque las claves primarias están agrupadas y las guiones son aleatorias. Eso significa que cada vez que inserte una nueva fila, su tabla se reestructurará esencialmente en el disco. La gente normalmente aconseja que las claves primarias deben ser secuenciales, tipos en constante crecimiento, de modo que cada nueva fila se pegue al final de la tabla. –

+0

Una clave principal está respaldada por defecto por un índice agrupado, pero se puede eliminar (el índice agrupado). –

+0

@MattHamilton re "... no es una buena idea tener una columna guid como clave principal, porque las claves primarias están agrupadas y las guids son aleatorias" para superar esto, puede usar la función "newsequentialid()" en SQL 2005/Edición de 2008: encontró el requisito [CodingHorror post] (http://www.codinghorror.com/blog/archives/000817.html) que habla de esto ;-) –

1

Una clave principal no necesita ser un campo de autoincrementing, en muchos casos esto solo significa que está complicando la estructura de su tabla.

En su lugar, una clave principal debe ser la colección mínima de atributos (tenga en cuenta que la mayoría de los DBMS permitirá una clave primaria compuesta) que identifica de forma única una tupla.

En términos técnicos, debería ser el campo en el que todos los demás campos de la tupla dependan totalmente funcionalmente. (Si no es así, es posible que deba normalizar).

En la práctica, los problemas de rendimiento pueden significar que combina tablas, y utiliza un campo de incrementación, pero me parece recordar algo acerca de la optimización prematura siendo malos ...

6

simplemente entraban, porque Matt me ceba un poco .

Debe comprender que aunque un índice agrupado se coloca en la clave principal de una tabla de manera predeterminada, los dos conceptos son independientes y deben considerarse por separado. Un CIX indica la forma en que los datos son almacenados y referidos por los NCIX, mientras que el PK proporciona una singularidad para cada fila para satisfacer los requisitos LÓGICOS de una tabla.

Una tabla sin un CIX es solo un montón. Una tabla sin PK a menudo se considera "no una tabla". Lo mejor es obtener una comprensión de los conceptos de PK y CIX por separado para que pueda tomar decisiones sensatas en el diseño de la base de datos.

Rob

3

Nadie respondió a la pregunta real: ¿cuáles son ventajas/desventajas de una tabla sin PK NOR un índice agrupado. En mi opinión, si optimiza inserciones más rápidas (especialmente inserción incremental masiva, p. Ej. Cuando carga datos a granel en una tabla no vacía), tal tabla: sin índice agrupado, SIN restricciones, SIN claves externas, NO valores predeterminados y NO Primary Key, en una base de datos con Simple Recovery Model, es la mejor. Ahora, si alguna vez desea consultar esta tabla (en lugar de escanearla en su totalidad), puede agregar un índice no agrupado no exclusivo según sea necesario pero mantenerlo al mínimo.

+0

En realidad, esto está ** mal ** - como Kimberly Tripp (La reina de la indexación) muestra claramente: tener un ** buen ** índice agrupado ** aumentará ** el rendimiento de INSERTAR! http: // sqlskills.com/BLOGS/KIMBERLY/post/The-Clustered-Index-Debate-Continues.aspx –

+0

No llamaría a eso _clearly_ mostrando :) Habla sobre principios generales, no respalda su afirmación con, bueno, nada, mientras estoy hablando de un escenario muy específico que he encontrado en mi práctica: inserciones masivas de potencialmente cientos de millones de registros en una tabla no vacía, que luego nunca se actualiza ni se accede en un modo de lectura aleatoria, pero solo se escanea en su totalidad. Sin embargo, supongo que podría haber más factores en juego que los índices. Siempre prueba tus optimizaciones niños. – zvolkov

0

Como está haciendo la replicación, sus identidades correctas son algo de lo que no hay que preocuparse. Convertiría tu GUID en una clave principal pero no agrupada ya que no puedes usar newsequentialid. Eso me parece tu mejor opción. Si no lo convierte en PK, sino que pone un índice único en él, tarde o temprano puede hacer que las personas que mantienen el sistema no entiendan las relaciones FK introduciendo errores de forma adecuada.

Cuestiones relacionadas