sql-server - tablas - tipos de restricciones en base de datos
Tablas sin clave principal (7)
Tengo varias tablas cuyos únicos datos únicos son una columna uniqueidentifier (un 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.
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 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 identity int ya que son un poco complicadas para obtener la replicación correcta.
¿Cuáles son tus pensamientos? ¿Las tablas deben tener claves principales? ¿O está bien no tener ningún índice agrupado si no hay columnas sensatas para indexar de esa manera?
Al tratar con índices, debe determinar para qué se 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 bastante válidas para usar GUID como clave principal:
Por ejemplo, existe un problema conocido como "zona activa", donde ciertas páginas de datos en una tabla se encuentran en una disputa de moneda relativamente alta. 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, debido a que las inserciones se distribuyen aleatoriamente, la probabilidad 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 a un nivel que se aproxime 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 que podría necesitar habilitar la replicación para la tabla en cuestión, entonces también podría hacer que PK sea 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í.
Otra gran ventaja del uso de GUID para PK es el hecho de que el valor es realmente único, no solo entre todos los valores generados por este servidor, sino todos los valores generados por todas las computadoras, ya sea su servidor db, servidor web, servidor de aplicaciones , o máquina del 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.
La clave principal tiene tres propósitos:
- indica que la columna (s) debe ser única
- indica que la columna (s) no debe ser nula
- documentar el intento de que este sea el identificador único de la fila
Los dos primeros se pueden especificar de muchas maneras, como ya lo has hecho.
La tercera razón es buena:
- para los humanos, para que puedan ver fácilmente su intento
- para la computadora, por lo que un programa que pueda comparar o procesar su tabla puede consultar la base de datos de la clave principal de la tabla.
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.
Nadie respondió una pregunta real: ¿cuáles son las ventajas y desventajas de una tabla sin PK ni índice CLUSTERED? En mi opinión, si optimiza para inserciones más rápidas (especialmente inserción incremental masiva, por ejemplo cuando carga datos a granel en una tabla no vacía), tal tabla: sin índice agrupado, SIN restricciones, SIN claves externas, sin 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.
Solo estoy saltando, porque Matt me ha molestado un poco.
Debe comprender que, si bien 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 se almacenan y hacen referencia a 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 Heap. 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.
Robar
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 cambio, 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 de la funcionalidad. (Si no es así, es posible que deba normalizar).
En la práctica, los problemas de rendimiento pueden significar que fusionas tablas y usas un campo de incremento, pero parece que recuerdo algo acerca de que la optimización prematura es mala ...
Ya que está haciendo la replicación, sus identidades correctas son algo de lo que hay que librarse. 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.
Yo también siempre he escuchado que tener un int. De incremento automático es bueno para el rendimiento incluso si no lo usas realmente.