2011-02-10 12 views
5

así que estaba tratando de explicar a algunas personas por qué esta consulta es una mala idea:En SQL Server, ¿TOP es determinista de forma predeterminada cuando se usa en una tabla con un índice agrupado?

SELECT z.ReportDate, z.Zipcode, SUM(z.Sales) AS Sales, 
COALESCE(
    (SELECT TOP (1) GroupName 
    FROM dbo.zipGroups 
    WHERE (Zipcode = z.Zipcode)), 'Unknown') AS GroupName, 
COALESCE(
    (SELECT TOP (1) GroupCode 
    FROM dbo.zipGroups 
    WHERE (Zipcode = z.Zipcode)), 0) AS GroupNumber 
FROM dbo.Report_ByZipcode AS z 
GROUP BY z.ReportDate, z.Zipcode 

y sugerir una mejor manera de escribirlo, cuando mi jefe terminó la discusión con, "Bueno, ha estado volviendo la datos correctos para el último año y no hemos tenido ningún problema con eso, así que está bien ".

En ese momento pensé para mis adentros, ¿cómo es eso posible?

Después de algo de investigación, he descubierto estos hechos:

  1. Esta consulta se supone que las ventas del grupo por código postal y la fecha, y vincular los del grupo más grande (por tamaño de la población) que un CP se asigna a por forma de la tabla zipGroups.
  2. Cada código postal se puede asignar a 0 en muchos grupos, y si se asigna un código postal a 0 grupos, simplemente no está en la tabla zipGroups.
  3. Un grupo es un área geográfica, y los GroupNumbers se clasifican de mayor a menor por población (por ejemplo, el grupo que cubre el área tri-estatal NY-NJ-CT es GroupNumber 1, y North Platte, Nebraska es GroupNumber 209)
  4. La tabla zipGroups no ha cambiado en al menos 2 años.
  5. La tabla zipGroups tiene un índice agrupado con código postal, GroupNumber (ascendente) como las claves.
  6. La combinación de código postal, GroupNumber es única en zipGroups.

Entonces mi pregunta tiene 2 partes.

A) Aunque no hay cláusulas ORDER BY en esas consultas SELECT TOP, ¿son realmente deterministas porque el índice agrupado básicamente le proporciona un ORDER BY predeterminado?

B1) Si eso es cierto, ¿es la consulta, aunque precariamente, haciendo realmente lo que se supone que tiene que hacer?

B2) Si eso no es cierto, ¿me pueden ayudar a demostrarlo?

Nota: Ya he vuelto a escribir esto para utilizar las uniones, por lo que no necesito el SQL para arreglarlo, tengo que ponerlo en producción, así que dejo de preocuparme por su ruptura.

+0

Simple y llana: si no hay 'ORDER BY' no hay ** garantía ** para ningún orden –

+0

Problema: qué decirle al jefe que dice" está bien ". –

+0

No es lógicamente determinista, incluso si, desde una perspectiva práctica, el optimizador de consultas no hiciera nada más. Si necesita un comportamiento particular, debe especificarlo, de lo contrario, el siguiente paquete/versión de servicio puede quebrar sus consultas (el uso de 'TOP 100 PERCENT' en Views o el uso de variables para concatenar cadenas le viene a la mente). Parece un riesgo completamente sin sentido, ya que no hay beneficio por no ser explícito. –

Respuesta

4

SQL Server no garantiza el orden de los registros en ausencia de ORDER BY. Puede arrojar los resultados correctos 999,999 veces y luego fallar en el intento número uno. No lo hagas

+0

oh, mucho más que 1 en un millón – RichardTheKiwi

+1

@cyberwiki: Cuando dices "más", no estoy seguro de si te estás refiriendo al numerador o al denominador, y por lo tanto no puedo decir en qué punto estás haciendo (podría significar ambas cosas, supongo que, dependiendo de las circunstancias, podríamos ver failure_rate >>> 1e-6 o failure_rate <<< 1e-6). –

1

Utilice siempre un pedido con una instrucción TOP. No se garantiza que el orden esté en el orden del índice agrupado como se demuestra en esta publicación de blog (completa con una consulta que lo desmiente):

Without ORDER BY, there is no default sort order.

Incluso si fuera por el índice agrupado, no escribiría consultas que dependen del comportamiento no documentado del motor de DB y es mejor ser explícito para la legibilidad.

+0

el artículo vinculado y varios otros tratan la situación cuando el optimizador tiene * elección * en cuanto a qué índice usar. Si se le da solo una opción y TOP N se fija en N = 1, es mucho más predecible. – RichardTheKiwi

+0

Es por eso que he votado a favor su respuesta. Aún así, creo que es una mala idea confiar en el comportamiento no documentado del optimizador de consultas, incluso si parece funcionar. – JohnFx

0

A) Aunque no hay cláusulas ORDER BY en esas consultas SELECT TOP, ¿son realmente deterministas porque el índice agrupado básicamente le proporciona un ORDER BY predeterminado? B1) Si eso es cierto, ¿está haciendo la consulta, aunque precariamente, lo que se supone que debe hacer?

Cuando se especifica arriba sin pedir, el orden es un efecto secundario del método de acceso elegido por el optimizador de consultas. Dado que el optimizador de consultas usaría el índice agrupado para resolver esta consulta, obtendrá un efecto secundario bastante agradable.

No utilizaría la palabra determinista, ya que el optimizador de consultas podría no ser determinista. Sin embargo, en el caso donde el optimizador elige el índice agrupado, sí, la consulta hace lo que se supone que debe hacer.

ORDEN todavía se debe especificar, a fin de bloquear la exactitud de la consulta. Uno debe separar la corrección ("¿Qué es lo que quiere") y la implementación ("Cómo se obtiene") en el plan de consulta y optimizador, respectivamente.

B2) Si eso no es cierto, ¿me pueden ayudar a demostrarlo?

Suponiendo que hay más columnas en la tabla ZipGroups, un índice no agrupado que contiene las dos únicas columnas relevantes podrían añadirse que sería preferible sobre el índice agrupado. Si el índice no agrupado tenía un orden diferente (Zipcode asc, GroupNumber desc), la consulta se rompería.

+0

'obtienes un efecto secundario bastante agradable" no 100% cierto. Incluso si se selecciona un índice agrupado, no es garantía de orden (en ese índice) – RichardTheKiwi

+0

Por supuesto que no hay garantía. Pero hay -algunas- implementaciones allí, y esa implementación sería extraña si se comportase de manera diferente (el paralelismo, por supuesto, siempre es extraño). –

1

Si se basa en un índice agrupado en lugar de la intercalación, entonces obtener el orden correcto es una coincidencia, no determinista.

En el mundo real, los índices se pueden cambiar de un tipo a otro, por buenas razones, por malas razones o sin ningún motivo. Y, en el mundo real, no necesariamente puede elegir qué índice usará SQL Server al ejecutar una consulta. (O si usará un índice)

Técnicamente, la intercalación también se puede cambiar por buenas razones, malas razones o ninguna razón en absoluto. Pero todo el mundo sabe al cambiar la clasificación cambiará el orden de clasificación; ese es su trabajo, después de todo, así que no es una sorpresa. (¿Alguna vez escuchó hablar del "principio de la menor sorpresa"?)

1

El enlace de JohnFx es bueno, aunque es largo y difícil de seguir. Aquí hay un pequeño fragmento que mostrará los datos que regresan en orden de índice no agrupado.

CREATE TABLE t1 (x INT NOT NULL PRIMARY KEY CLUSTERED, z INT NOT NULL UNIQUE); 

INSERT INTO t1 (x,z) VALUES (1,4); 
INSERT INTO t1 (x,z) VALUES (3,3); 
INSERT INTO t1 (x,z) VALUES (2,2); 
INSERT INTO t1 (x,z) VALUES (4,1); 

SELECT x, z FROM t1; 

salida (usted debe conseguir)

x   z 
----------- ----------- 
4   1 
2   2 
3   3 
1   4 

plan de ejecución muestra que el uso de la única (o de otro tipo) en lugar del índice de índice agrupado.

Incluso si se elige el índice agrupado, es posible que no se ordene correctamente si los datos se combinan desde el paralelismo, si el recuento de TOP N es suficientemente alto.

Una vez dicho esto, ya que sólo está utilizando TOP (1) y si la tabla tiene un solo índice disponibles, puede ser considerada determinista ya que sólo usará ese índice y escoger el primera entrada en las páginas de índice.

+0

Entonces, dado que esta consulta es "considerada determinista", ¿debería informarle a su jefe que "está bien" es cierto? –

+0

@David - sí, en este caso en todas las implementaciones actuales de SQL Server hasta 2008 R2 – RichardTheKiwi

+0

¿Qué tan seguro está usted de que ["Escaneo avanzado"] (http://msdn.microsoft.com/en-us/library/ms191475 .aspx) no se puede aplicar aquí? –

Cuestiones relacionadas