¿Qué sucede durante las inserciones "grandes" en una mesa con una clave compuesta agrupada?

8

Mi conocimiento de SQL es limitado, por lo que los términos que usaré probablemente no sean los correctos.

Tengo una tabla que almacenará los resultados de las pruebas, para múltiples ubicaciones.

Las pruebas se registrarán en diferentes bases de datos en diferentes ubicaciones (sin conexión de red) y la ubicación "maestra" regularmente "importará" los resultados de la prueba desde las otras ubicaciones.

Planeo tener una clave principal compuesta en clúster en las columnas LocationId (int) y Date (datetime), en ese orden. El razonamiento es que debería mantener todos los resultados de una ubicación juntos y casi nunca haré una consulta por rango de fechas, sino por rango de fechas y ubicación.

El tamaño de la fila será de 80 a 100 bytes y el número de resultados de la prueba no debe exceder algunos millones. Una "importación" típica insertará de 50 a 100 mil resultados de otra ubicación.

¿Qué pasará durante las importaciones? ¿SQL "moverá" las filas existentes para mantener el agrupamiento, o permitirá que la tabla se "fragmente"? ¿Podría esto causar un gran impacto en el rendimiento si la importación se realiza una fila a la vez? ¿Debería preferir no molestarme con el orden de las filas y simplemente agregar una columna de identidad como clave principal y un índice en la columna Fecha para ayudar con mis consultas?

Sacha K
fuente

Respuestas:

19

Santa vaca, tienes muchas preguntas aquí. Analicemos esto.

P: ¿SQL "moverá" las filas existentes para mantener la agrupación, o permitirá que la tabla se "fragmente"?

Piense en una base de datos como una colección de páginas: trozos de papel literales dispuestos en su escritorio. Piensa en el diccionario por ahora. Si desea agregar más palabras al diccionario, puede agregarlas en su lugar si las páginas tienen un espacio vacío.

Cuando comienzas con un diccionario vacío, esto es relativamente fácil. Pero piense en un diccionario maduro con miles de páginas en papel, todo lleno.

Cuando desee agregar más palabras a ese diccionario maduro, es probable que no quede espacio en la página. SQL Server "rasgará" una página; tomará una página nueva en otro lugar y moverá algunas de las palabras a esa nueva página. La nueva página estaría al final del diccionario. La buena noticia es que inmediatamente después de esa acción, ahora hay una página medio vacía al final de su diccionario, y también en el medio, ambas con espacio para agregar palabras.

Si los agrega en ese orden, es decir. (Es por eso que la forma en que carga los datos se vuelve cada vez más importante).

¿Podría esto causar un gran impacto en el rendimiento si la importación se realiza una fila a la vez?

Olvide el índice por un segundo: agregar datos una fila a la vez es simplemente ineficiente, independientemente de la estructura de indexación. SQL Server es un sistema basado en conjuntos: siempre que pueda trabajar en conjuntos, probablemente debería hacerlo.

¿Qué sucede cuando consulto los datos?

No preguntaste esto, pero te lo pregunto, jajaja.

Piense en las secuelas de nuestros insertos. Ahora tenemos un diccionario que está ordenado principalmente, pero cuando llegue a algunos puntos del diccionario, tendrá que saltar hacia atrás para leer desde algunas otras páginas. Si todas estas páginas están en caché en su memoria (RAM, grupo de búferes, etc.), la sobrecarga no será tan grande. La mayor parte del acceso a la memoria es aleatorio de todos modos: no es como si SQL Server almacena su diccionario en la memoria en orden.

Por otro lado, si necesita obtener los datos de los discos duros magnéticos convencionales (óxido giratorio), puede obtener un beneficio de rendimiento si esos datos se almacenan en orden. Sin embargo, el objetivo real del diseño aquí es obtener los datos de la RAM en lugar de obtenerlos de las unidades. La diferencia entre los datos desfragmentados en el disco y los datos fragmentados en el disco no es tan significativa como la diferencia entre obtenerlos del disco y obtenerlos de la RAM .

¿Debería preferir no molestarme con el orden de las filas y simplemente agregar una columna de identidad como clave principal y un índice en la columna Fecha para ayudar con mis consultas?

Bingo: esta es la diferencia entre el diseño físico de la base de datos y el diseño lógico de la base de datos. Los programadores tienen que preocuparse mucho por el diseño de la base de datos física inicialmente, pero mientras su base de datos tenga un tamaño de, por ejemplo, 100 GB, puede arreglar el diseño lógico en la publicación, por así decirlo. Ponga un campo de identidad allí para empezar, agrúpelo y luego, después de estar en vivo durante unos meses, vuelva a visitar el diseño del índice para maximizar el rendimiento.

Ahora, dicho esto, una vez que tenga experiencia con este tipo de toma de decisiones, estará mejor equipado para adivinar índices desde el principio. Aun así, ni siquiera suelo pensar mucho en el diseño de índices inicialmente. Los usuarios nunca parecen consultar los datos de la manera que yo hubiera esperado.

Brent Ozar
fuente
1
El inserto uno por uno era una pregunta teórica. Me pareció dudoso, en cuanto al rendimiento, que "las filas se almacenan físicamente en el disco en el mismo orden que el índice agrupado" como leyó en la mayoría de los lugares.
Sacha K
Iré por una columna de identidad. Los datos se agregarán "al final" y, naturalmente, se ordenarán por fecha. Las mismas fechas para diferentes ubicaciones no estarán "juntas", pero eso no me importa en absoluto.
Sacha K