Mi conocimiento de nivel inferior de SQL (Server 2008) es limitado y ahora está siendo cuestionado por nuestros DBA. Déjame explicarte (he mencionado declaraciones obvias con la esperanza de estar en lo cierto, pero si ves algo mal, dímelo) el escenario:
Tenemos una mesa que contiene 'Órdenes judiciales' para las personas. Cuando creé la tabla, (Nombre: CourtOrder), la creé como:
CREATE TABLE dbo.CourtOrder
(
CourtOrderID INT NOT NULL IDENTITY(1,1), (Primary Key)
PersonId INT NOT NULL,
+ around 20 other fields of different types.
)
Luego apliqué un índice no agrupado a la clave principal (para mayor eficiencia). Mi razón es que es un campo único (clave primaria) y debe indexarse, principalmente con fines de selección, como solemosSelect from table where primary key = ...
Luego apliqué un índice CLUSTER en PersonId. El motivo era agrupar los pedidos de una persona en particular físicamente, ya que la gran mayoría del trabajo es recibir pedidos de una persona. Entonces,select from mytable where personId = ...
Me han detenido en esto ahora. Me han dicho que deberíamos poner el índice agrupado en la clave principal y el índice normal en personId. Eso me parece muy extraño. En primer lugar, ¿por qué pondría un índice agrupado en una columna única? ¿Qué es la agrupación? ¿Seguramente eso es un desperdicio del índice agrupado? Habría creído que se usaría un índice normal en una columna única. Además, agrupar el índice significaría que no podemos agrupar una columna diferente (una por tabla, ¿verdad?).
El motivo por el que me han dicho que he cometido un error es que creen que poner un índice agrupado en PersonId haría que las inserciones fueran lentas. Para el aumento del 5% en la velocidad de una selección, obtendríamos una degradación del 95% en la velocidad en inserciones y actualizaciones. ¿Es eso correcto y válido?
Dicen que debido a que agrupamos el personId, SQL Server tiene que reorganizar los datos cada vez que insertamos o hacemos un cambio en el PersonId.
Entonces, he preguntado, ¿por qué SQL tendría el concepto de ÍNDICE CLÚSTER, si es tan lento? ¿Es tan lento como dicen? ¿Cómo debería haber configurado mis índices para lograr un rendimiento óptimo? Pensé que SELECT se usa más que INSERT ... pero dicen que estamos teniendo problemas de bloqueo en INSERTS ...
Espero que alguien pueda ayudarme.
Respuestas:
La distinción entre un índice agrupado y no agrupado es que el índice agrupado determina el orden físico de las filas en la base de datos . En otras palabras, aplicar el índice agrupado a
PersonId
significa que las filas se ordenarán físicamente porPersonId
en la tabla, lo que permitirá que una búsqueda de índice en esto vaya directamente a la fila (en lugar de un índice no agrupado, que lo dirigirá a la fila ubicación, agregando un paso adicional).Dicho esto, es inusual que la clave principal no sea el índice agrupado, pero no es inaudito. El problema con su escenario es en realidad lo contrario de lo que está asumiendo: desea valores únicos en un índice agrupado, no duplicados. Debido a que el índice agrupado determina el orden físico de la fila, si el índice está en una columna no única, entonces el servidor tiene que agregar un valor de fondo a las filas que tienen un valor de clave duplicado (en su caso, cualquier fila con el mismo
PersonId
) para que el valor combinado (clave + valor de fondo) sea único.Lo único que sugeriría es no usar una
CourtOrderId
columna de clave sustituta (su ) como clave principal, sino usar una clave primaria compuesta de laPersonId
y alguna otra columna o conjunto de columnas de identificación única. Sin embargo, si eso no es posible (o no es práctico), active el índice agrupadoCourtOrderId
.fuente
PersonId
. Está ordenado lógicamente porPersonId
, cualquier discrepancia entre el orden lógico y físico es el grado de fragmentación lógica.De ninguna manera soy un experto en SQL ... así que tome esto como la vista de un desarrollador en lugar de una vista de DBA ...
Las inserciones en índices agrupados (ordenados físicamente) que no están en orden secuencial provocan un trabajo adicional para las inserciones / actualizaciones. Además, si tiene muchas inserciones sucediendo a la vez y todas están ocurriendo en la misma ubicación, terminará con contención. Su rendimiento específico varía según sus datos y cómo accede a ellos. La regla general es construir su índice agrupado en el valor estrecho más exclusivo de su tabla (normalmente el PK)
Supongo que su PersonId no cambiará, por lo que las actualizaciones no entran en juego aquí. Pero considere una instantánea de algunas filas con PersonId de 1 2 3 3 4 5 6 7 8 8
Ahora inserte 20 filas nuevas para PersonId de 3. Primero, dado que esta no es una clave única, el servidor agrega algunos bytes adicionales a su valor (detrás de escena) para hacerlo único (que también agrega espacio adicional) y luego la ubicación donde estos residirán tiene que ser alterados. Compare eso con la inserción de un PK de incremento automático donde las inserciones ocurren al final. La explicación no técnica probablemente se reduciría a esto: hay menos trabajo de 'barajar hojas' que hacer si naturalmente progresan valores más altos al final de la tabla en lugar de volver a trabajar la ubicación de los elementos existentes en esa ubicación mientras inserta sus elementos.
Ahora, si tiene problemas con las inserciones, es probable que esté insertando un montón de valores de PersonId iguales (o similares) a la vez, lo que está causando este trabajo adicional en varios lugares de la tabla y la fragmentación lo está matando. La desventaja de cambiar a la PK agrupada en su caso, es que si tiene problemas de inserción hoy en PersonIds que varían en valor distribuidos en toda la tabla, si cambia su índice agrupado a la PK y todas las inserciones ahora ocurren en una ubicación, su problema puede empeorar debido a una mayor concentración de contención. (Por otro lado, si sus inserciones de hoy no están esparcidas por todas partes, pero generalmente están agrupadas en áreas similares, entonces su problema probablemente se aliviará al cambiar su índice agrupado de PersonId a su PK porque estará minimizando el fragmentación.)
Sus problemas de desempeño deben analizarse para su situación particular y tomar este tipo de respuestas solo como pautas generales. Su mejor opción es confiar en un DBA que pueda validar exactamente dónde se encuentran sus problemas. Parece que tiene problemas de contención de recursos que pueden ir más allá de un simple ajuste de índice. Esto podría ser síntoma de un problema mucho mayor. (Problemas de diseño probables ... de lo contrario limitaciones de recursos).
en cualquier caso, buena suerte!
fuente
Algunos autores sugieren no "desperdiciar" el
CI
en unaidentity
columna si hay una alternativa que beneficiaría las consultas de rango.De las Pautas de diseño de índices agrupados de MSDN, la clave debe elegirse de acuerdo con los siguientes criterios
Tu
CourtOrderID
columna se encuentra2
. TuPersonId
cumple1
y3
. Como la mayoría de las filas terminarán con eluniqueifier
agregado de todos modos, también puede declararlo como único y usarlo,PersonId,CourtOrderID
ya que tendrá el mismo ancho pero será más útil ya que la clave de índice agrupado se agrega a todos los NCI como el localizador de filas y esto permitirá para cubrir más consultas.El problema principal con el uso
PersonId,CourtOrderID
como CI es que probablemente se producirá una fragmentación lógica (y esto afecta particularmente las consultas de rango que está tratando de ayudar), por lo que necesitaría monitorear el factor de relleno y los niveles de fragmentación y realizar el mantenimiento del índice con más frecuencia.fuente
Se explica en el siguiente enlace: https://msdn.microsoft.com/en-us/ms190457.aspx
Agrupado
Los índices agrupados ordenan y almacenan las filas de datos en la tabla o vista según sus valores clave. Estas son las columnas incluidas en la definición del índice. Solo puede haber un índice agrupado por tabla, porque las filas de datos en sí mismas se pueden ordenar en un solo orden.
La única vez que las filas de datos de una tabla se almacenan ordenadas es cuando la tabla contiene un índice agrupado. Cuando una tabla tiene un índice agrupado, la tabla se denomina tabla agrupada. Si una tabla no tiene un índice agrupado, sus filas de datos se almacenan en una estructura desordenada llamada montón.
No agrupado
Los índices no agrupados tienen una estructura separada de las filas de datos. Un índice no agrupado contiene los valores clave del índice no agrupado y cada entrada de valor clave tiene un puntero a la fila de datos que contiene el valor clave .
El puntero de una fila de índice en un índice no agrupado a una fila de datos se denomina localizador de filas. La estructura del localizador de filas depende de si las páginas de datos se almacenan en un montón o en una tabla agrupada. Para un montón, un localizador de filas es un puntero a la fila. Para una tabla agrupada, el localizador de filas es la clave de índice agrupada.
Puede agregar columnas sin clave al nivel de hoja del índice no agrupado para omitir los límites de clave de índice existentes, 900 bytes y 16 columnas de clave, y ejecutar consultas indexadas y totalmente cubiertas.
fuente
Algunas bases de datos con algunas selecciones desagradables, se unen en un procedimiento almacenado; la única diferencia es el índice
ÍNDICES: agrupados frente a no agrupados
fuente