2008-11-24 19 views
15

Tengo una consulta SQL que se ejecuta muy rápido, alrededor de un segundo, cuando no esté utilizando variables, como:¿Por qué SQL Server se ralentiza cuando se usan variables?

WHERE id BETWEEN 5461094 and 5461097 

Pero cuando tengo:

declare @firstId int 
declare @lastId int 

set @firstId = 5461094 
set @lastId = 5461097 

... 
    WHERE id BETWEEN @firstId and @lastId 

... la consulta se ejecuta muy lento , terminando solo después de algunos minutos. ¿Por que sucede? Necesito usar variables. ¿Puedo hacer alguna mejora para evitar estos problemas de rendimiento?

Respuesta

10

Esto se debe a que cuando los valores están codificados, puede buscar the statistics en los datos de la tabla y determinar la mejor consulta para ejecutar. Eche un vistazo a los planes de ejecución de cada una de estas consultas. Debe estar escaneando cuando usa variables.

si el rango es siempre pequeño, es posible que pueda utilizar una sugerencia de índice para ayudarlo.

+0

En Oracle, si el rango fuera siempre pequeño, todo estaría bien. Elegiría el plan basado en las primeras variables. Si siempre es pequeño, siempre estás bien. Son los casos que oscilan entre los extremos. Creo que SS agregó algo así como mirar a escondidas recientemente ... tal vez '05 o '08. –

0

¿Está la ID en un índice (por ejemplo, clave principal)? Si no, intente agregar uno.

Otra cosa podría ser que en la primera instancia (rápida) la consulta se ejecuta de forma ligeramente diferente. Lo más común que he visto pasar es que las uniones se realizan en un orden ineficiente. Intente reordenar las uniones o convierta algunas a subconsultas. Si publica más de su consulta, podemos ayudarlo más.

3

curioso es que este código será rápido también:

DECLARE @sql VARCHAR(8000) 

SET @sql = 'SELECT * FROM table_x WHERE id BETWEEN ' + CAST(@firstId AS VARCHAR) + ' AND ' + CAST(@lastId AS VARCHAR) 

EXEC (@sql) 

(MSSQL 2000)

19

OK,

  1. Usted es el Optimizer y el plan de consulta es un vehículo.
  2. Te haré una consulta y tendrás que elegir el vehículo.
  3. Todos los libros en la biblioteca tienen un número secuencial

Mi consulta es ir a la biblioteca y obtener de mí todos los libros entre 3 y 5

Se podría elegir un derecho bicicleta, rápida, barato, eficiente y lo suficientemente grande como para llevar 3 libros.

Nueva consulta.

Ir a la biblioteca y obtener todos los libros entre @x y @y.

Elija el vehículo.

Adelante.

Eso es lo que sucede. ¿Escoges un camión de basura en caso de que pida libros entre 1 y Maxvalue? Eso es exagerado si x = 3 ey = 5. SQL tiene que elegir el plan antes de ver los números.

+0

procedimientos almacenados actualizados y agregado 'opción recompilar' al final – atoms

+0

Esa es una bella explicación sobre lo que Microsoft está haciendo mal. Vida real: pregunte valores variables, luego, elija el vehículo adecuado. – norgematos

1

Parece que esta consulta está relacionada con un procedimiento almacenado, su plan de ejecución se compilará la primera vez que se ejecuta el proceso y luego se reutilizará para las ejecuciones posteriores.

Es posible que el plan compilado sea realmente malo para las situaciones en las que firstid está realmente cerca del lastid, sin embargo es realmente bueno cuando los valores están muy separados.

Intente habilitar la opción WITH RECOMPILE en su proceso almacenado. Si resuelve el problema y está satisfecho con el proceso que se vuelve a compilar cada vez que se ejecuta (obtendrá un golpe de rendimiento) déjelo ahí. Si aún no está satisfecho con el rendimiento, considere volver a diseñar el proceso para que no necesite la compilación.

0

En realidad, se respondió muy bien, yo sólo escribo aquí una solución que funcionó para mí:

crear un procedimiento almacenado con el SQL

WHERE id BETWEEN @firstId and @lastId 

Después continuación, llamar al procedimiento almacenado con los parámetros @firstId y @lastId y se acelerará. Todavía no estoy 100% de por qué está funcionando, pero funciona.

Cuestiones relacionadas