2011-05-31 15 views
11

Tengo una tabla [MyTable] con una columna [MyColumn] NVarchar (50). Tengo un índice no agrupado en esta columna, ahora mientras se ejecuta el siguiente dos consultas:Buscar índice con unir

SELECT 1 
FROM [MyTable] M 
WHERE M.[MyColumn] = @MyColumn 

SELECT 1 
FROM [MyTable] M 
WHERE M.[MyColumn] = COALESCE(@MyColumn, M.[MyColumn]) 

noté la primera consulta está utilizando Index Seek (no agrupados) y la segunda es el uso de Index Scan (no agrupado). ¿Puedo saber cómo utilizaré index seek con coalesce o isnull?

Respuesta

2

se puede saber cómo voy a hacer uso de búsqueda de índice se unen con o isnull?

Quizás no sea una respuesta a su pregunta, pero puede tener dos consultas diferentes. Uno para el caso donde @MyColumn is null y uno para el caso en el que desea utilizar @MyColumn en la cláusula where.

IF @MyColumn IS NULL 
BEGIN 
    SELECT 1 
    FROM [MyTable] M 
END 
ELSE 
BEGIN 
    SELECT 1 
    FROM [MyTable] M 
    WHERE M.[MyColumn] = @MyColumn 
END 
0

Uso de funciones como COALESCE o ISNULL en la cláusula where está pidiendo el servidor para buscar los resultados de esas funciones - que son desconocidos hasta que se ejecutan para cada fila del conjunto resultante, por lo que no hay manera de es para hacer uso de un índice.

Para aprovechar al máximo el índice, no utilice funciones en la cláusula WHERE, modifíquelas con las condiciones estándar, p. WHERE MyColumn = @MyColumn OR @MyColumn IS NULL

+2

Solo que 'MyColumn = @MyColumn O @MyColumn IS NULL' también conducirá a un escaneo de índice. ;-) – Tomalak

+0

Ejecuto "MyColumn = @MyColumn OR @MyColumn IS NULL" pero también desafortunadamente el mismo resultado que está usando Index Scan (no agrupado) –

+0

'OR' no cortocircuita, revisará cada fila independientemente. Si el optimizador sabe que necesitará verificar cada fila, solo hará un escaneo. – JNK

0

Esto no es fácil, ya que como Alex señaló utilizando las funciones obliga a un escaneo, ya que el optimizador sabe que necesita verificar cada fila.

Lo que PUEDE hacer es crear un Computed Column para el resultado de su función, and index that column.

No hay realmente una manera más bonita de obtener una búsqueda.

EDIT:

Al releer su pregunta, esto puede no ser una opción para usted a menos que reconsiderar su lógica. Está integrando una variable en la función, y no hay forma de indexar eso.

EDIT 2:

En lugar de la lógica actual, intentar algo como:

... 
WHERE (M.[MyColumn] = @MyColumn 
     OR @MyColumn IS NULL) 
0

supongo que va a utilizar esta consulta en una más compleja, posiblemente con EXISTS:

EXISTS 
(SELECT 1 
    FROM [MyTable] M 
    WHERE M.[MyColumn] = COALESCE(@MyColumn, M.[MyColumn]) 
) 

Tal vez puedas probar:

EXISTS 
(SELECT 1 
    FROM [MyTable] M 
    WHERE M.[MyColumn] = @MyColumn 
) 
OR EXISTS 
(SELECT 1 
    FROM [MyTable] M 
    WHERE @MyColumn IS NULL 
) 

O esta otra:

CASE WHEN @MyColumn IS NULL 
    THEN 1 
    ELSE 
     (SELECT 1 
      FROM [MyTable] M 
      WHERE M.[MyColumn] = @MyColumn 
     ) 
END 
0

En la consulta con la cláusula Coalesce, el optimizador sabe que "MyColumn" es un rango de valores por lo que decidirá usar un escaneo en el índice. El único método para usar una búsqueda cuando se pasa una variable no nula es codificar dos procesos almacenados y llamar al apropiado a través de la prueba lógica de la variable.

Si usted tiene una situación tan simple como su ejemplo y desea utilizar un Index Seek cuando la variable no es NULL, entonces debería codificar la consulta como:

If @MyColumn is NULL 
Begin 
    EXEC MyStoredProcWithMyColumn=Mycolumn 
END 
ELSE 
Begin 
    EXEC MyStoredProcWithMyColumn=Variable @MyColumn 
END 

después de crear dos procedimientos almacenados uno el cual devuelve los datos usando la cláusula where con la variable y uno con la cluase where para la columna igual a ella.

Cuestiones relacionadas