sql >> Databasteknik >  >> RDS >> Sqlserver

SQL Server - parametersniffning

Det är bra men kan vara dåligt ibland.

Parametersniffning handlar om att frågeoptimeraren använder värdet på den angivna parametern för att ta reda på den bästa möjliga frågeplanen. Ett av många val och ett som är ganska lätt att förstå är om hela tabellen ska skannas för att få värdena eller om det kommer att gå snabbare med indexsökningar. Om värdet i din parameter är mycket selektivt kommer optimeraren troligen att bygga en frågeplan med sökningar och om det inte är det kommer frågan att göra en genomsökning av din tabell.

Frågeplanen cachelagras sedan och återanvänds för på varandra följande frågor som har olika värden. Den dåliga delen av parametersniffning är när den cachade planen inte är det bästa valet för ett av dessa värden.

Exempeldata:

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 är en tabell med ett par tusen rader med ett icke klustrat index på Value. Det finns en rad där värdet är 1 och resten har värdet 2 .

Exempelfråga:

select *
from T 
where Value = @Value;

Valen som frågeoptimeraren har här är att antingen göra en Clustered Index Scan och kontrollera where-satsen mot varje rad eller använda en Index Seek för att hitta till rader som matchar och sedan göra en Key Lookup för att få värdena från kolumnerna som efterfrågas i kolumnlistan.

När det sniffade värdet är 1 frågeplanen kommer att se ut så här:

Och när det sniffade värdet är 2 det kommer att se ut så här:

Den dåliga delen av parametersniffning i det här fallet inträffar när frågeplanen är byggd genom att sniffa en 1 men exekveras senare med värdet 2 .

Du kan se att nyckelsökningen utfördes 2352 gånger. En skanning skulle helt klart vara det bättre valet.

För att sammanfatta skulle jag säga att parametersniffning är en bra sak som du bör försöka få till stånd så mycket som möjligt genom att använda parametrar för dina frågor. Ibland kan det gå fel och i de fallen beror det med största sannolikhet på skev data som krånglar till din statistik.

Uppdatering:

Här är en fråga mot ett par dmv:er som du kan använda för att hitta vilka frågor som är dyrast på ditt system. Ändra till beställning efter klausul för att använda olika kriterier på vad du letar efter. Jag tror att TotalDuration är ett bra ställe att börja.

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. Hur kontrollerar du om IDENTITY_INSERT är inställt på PÅ eller AV i SQL Server?

  2. MySQL-frågor

  3. near synatx error (kod 1) infoga Android SQLite

  4. En introduktion till MySQL-distribution med en Ansible-roll