Esta es una pregunta derivada del orden de clasificación especificada en la clave principal, pero la clasificación se ejecuta en SELECT .
@Catcall dice esto sobre el tema del orden de almacenamiento (índice agrupado) y el orden de salida
Mucha gente cree que un índice agrupado garantiza un orden de clasificación en la salida. Pero eso no es lo que hace; garantiza una orden de almacenamiento en disco. Ver, por ejemplo, esta publicación de blog .
He leído la publicación de blog de Hugo Kornelis y entiendo que un índice no garantiza que el servidor SQL lea los registros en un orden específico. Sin embargo, ¿me cuesta aceptar que no puedo asumir esto para mi situación?
CREATE TABLE [dbo].[SensorValues](
[DeviceId] [int] NOT NULL,
[SensorId] [int] NOT NULL,
[SensorValue] [int] NOT NULL,
[Date] [int] NOT NULL,
CONSTRAINT [PK_SensorValues] PRIMARY KEY CLUSTERED
(
[DeviceId] ASC,
[SensorId] ASC,
[Date] DESC
) WITH (
FILLFACTOR=75,
DATA_COMPRESSION = PAGE,
PAD_INDEX = OFF,
STATISTICS_NORECOMPUTE = OFF,
SORT_IN_TEMPDB = OFF,
IGNORE_DUP_KEY = OFF,
ONLINE = OFF,
ALLOW_ROW_LOCKS = ON,
ALLOW_PAGE_LOCKS = ON)
ON [MyPartitioningScheme]([Date])
Mi consulta original fue esta:
SELECT TOP 1 SensorValue
FROM SensorValues
WHERE SensorId = 53
AND DeviceId = 3819
AND Date < 1339225010
ORDER BY Date DESC
Pero sugiero que también podría usar este (lea a continuación para obtener mi explicación):
SELECT TOP 1 SensorValue
FROM SensorValues
WHERE SensorId = 53
AND DeviceId = 3819
AND Date < 1339225010
Como puede ver, las filas de mi tabla son pequeñas (16bytes) y solo tengo un índice, un clúster. En mi escenario, la tabla consta de 100.000.000 registros en este momento (y esto probablemente aumentará diez veces).
Cuando el servidor de bases de datos consulta esta tabla, tiene dos formas de encontrar mis filas, o busca la clave primaria y, por lo tanto, lee y devuelve mis valores en desc. orden de fecha, o tiene que hacer un escaneo completo de la tabla. Mi conclusión es que una exploración completa de la tabla en todos esos registros será demasiado lenta y, por lo tanto, el servidor de la base de datos siempre buscará la tabla a través de su clave principal y, por lo tanto, devolverá los valores ordenados porDate DESC
ORDER BY
allí y sabes que puedes confiar en ella? Ver # 3 aquíORDER BY
cláusula es un gran éxito para mí (lea la otra pregunta para obtener más información). Tengo una solución que funciona por ahora, pero no se mantendrá cuando y si mi tráfico aumenta.ORDER BY
cláusula en su consulta. Esto es cierto para SQL Server , Oracle , MySQL y cualquier otro RDBMS que se te ocurra. Pruebe cualquier otra cosa y se está preparando para una taza sorpresa de FALLA.Respuestas:
Voy a tratar de explicar por qué usted debe no hacer eso, por las que debe Nunca asumir que un subproducto de SQL devolverá un conjunto de resultados en un orden específico, a menos que se especifique lo tanto, lo índices - agrupados o no agrupados, los árboles B o R-Trees o kd-trees o fractal-trees o cualquier otro índice exótico que esté utilizando un DBMS.
Su consulta original le dice al DBMS que busque en la
SensorValues
tabla, encuentre filas que coincidan con las 3 condiciones, ordene esas filasDate
descendiendo, mantenga solo la primera fila de esas y, finalmente, seleccione y devuelva solo laSensorValue
columna.Estas son órdenes muy específicas que le ha dado al DBMS y el resultado probablemente será el mismo cada vez que ejecute la consulta (existe la posibilidad de que no lo sea, si tiene más de una fila que coincida con las condiciones y tenga las mismas max
Date
pero diferente,SensorValue
pero supongamos para el resto de la conversación que no existen tales filas en su tabla).¿El DBMS tiene que hacer esto, para ejecutar esta consulta, exactamente como la describí anteriormente? No, por supuesto que no, y lo sabes. Es posible que no lea la tabla, sino que lea desde un índice. O puede usar dos índices si cree que es mejor (más rápido). O tres O puede usar un resultado en caché (no SQL Server sino otros resultados de consulta de caché DBMS). O puede usar la ejecución paralela una vez y no la próxima vez que se ejecute. O ... (agregue cualquier otra característica que afecte la ejecución y los planes de ejecución).
Sin embargo, lo que está garantizado es que devolverá exactamente el mismo resultado, cada vez que lo ejecute, siempre que no se inserten, eliminen o actualicen filas.
Ahora veamos qué dice tu sugerencia:
Esta consulta le dice al DBMS que busque en la
SensorValues
tabla, busque filas que coincidan con las 3 condiciones,ordene esas filas, no se preocupe por el orden, mantenga solo una fila y, finalmente, seleccione y devuelva solo laDate
descendiendoSensorValue
columna.Entonces, básicamente dice lo mismo que el primero, excepto que dice que solo desea un resultado que coincida con las condiciones y no le importa cuál .
Ahora, ¿podemos suponer que dará siempre el mismo resultado debido al índice agrupado?
- Si usa este índice agrupado cada vez, sí.
¿Pero lo usará?
- No.
Por qué no?
- Porque puede. El optimizador de consultas es libre de elegir una ruta de ejecución cada vez que ejecuta una instrucción. Cualquiera sea el camino que considere adecuado en ese momento para esa declaración.
¿Pero no está usando el índice agrupado la mejor / más rápida forma de obtener resultados?
- No, no siempre. Puede ser la primera vez que ejecute la consulta. La segunda vez, puede usar un resultado en caché (si el DBMS tiene esa característica, no SQL Server * ). La milésima vez que el resultado puede haberse eliminado de la memoria caché y puede existir otro resultado allí. Digamos que había ejecutado esta consulta justo antes:
y el resultado en caché (de la consulta anterior) es otro, diferente, que aún coincide con sus condiciones, pero no es el primero en su pedido (deseado). Y le ha dicho al DBMS que no se preocupe por el pedido.
OK, ¿entonces solo el caché puede afectar esto?
- No, muchas otras cosas también.
*: SQL Server no almacena en caché los resultados de las consultas, pero Enterprise Edition tiene una función de Análisis avanzado que es similar en el sentido de que puede obtener resultados diferentes debido a consultas simultáneas. Sin embargo, no estoy seguro exactamente cuándo esto entra en acción (Gracias a Martin Smith por la propina).
Espero que esté convencido de que nunca debe confiar en que una consulta SQL devolverá resultados en un orden específico, a menos que así lo especifique. Y nunca use
TOP (n)
sinORDER BY
, a menos que, por supuesto, solo quiera n filas en el resultado y no le importe cuáles se devuelven.fuente