sql >> Database teknologi >  >> RDS >> Sqlserver

SQL Server - parametersniffing

Det er godt, men kan nogle gange være dårligt.

Parametersniffing handler om, at forespørgselsoptimeringsværktøjet bruger værdien af ​​den angivne parameter for at finde ud af den bedst mulige forespørgselsplan. Et af mange valg og et, der er ret nemt at forstå, er, om hele tabellen skal scannes for at få værdierne, eller om det vil være hurtigere ved at bruge indekssøgninger. Hvis værdien i din parameter er meget selektiv, vil optimeringsværktøjet sandsynligvis bygge en forespørgselsplan med søgninger, og hvis den ikke er det, vil forespørgslen foretage en scanning af din tabel.

Forespørgselsplanen cachelagres derefter og genbruges til på hinanden følgende forespørgsler, der har forskellige værdier. Den dårlige del af parametersniffing er, når den cachelagrede plan ikke er det bedste valg for en af ​​disse værdier.

Eksempeldata:

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 er en tabel med et par tusinde rækker med et ikke-klynget indeks på Værdi. Der er én række, hvor værdien er 1 og resten har værdien 2 .

Eksempelforespørgsel:

select *
from T 
where Value = @Value;

Valgene, som forespørgselsoptimeringsværktøjet har her, er enten at lave en Clustered Index Scan og kontrollere where-sætningen mod hver række eller bruge en Index Seek til at finde til rækker, der matcher og derefter lave et nøgleopslag for at få værdierne fra de kolonner, der bliver bedt om i kolonnelisten.

Når den sniffede værdi er 1 forespørgselsplanen vil se sådan ud:

Og når den sniffede værdi er 2 det vil se sådan ud:

Den dårlige del af parametersniffing sker i dette tilfælde, når forespørgselsplanen er bygget ved at sniffe en 1 men udført senere med værdien 2 .

Du kan se, at nøgleopslaget blev udført 2352 gange. En scanning ville klart være det bedre valg.

For at opsummere vil jeg sige, at parametersniffing er en god ting, som du bør prøve at få til at ske så meget som muligt ved at bruge parametre til dine forespørgsler. Nogle gange kan det gå galt og i de tilfælde er det højst sandsynligt på grund af skæve data, der roder med dine statistikker.

Opdatering:

Her er en forespørgsel mod et par dmv'er, som du kan bruge til at finde ud af, hvilke forespørgsler der er dyrest på dit system. Skift til orden efter klausul for at bruge forskellige kriterier på det, du leder efter. Jeg tror, ​​at TotalDuration er et godt sted at starte.

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
;


  1. Udførelse af dataændringsrevision ved hjælp af tidsmæssig tabel

  2. PostgreSQL fejl ved forsøg på at oprette en udvidelse

  3. Fjernede ved et uheld postgres standard superbruger privilegier - kan jeg få det tilbage?

  4. Minimal logning med INSERT...SELECT i tomme grupperede tabeller