2009-05-16 21 views
11

Una aplicación causa una gran carga en nuestra base de datos Sql Server 2005. No tenemos control sobre la aplicación que se ejecuta esta consulta hundres de veces por minuto:Exploración de tabla inesperada para identificación! = Id

select id,col1,col2,col3 from table where id != id 

Nota del id = id, es decir, una fila no es igual a sí mismo. Como era de esperar, el resultado siempre no se encuentra filas. Sin embargo, el servidor Sql realiza un escaneo de índice agrupado cada vez que ejecuta esta consulta.

La columna ID se define como:

varchar(15) not null primary key 

El plan de consulta muestra un gran número de "Estimación del número de filas". ¿Alguien tiene una idea de por qué Sql Server necesita el escaneo de la tabla para descubrir lo obvio?

Respuesta

2

Después de leer las respuestas aquí y sus ediciones, vamos a resumir sus opciones:

  1. Cambio MS SQL Server para manejar este caso (básicamente, hablar con soporte de Microsoft)
  2. cambiar la aplicación para evitar este caso, o hacerlo de manera diferente (básicamente, hablar con el soporte de la compañía que realizó la aplicación)
  3. Cambiar a algo que no sea SQL Server (si la aplicación lo permite), que maneja este caso
  4. Cambiar a otra aplicación

Ninguna de estas son buenas soluciones, pero desafortunadamente, son las únicas que tiene. Tienes que elegir uno e ir con él.

Primero probaría la solución 2, es la que debería/debería tomar el menor tiempo de ejecución.

Si, por otro lado, esa empresa no está dispuesta a cambiar la aplicación, entonces yo iría con la solución 4. Este es un error de rendimiento importante, y si la empresa no está dispuesta o no puede solucionar ese problema, tiene para preguntarse, ¿qué más acecha en la próxima esquina?

+0

Gracias por el resumen, pero probablemente vayamos con la Opción n. ° 5: arroje más hardware. Trabajando en 1 y 2 también. :) – Andomar

+0

tomó un par de meses, pero finalmente conseguimos un desarrollador de la aplicación en nuestro sitio, y él cambió la aplicación a una consulta más inteligente en una hora. – Andomar

1

No sé por qué id! = Id lleva tanto tiempo en este caso (aunque "obvio" es subjetivo - no es necesariamente una optimización que pensaría ... parece una consulta inusual; unión cartesiana es doloroso, sin embargo). Pero, en general, prueba "donde 1 = 0" - o si solo quieres el esquema, quizás el ligeramente arriesgado SET FMTONLY ON.

Editar: acabo de ver "No controlamos la aplicación que ejecuta esta consulta cientos de veces por minuto" ... hmmm ... eso lo hace complicado.

3

Cada valor se compara con el resto de los valores n-1. es por eso que devuelve un gran número para "Número estimado de filas". Para el problema anterior, es mejor usar no en.

El artículo aquí es un buen puntero para su problema. Espero que te ayude. http://www.sqlservercentral.com/articles/Performance+Tuning/2924/

+0

Una prueba mostró que la variante NOT IN sigue causando un escaneo de tabla. Y no controlamos la aplicación, por lo que no podemos cambiar la consulta. – Andomar

4

Tu mayor problema no es el escaneo de la tabla. Sus dos mayores problemas son:

  • Tiene una consulta absolutamente inútil que se ejecuta 100 veces veces por minuto en su base de datos. Por cierto, supongo que la consulta está tratando de obtener los nombres de las columnas de la tabla como sugiere Marc Gravell.

y lo más importante:

  • Usted no tiene control sobre quién o qué está teniendo acceso a su base de datos.

Ese segundo problema, en especial, es lo más probable que te cause dolores de cabeza interminables. Asumiendo que usted es parte del equipo de datos en su organización (ya que usted es el que está tratando de resolver este problema), realmente debería estar buscando hacer los cambios organizacionales necesarios para hacer su trabajo.

¡Buena suerte!

+0

¡Gracias por su respuesta! La consulta en realidad contiene los nombres de las columnas, lo editaré en la pregunta. A la organización no le importaría a menos que fuera un problema visible, que aún no es ( – Andomar

+0

) ¡SIEMPRE PUEDE HACERLO un problema visible! –

+1

Tom H. tiene razón. Esto realmente no es un problema técnico. Es un problema político Aparentemente, los equipos de desarrollo de aplicaciones y de control de calidad creen que es razonable ejecutar esta consulta cientos de veces por minuto. Tu tarea es cambiar su opinión sobre ella para que pueda ser corregida. En ausencia de eso, debe cuantificar el impacto en el desempeño y los riesgos asociados y hacer que la administración tome conciencia del problema. Una vez que se trata de una crisis, la administración se enfocará en el problema. – spencer7593

6

Me gustaría falsificar esta consulta ... abstraer con una vista, y engañar a la consulta.

Cambiar el nombre de la tabla de 'mesa' existente para 'table_org' o alguna otra cosa, y crear una vista como esta:

CREATE VIEW table 
AS 
SELECT * FROM table_org 
WHERE id='BOGUSKEY' 

Ahora, usted debe obtener su 1 lectura, a través de la tabla de la clave primaria, y debería (como la consulta original) no encontrar nada. La aplicación no sabe nada más sabio ...

+0

¡Buen pensamiento fuera de la caja! Desafortunadamente, la consulta contiene datos reales y otras consultas piden resultados reales. Además de eso, la aplicación crea sus propias tablas, y se niega a ejecutar si lo reemplaza con una vista. – Andomar

3

He visto este tipo de consulta.

Lo más probable es que los desarrolladores estén creando cláusulas 'DONDE' en función de la entrada del usuario, la configuración actual o algunos otros factores. En muchos casos, tal vez la instancia predeterminada, necesitarían una cláusula WHERE que sea solo un marcador de posición. Es entonces cuando usan criterios como 'id! = Id', '1 <> 1', etc.

Los 'cientos de veces por minuto' también me llevan a pensar que se trata de un marcador de posición predeterminado erróneo.

A veces usarán un criterio que haga lo contrario, siempre se evalúa como verdadero si el caso predeterminado requiere todas las filas.

Es una posibilidad remota, pero mi sugerencia sería ver si puede modificar la configuración de la aplicación y ver si esta consulta desaparece. Puede terminar con un pequeño conjunto resultante, pero algo que se ejecuta con menos frecuencia y que SQL Server maneja mejor.

3

Es posible que desee que el equipo de soporte técnico de SQL Server conozca esta consulta (id <> id cuando la columna se define como clave principal) y el escaneo completo de la tabla que causa, y para ver si tal vez ellos quieran agregue una optimización en el motor de consultas para asegurarse de que esto no provoque un escaneo completo de la tabla.

O eso, o hable con el equipo de soporte de la aplicación que no puede controlar.

EDITAR: Pruebe el foro de TechNet en http://social.msdn.microsoft.com/forums/en-US/sqldatabaseengine/threads/ para informar del comportamiento.

+0

¿Conoces una buena manera de informar esto al equipo de soporte del servidor Sql? – Andomar

2

¿Tiene un índice no agrupado en la columna de identificación? De lo contrario, el curso más eficiente siempre será un escaneo CIX. Intente agregar un NCIX en la columna de ID: aún puede realizar un escaneo, pero al menos será un escaneo en un índice muy pequeño. Si estuviera en SQL Server 2008, podría crear un índice filtrado (WHERE id <> id) y SQL Server usaría el índice filtrado (vacío) para satisfacer la consulta.

+0

Tenemos un CIX en la columna de id. Si agrego un NCIX en (id, col1, col2, col3) lo usaré en su lugar, ¡que es más rápido! Desafortunadamente col3 es bastante grande. Estamos en 2005, pero si estuviéramos en 2008, esos índices filtrados parecen una posible solución. – Andomar

1

Al estar menos familiarizado con SQL Server, creo que la solución a continuación también podría aplicarse a SQL Server.

En Oracle, creo que se puede superar al ingenuo SQL mediante el uso de una vista materializada y reescritura de consultas. La vista materializada no contendría filas, y la reescritura de la consulta reconoce el SQL y en su lugar redirige la consulta a la vista vacía. La vista materializada nunca necesitaría actualizarse, debido al hecho de que siempre estará vacía.

2

estoy casi demasiado avergonzado para enviar esta respuesta, pero en el espíritu de "si funciona sanos nada, tratan los locos" ...

 
    Create a constraint on the table where id = id? 

La cláusula where sólo podría devolver filas que violan la restricción , de los cuales no hay ninguno por definición. Esta información adicional (aunque redundante) puede ayudar al optimizador en su caso. Igualmente puede lograr la raíz cuadrada de nada, pero en su caso yo lo probaría por si acaso ...

+0

+1 Brillante idea pero no funcionó. Intenté vaciar el caché del plan de consulta, o una restricción en (no (id! = Id)), pero todavía hace un escaneo de índice agrupado. – Andomar

1

Me parece que tiene un problema político disfrazado de problema técnico. Puede dedicar mucho tiempo y esfuerzo al problema técnico, pero mientras siga repitiendo "no controlamos la aplicación", se está alejando de las opciones políticas.

No puede controlar la aplicación, pero probablemente pueda hacer que se aplique alguna influencia. Haga que todos los interesados ​​conozcan cómo el comportamiento de esta aplicación afecta a todos los demás que usan esa base de datos (use gráficos, ya que querrá transmitir este mensaje rápidamente a la administración). Y tenga en claro que es un problema para el autor de la aplicación o para solucionarlo. Eso podría generar una presión en el autor de la aplicación, o podría generar una respuesta "O.K., bien, compremos otra base de datos para esa aplicación" de la administración.

(Usted querrá tener una respuesta disponible para la cuestión de si Microsoft ha "fijado" en SQL Server 2008.)

+0

¡Gracias por la respuesta! Aunque estoy realmente molesto de que la carga top-1 sea esta consulta falsa, no es realmente un gran problema. La base de datos todavía funciona sin problemas. También hay algunas ranuras de RAM vacías en el servidor. – Andomar

1

sospecho que SqlServer no "sabe" que! = (Debe ser "<>"?) es anti-reflexivo (es decir, A! = A siempre es falso) ... simplemente ve que no es constante (depende de los valores de una fila de resultados) y por lo tanto lo pone en el resultado filtrar. Entonces "donde id <> id" es potencialmente muy diferente de "donde 1 <> 1".

Ahora, ciertamente pueden hacer que detecte este caso; pero supongo que simplemente nunca llegó a su lista de prioridades porque está entre "extraño" y "tonto" para estar haciendo esto.

Sí, la aplicación haciendo esto chupa, creo que ya sabe que;)

+0

! = Parece ser un sinónimo de <>. La aplicación es bastante útil, excepto por este aspecto falso. – Andomar

0

no hay manera de hacer esto no scan, que está pidiendo todo, menos de 1 fila, es una exploración. Lo mejor que puede esperar es que la aplicación deje de enviar estas consultas.

+0

La falsedad de la consulta podría haberle cegado a su significado. Está consultando "id! = Id": el valor de la columna de la clave principal no es igual a sí mismo. El resultado es siempre 0 filas. – Andomar

+0

@Andomar, duh, estaba pensando id! = Id –

Cuestiones relacionadas