sql >> Base de Datos >  >> RDS >> Sqlserver

SQL Server:detección de parámetros

Es bueno pero a veces puede ser malo.

La detección de parámetros se trata de que el optimizador de consultas utilice el valor del parámetro proporcionado para determinar el mejor plan de consulta posible. Una de las muchas opciones y que es bastante fácil de entender es si se debe escanear toda la tabla para obtener los valores o si será más rápido usar búsquedas de índice. Si el valor en su parámetro es altamente selectivo, el optimizador probablemente creará un plan de consulta con búsquedas y, si no lo es, la consulta escaneará su tabla.

Luego, el plan de consulta se almacena en caché y se reutiliza para consultas consecutivas que tienen valores diferentes. La parte mala de la detección de parámetros es cuando el plan en caché no es la mejor opción para uno de esos valores.

Datos de muestra:

create table T
(
  ID int identity primary key,
  Value int not null,
  AnotherValue int null
);

create index IX_T_Value on T(Value);

insert into T(Value) values(1);

insert into T(Value)
select 2
from sys.all_objects;

T es una tabla con un par de miles de filas con un índice no agrupado en Valor. Hay una fila donde el valor es 1 y el resto tiene el valor 2 .

Ejemplo de consulta:

select *
from T 
where Value = @Value;

Las opciones que tiene el optimizador de consultas aquí son hacer un escaneo de índice agrupado y verificar la cláusula where en cada fila o usar una búsqueda de índice para encontrar filas que coincidan y luego hacer una búsqueda de clave para obtener los valores de las columnas solicitadas en la lista de columnas.

Cuando el valor rastreado es 1 el plan de consulta se verá así:

Y cuando el valor olfateado es 2 se verá así:

La parte mala de la detección de parámetros en este caso ocurre cuando el plan de consulta se crea detectando un 1 pero ejecutado más tarde con el valor de 2 .

Puede ver que la búsqueda de claves se ejecutó 2352 veces. Un escaneo sería claramente la mejor opción.

Para resumir, diría que la detección de parámetros es algo bueno que debe intentar que suceda tanto como sea posible mediante el uso de parámetros en sus consultas. A veces puede salir mal y, en esos casos, lo más probable es que se deba a datos sesgados que interfieren con sus estadísticas.

Actualización:

Aquí hay una consulta contra un par de dmv que puede usar para encontrar qué consultas son más costosas en su sistema. Cambie a orden por cláusula para usar diferentes criterios sobre lo que está buscando. Creo que TotalDuration es un buen lugar para comenzar.

set transaction isolation level read uncommitted;

select top(10)
  PlanCreated       = qs.creation_time,
  ObjectName        = object_name(st.objectid),
  QueryPlan         = cast(qp.query_plan as xml),
  QueryText         = substring(st.text, 1 + (qs.statement_start_offset / 2), 1 + ((isnull(nullif(qs.statement_end_offset, -1), datalength(st.text)) - qs.statement_start_offset) / 2)),
  ExecutionCount    = qs.execution_count,
  TotalRW           = qs.total_logical_reads + qs.total_logical_writes,
  AvgRW             = (qs.total_logical_reads + qs.total_logical_writes) / qs.execution_count,
  TotalDurationMS   = qs.total_elapsed_time / 1000,
  AvgDurationMS     = qs.total_elapsed_time / qs.execution_count / 1000,
  TotalCPUMS        = qs.total_worker_time / 1000,
  AvgCPUMS          = qs.total_worker_time / qs.execution_count / 1000,
  TotalCLRMS        = qs.total_clr_time / 1000,
  AvgCLRMS          = qs.total_clr_time / qs.execution_count / 1000,
  TotalRows         = qs.total_rows,
  AvgRows           = qs.total_rows / qs.execution_count
from sys.dm_exec_query_stats as qs
  cross apply sys.dm_exec_sql_text(qs.sql_handle) as st
  cross apply sys.dm_exec_text_query_plan(qs.plan_handle, qs.statement_start_offset, qs.statement_end_offset) as qp
--order by ExecutionCount desc
--order by TotalRW desc
order by TotalDurationMS desc
--order by AvgDurationMS desc
;