sql >> Databasteknik >  >> RDS >> Database

Ställa in och identifiera radmål i genomförandeplaner

Introduktion

SQL Server-produktdokumentationen är lite lätt på ämnet radmål . De viktigaste officiella referenserna finns i:

  • Tips (Transact-SQL) – Fråga (FAST och DISABLE_OPTIMIZER_ROWGOAL tips)
  • DBCC TRACEON – Spårningsflaggor (Transact-SQL) (spårningsflagga 4138)
  • En fråga kan ta lång tid att köra om frågeoptimeraren använder topoperatorn (KB 2667211)

När folk ber om mer information än vad som finns där, hänvisar jag dem normalt till ett eller flera av följande:

  • Radmål i aktion av SQL Server Query Optimization Team
  • Radmål återbesökt – SNABB tipsvägledning även av SQL Server Query Optimization Team
  • Row Goals Gone Rogue av Bart Duncan
  • Inuti Optimizern:Radmål på djupet av mig
  • SSIS-trimningstipset som alla missar av Rob Farley

För att sammanfatta kort:Radmålsfunktionen tillåter optimeraren att generera en exekveringsplan (eller delar av en exekveringsplan) med syftet att returnera ett visst antal rader snabbt. Detta i motsats till det normala beteendet (utan ett radmål), som syftar till att hitta en plan som är optimerad för hela potentiella resultatuppsättningen.

En radmålsstrategi innebär i allmänhet att gynna icke-blockerande navigeringsoperationer (till exempel kapslade slingor, indexsökningar och uppslagningar) framför blockerande, uppsättningsbaserade operationer som sortering och hash. Detta kan vara användbart närhelst klienten kan dra nytta av en snabb uppstart och en stadig ström av rader (med kanske en längre total körningstid – se Rob Farleys inlägg ovan). Det finns också de mer uppenbara och traditionella användningsområdena t.ex. att presentera resultat en sida i taget.

Naturligtvis finns det ett inslag av risk med en radmålsplan. Om allt fungerar i stort sett som optimeraren förväntar sig (med tanke på den tillgängliga informationen och de gjorda modelleringsantagandena), kommer exekveringsplanen att börja streama det begärda antalet rader snabbare och mer effektivt än vad som skulle ha varit fallet utan radmålet.

Tyvärr, när radmålsstrategin går fel, kan det bli en prestationskatastrof (se Bart Duncans inlägg). Detta kan till exempel hända när optimeraren har ofullständig information, stöter på en ogynnsam datadistribution eller gör ett osäkert antagande. Hur som helst är orsaken till den dåliga prestandan nästan alltid att många fler rader behöver bearbetas vid körningstid än vad optimeraren förväntade sig.

Det kan vara mycket användbart att identifiera exekveringsplanområden som påverkas av ett radmål, eftersom det hjälper oss att förstå varför optimeraren gjorde de val den gjorde. Detta är särskilt viktigt när radmålslogiken ger ett negativt resultat. Utan att förstå vilken roll radmålet spelar kan det se ut som om optimeraren helt enkelt underskattade antalet rader, vilket leder till att människor letar på fel ställen (t.ex. statistik) efter en grundorsak.

Ställa in radmål

Det är mycket lättare att leta efter radmålseffekter om man vet vilken typ av saker som kan orsaka att ett radmål ställs in i första hand. Den officiella dokumentationen talar ofta om att radmål är associerade med nyckelorden TOP , FAST , IN och EXISTS . Detta kan lämna läsaren med en ofullständig eller missvisande förståelse, så det är värt att ta en stund för att klargöra vissa aspekter.

Jag vill understryka direkt att att använda specifika T-SQL-sökord i en frågagarantier inte att ett radmål kommer att ställas in . Den officiella dokumentationen nämner vissa nyckelord för att hjälpa människor att identifiera vanliga scenarier där radmål kan införas, utan att gå in på alltför många tekniska detaljer.

En andra allmän punkt att tänka på är attett radmål endast ställs in när målet skulle vara mindre än den vanliga uppskattningen . När allt kommer omkring är det ingen mening med att generera ett planfragment optimerat för 100 rader om det hela bara förväntas producera 50 rader ändå. För att vara extra tydlig gäller denna punkt alltid alla sätt som ett radmål kan sättas på. Om du förväntar dig ett radmål, men inte ser ett, är detta en trolig orsak.

Slutligen, för ingressen, notera att radmål är en kostnadsbaserad optimeringsgrej; ett radmål påverkar optimeringsvalen, så om det inte finns några val att göra (dvs. en trivial plan) finns det ingen radmålseffekt.

Låt oss nu titta på de saker som kan sätta ett radmål:

SNABB och TOPP

Använd FAST frågetips är ett tillförlitligt sätt att ställa in ett radmål vid roten av genomförandeplanen (med förbehåll för de allmänna undantagen som anges ovan). A SET ROWCOUNT n uttalande anger också ett liknande radmål på toppnivå (när n är naturligtvis inte noll) för de påståenden det gäller.

Att skriva en TOP klausul i en fråga resulterar också mycket ofta i ett radmål. Så länge som den färdiga utförandeplanen innehåller en fysisk toppoperatör är det troligt att åtminstone en del av planen under toppoperatören påverkades av ett radmål (återigen, de allmänna villkoren gäller).

Observera att Topoperatorer introducerade av frågeoptimeraren (utan en frågespecificerad TOP klausul) kan också sätta ett radmål. Detta är viktigt, eftersom det finns alla möjliga sätt som detta kan hända, till exempel när du filtrerar på ett enkelt radnummer, som visas i följande AdventureWorks-fråga:

SELECT
    THN.RowNum,
    THN.TransactionID 
FROM 
(
    SELECT 
        TH.TransactionID, 
        RowNum = 
            ROW_NUMBER() OVER (
                ORDER BY TH.TransactionID ASC)
    FROM Production.TransactionHistory AS TH
    WHERE
        TH.ProductID = 400
) AS THN
WHERE
    THN.RowNum >= 10
    AND THN.RowNum < 20
ORDER BY
    THN.RowNum ASC;

Exekveringsplanen för den frågan inkluderar en Top-operator som lagts till av optimeraren (för att begränsa antalet rader som behandlas till 20):