2009-09-25 26 views
5

Estoy intentando depurar un procedimiento almacenado bastante complejo que se une a muchas pestañas (10-11). Estoy viendo que para una parte del árbol el número estimado de filas difiere drásticamente del número real de filas: en el peor de los casos, SQL Server estima que se devolverá 1 fila, ¡cuando en realidad se devuelven 55,000 filas!¿Cómo funciona SQL Server el número estimado de filas?

Estoy tratando de averiguar por qué esto es así - todas mis estadísticas están actualizadas, y he actualizado las estadísticas con un FULLSCAN en varias tablas. No estoy usando ninguna función definida por el usuario o variables de tabla. Por lo que puedo ver, SQL Server debería ser capaz de estimar exactamente cuántas filas se van a devolver, pero continúa eligiendo un plan que lo lleva a realizar decenas de miles de búsquedas de RDI (cuando espera realizar solo 1) o 2).

¿Qué puedo hacer para tratar de comprender por qué la cantidad estimada de filas se ha reducido tanto?

ACTUALIZACIÓN: Así que mirar el plan que he encontrado un nodo en particular, que parece suspicous - es un recorrido de tabla en una tabla utilizando la siguiente predecate:

status <> 5 
AND [type] = 1 
OR [type] = 2 

Este predicado devuelve toda la tabla (630 filas, la tabla escanea por sí misma, NO es la fuente del bajo rendimiento); sin embargo, el servidor SQL tiene el número estimado de filas a solo 37. El servidor SQL luego realiza varios ciclos anidados con esto en búsquedas RDI, escaneos de índice e índice busca. ¿Podría ser esta la fuente de mi gran error de cálculo? ¿Cómo hago para estimar un número más razonable de filas?

+0

¿Podría publicar la definición de la tabla y la consulta completa? – Quassnoi

+0

Lo siento, pero no realmente, es demasiado grande (250 líneas sp + 10 tablas). – Justin

+3

Si su predicado es exactamente así (sin corchetes), entonces puede tener un problema de lógica. Y tiene prioridad sobre OR. Debe ser [estado] <> 5 Y (tipo = 1 O tipo = 2) – GilaMonster

Respuesta

8

SQL Server divide cada índice en hasta 200 rangos con los siguientes datos (de here):

  • RANGE_HI_KEY

    Un valor clave que muestra el límite superior de un paso de histograma.

  • RANGE_ROWS

    especifica cuántas filas se encuentran dentro del rango (que son más pequeños que este RANGE_HI_KEY, pero más grande que el anterior más pequeña RANGE_HI_KEY).

  • EQ_ROWS

    especifica cuántas filas son exactamente iguales a RANGE_HI_KEY.

  • AVG_RANGE_ROWS

    Promedio del número de filas por valor distinto dentro de la gama.

  • DISTINCT_RANGE_ROWS

    especifica cuántos valores clave son distintas dentro de este rango (sin incluir la clave anterior antes RANGE_HI_KEY y RANGE_HI_KEY sí mismo);

Por lo general, los valores más pobladas entrar en RANGE_HI_KEY.

Sin embargo, pueden entrar en el rango y esto puede llevar a la distorsión en la distribución.

Imagínese estos datos (entre otros):

valor de recuento de claves de filas

1   1 
2   1 
3   10000 
4   1 

SQL Server por lo general genera dos rangos: 1 a 3 y 4 al siguiente valor poblada, lo que hace que estas estadísticas :

RANGE_HI_KEY RANGE_ROWS EQ_ROWS AVG_RANGE_ROWS DISTINCT_RANGE_ROWS 
3    2   10000 1    2 

, lo que significa que al buscar, por ejemplo, 2, solo hay una fila 1 y es mejor usar el acceso de índice.

Pero si 3 va dentro de la gama, las estadísticas son las siguientes:

RANGE_HI_KEY RANGE_ROWS EQ_ROWS AVG_RANGE_ROWS DISTINCT_RANGE_ROWS 
4    10002  1  3334   3 

El optimizador piensa que hay 3334 filas de la clave de acceso y 2 índice es demasiado caro.

+0

¿Cómo podemos resolver este problema incluso si la actualización de las estadísticas con escaneo completo no pudo resolverlo? – Meysam

+0

@Maysam: puede usar 'CREATE STATISTICS' para los predicados que usa con frecuencia. – Quassnoi

3

Utiliza las estadísticas, que se mantiene para cada índice.

(También puede crear estadísticas de columnas no indexados)

Para actualizar todas sus estadísticas de cada mesa en una base de datos (ADVERTENCIA:. Va a tomar algún tiempo en grandes bases de datos No haga esto en los servidores de producción sin consultar con su DBA ...):

exec sp_msforeachtable 'UPDATE STATISTICS ?' 

Si usted no tiene un trabajo regular programada para reconstruir sus índices más activos (es decir, un montón de añadir o suprimir), se debe considerar la reconstrucción de su índices (se aplica la misma advertencia que arriba):

exec sp_msforeachtable "DBCC DBREINDEX('?')" 
0

la reconstrucción de los índices podría resolver el problema del valor de filas estimadas incorrectas

Cuestiones relacionadas