¿Cómo puedo eliminar un operador de búsqueda de claves (agrupado) en mi plan de ejecución?
La tabla tblQuotes
ya tiene un índice agrupado ( QuoteID
activado) y 27 índices no agrupados, por lo que estoy tratando de no crear más.
Puse la columna de índice agrupado QuoteID
en mi consulta, esperando que ayude, pero desafortunadamente sigue siendo la misma.
O verlo:
Esto es lo que dice el operador de búsqueda clave:
Consulta:
declare
@EffDateFrom datetime ='2017-02-01',
@EffDateTo datetime ='2017-08-28'
SET NOCOUNT ON
SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED
IF OBJECT_ID('tempdb..#Data') IS NOT NULL
DROP TABLE #Data
CREATE TABLE #Data
(
QuoteID int NOT NULL, --clustered index
[EffectiveDate] [datetime] NULL, --not indexed
[Submitted] [int] NULL,
[Quoted] [int] NULL,
[Bound] [int] NULL,
[Exonerated] [int] NULL,
[ProducerLocationId] [int] NULL,
[ProducerName] [varchar](300) NULL,
[BusinessType] [varchar](50) NULL,
[DisplayStatus] [varchar](50) NULL,
[Agent] [varchar] (50) NULL,
[ProducerContactGuid] uniqueidentifier NULL
)
INSERT INTO #Data
SELECT
tblQuotes.QuoteID,
tblQuotes.EffectiveDate,
CASE WHEN lstQuoteStatus.QuoteStatusID >= 1 THEN 1 ELSE 0 END AS Submitted,
CASE WHEN lstQuoteStatus.QuoteStatusID = 2 or lstQuoteStatus.QuoteStatusID = 3 or lstQuoteStatus.QuoteStatusID = 202 THEN 1 ELSE 0 END AS Quoted,
CASE WHEN lstQuoteStatus.Bound = 1 THEN 1 ELSE 0 END AS Bound,
CASE WHEN lstQuoteStatus.QuoteStatusID = 3 THEN 1 ELSE 0 END AS Exonareted,
tblQuotes.ProducerLocationID,
P.Name + ' / '+ P.City as [ProducerName],
CASE WHEN tblQuotes.PolicyTypeID = 1 THEN 'New Business'
WHEN tblQuotes.PolicyTypeID = 3 THEN 'Rewrite'
END AS BusinessType,
tblQuotes.DisplayStatus,
tblProducerContacts.FName +' '+ tblProducerContacts.LName as Agent,
tblProducerContacts.ProducerContactGUID
FROM tblQuotes
INNER JOIN lstQuoteStatus
on tblQuotes.QuoteStatusID=lstQuoteStatus.QuoteStatusID
INNER JOIN tblProducerLocations P
On P.ProducerLocationID=tblQuotes.ProducerLocationID
INNER JOIN tblProducerContacts
ON dbo.tblQuotes.ProducerContactGuid = tblProducerContacts.ProducerContactGUID
WHERE DATEDIFF(D,@EffDateFrom,tblQuotes.EffectiveDate)>=0 AND DATEDIFF(D, @EffDateTo, tblQuotes.EffectiveDate) <=0
AND dbo.tblQuotes.LineGUID = '6E00868B-FFC3-4CA0-876F-CC258F1ED22D'--Surety
AND tblQuotes.OriginalQuoteGUID is null
select * from #Data
Plan de ejecución:
Respuestas:
Las búsquedas clave de varios tipos se producen cuando el procesador de consultas necesita obtener valores de columnas que no están almacenadas en el índice utilizado para ubicar las filas necesarias para que la consulta devuelva resultados.
Tomemos, por ejemplo, el siguiente código, donde estamos creando una tabla con un índice único:
Insertaremos 1,000,000 de filas en la tabla para tener algunos datos con los que trabajar:
Ahora, consultaremos los datos con la opción de mostrar el plan de ejecución "real":
El plan de consulta muestra:
La consulta mira el
IX_Table1
índice para encontrar la filaTable1ID = 5000000
ya que mirar ese índice es mucho más rápido que escanear toda la tabla en busca de ese valor. Sin embargo, para satisfacer los resultados de la consulta, el procesador de consultas también debe encontrar el valor para las otras columnas de la tabla; aquí es donde entra la "Búsqueda de RID". Busca en la tabla el ID de fila (el RID en Búsqueda de RID) asociado con la fila que contiene elTable1ID
valor de 500000, obteniendo los valores de laTable1Data
columna. Si coloca el mouse sobre el nodo "RID Lookup" en el plan, verá esto:La "Lista de resultados" contiene las columnas devueltas por la búsqueda de RID.
Una tabla con un índice agrupado y un índice no agrupado es un ejemplo interesante. La siguiente tabla tiene tres columnas; ID que es la clave de agrupación,
Dat
que está indexado por un índice no agrupadoIX_Table
, y una tercera columna,Oth
.Tome esta consulta de ejemplo:
Le pedimos a SQL Server que devuelva cada columna de la tabla donde la
Dat
columna contiene la palabraTest
. Tenemos un par de opciones aquí; podemos mirar la tabla (es decir, el índice agrupado), pero eso implicaría escanear todo, ya que la tabla está ordenada por laID
columna, que no nos dice nada sobre qué fila (s) contieneTest
en laDat
columna. La otra opción (y la elegida por SQL Server) consiste en buscar en elIX_Table1
índice no agrupado para encontrar la fila dondeDat = 'Test'
, sin embargo, dado que también necesitamos laOth
columna, SQL Server debe realizar una búsqueda en el índice agrupado utilizando una "Clave Operación de búsqueda ". Este es el plan para eso:Si modificamos el índice no agrupado para que incluya la
Oth
columna:Luego vuelva a ejecutar la consulta:
Ahora vemos una única búsqueda de índice no agrupado, ya que SQL Server simplemente necesita ubicar la fila
Dat = 'Test'
en elIX_Table1
índice, que incluye el valor paraOth
, y el valor de laID
columna (la clave primaria), que está presente automáticamente en cada índice agrupado El plan:fuente
La búsqueda de claves se debe a que el motor eligió usar un índice que no contiene todas las columnas que está tratando de recuperar. Por lo tanto, el índice no cubre las columnas en la instrucción select y where.
Para eliminar la búsqueda de clave, debe incluir las columnas que faltan (las columnas en la lista de resultados de la búsqueda de clave) = ProducerContactGuid, QuoteStatusID, PolicyTypeID y ProducerLocationID u otra forma es forzar a la consulta a utilizar el índice agrupado en su lugar.
Tenga en cuenta que 27 índices no agrupados en una tabla pueden ser malos para el rendimiento. Al ejecutar una actualización, insertar o eliminar, SQL Server debe actualizar todos los índices. Este trabajo adicional puede afectar negativamente el rendimiento.
fuente
Olvidó mencionar el volumen de datos involucrados en esta consulta. Además, ¿por qué te estás insertando en una tabla temporal? Si solo necesita mostrar, no ejecute una instrucción de inserción.
Para los fines de esta consulta,
tblQuotes
no necesita 27 índices no agrupados. Necesita 1 índice agrupado y 5 índices no agrupados o, quizás 6 indexex no agrupados.Esta consulta quisiera índices en estas columnas:
También noté el siguiente código:
es
NON Sargable
decir, no puede utilizar índices.Para hacer que el código lo
SARgable
cambie a esto:Para responder a su pregunta principal, "¿por qué está recibiendo una búsqueda clave?":
Está obteniendo
KEY Look up
porque parte de la columna que se menciona en la consulta no está presente en un índice de cobertura.Puedes buscar en Google y estudiar sobre
Covering Index
oInclude index
.En mi ejemplo, supongamos que tblQuotes.QuoteStatusID es un índice no agrupado, entonces también puedo cubrir DisplayStatus. Como desea DisplayStatus en Resultset. Cualquier columna que no esté presente en un índice y esté presente en el conjunto de resultados se puede cubrir para evitar
KEY Look Up or Bookmark lookup
. Este es un ejemplo que cubre el índice:** Descargo de responsabilidad: ** Recuerde que lo anterior es solo mi ejemplo. DisplayStatus puede estar cubierto con otro No CI después del análisis.
Del mismo modo, deberá crear un índice y un índice de cobertura en las otras tablas involucradas en la consulta.
También te estás metiendo
Index SCAN
en tu plan.Esto puede suceder porque no hay un índice en la tabla o cuando hay un gran volumen de datos, el optimizador puede decidir escanear en lugar de realizar una búsqueda de índice.
Esto también puede ocurrir debido a
High cardinality
. Obteniendo más filas de las requeridas debido a una unión defectuosa. Esto también se puede corregir.fuente