Articles

UNION all optimering

sammenkædningen af to eller flere datasæt udtrykkes oftest i T-KVL ved hjælp afUNION ALL klausulen. I betragtning af at vi ofte kan omarrangere ting som joinforbindelser og aggregater for at forbedre ydeevnen, er det ret rimeligt at forvente, at vi også vil overveje at omarrangere sammenkædningsindgange, hvor dette ville give en fordel. For eksempel kan optimeringen overveje fordelene ved at omskrive A UNION ALL B som B UNION ALL A.

faktisk gør SERVEROPTIMERINGEN ikke dette. Mere præcist var der en vis begrænset understøttelse af sammenkædningsinput omlægning i SEKL-serverudgivelser op til 2008 R2, men dette blev fjernet i SEKL-Server 2012 og er ikke dukket op igen siden.

Server 2008 R2

intuitivt betyder rækkefølgen af sammenkædningsindgange kun noget, hvis der er et rækkemål. Som standard optimerer vi eksekveringsplaner ud fra, at alle kvalificerende rækker vil blive returneret til klienten. Når et rækkemål er i kraft, forsøger optimatoren at finde en eksekveringsplan, der hurtigt producerer de første par rækker.

Rækkemål kan indstilles på en række måder, for eksempel ved hjælp af TOP, a FAST n forespørgselstip eller ved at bruge EXISTS (som i sagens natur skal finde højst en række). Hvor der ikke er noget rækkemål (dvs.klienten kræver alle rækker), betyder det generelt ikke noget i hvilken rækkefølge sammenkædningsindgangene læses: hvert input behandles til sidst under alle omstændigheder fuldt ud.

den begrænsede support i versioner op til Server 2008 R2 gælder, hvor der er et mål på nøjagtigt en række. I denne særlige situation, vil vi omarrangere sammenkædningsindgange på grundlag af forventede omkostninger.

dette gøres ikke under omkostningsbaseret optimering (som man kunne forvente), men snarere som en omskrivning i sidste øjeblik efter optimering af det normale optimeringsoutput. Dette arrangement har den fordel, at det ikke øger det omkostningsbaserede plansøgningsrum (potentielt et alternativ til hver mulig omregning), mens det stadig producerer en plan, der er optimeret til hurtigt at returnere den første række.

eksempler

følgende eksempler bruger to tabeller med identisk indhold: en million rækker af heltal fra en til en million. Den ene tabel er en bunke uden ikke-lukkede indekser; den anden har et unikt grupperet indeks:

ingen række mål

følgende forespørgsel ser efter de samme rækker i hver tabel og returnerer sammenkædningen af de to sæt:

SELECT E.Val FROM dbo.Expensive AS E WHERE E.Val BETWEEN 751000 AND 751005 UNION ALL SELECT C.ValFROM dbo.Cheap AS C WHERE C.Val BETWEEN 751000 AND 751005;

:

UNION alle uden et række mål

advarslen på rodenSELECT operatør advarer os om det åbenlyse manglende indeks på bunkebordet. Advarslen på bordet scan operatør er tilføjet af Sentry en plan opdagelsesrejsende. Det henleder vores opmærksomhed på I / O-omkostningerne ved det resterende prædikat, der er skjult i scanningen.

rækkefølgen af indgangene til sammenkædningen betyder ikke noget her, fordi vi ikke har sat et rækkemål. Begge indgange læses fuldt ud for at returnere alle resultatrækker. Af interesse (selvom dette ikke er garanteret) bemærk, at rækkefølgen af input følger den tekstmæssige rækkefølge af den oprindelige forespørgsel. Vær også opmærksom på, at rækkefølgen af de endelige resultatrækker heller ikke er angivet, da vi ikke brugte et topniveau ORDER BY klausul. Vi antager, at det er bevidst, og den endelige bestilling er uden betydning for den aktuelle opgave.

Hvis vi vender den skriftlige rækkefølge af tabellerne i forespørgslen som sådan:

SELECT C.ValFROM dbo.Cheap AS C WHERE C.Val BETWEEN 751000 AND 751005 UNION ALL SELECT E.Val FROM dbo.Expensive AS E WHERE E.Val BETWEEN 751000 AND 751005;

UNION ALL with reversed inputsunion alle med omvendte indgange

begge forespørgsler kan forventes at have de samme ydeevneegenskaber, da de udfører de samme operationer, bare i en anden rækkefølge.

med et Rækkemål

det er klart, at manglen på indeksering på bunkebordet normalt vil gøre det at finde specifikke rækker dyrere sammenlignet med den samme operation på det grupperede bord. Hvis vi beder optimeringsenheden om en plan, der hurtigt returnerer den første række, forventer vi, at vi omarrangerer sammenkædningsindgangene, så den billige grupperede tabel konsulteres først.

brug af forespørgslen, der nævner heap-tabellen først, og brug et hurtigt 1 forespørgselstip til at specificere rækkemålet:

SELECT E.Val FROM dbo.Expensive AS E WHERE E.Val BETWEEN 751000 AND 751005 UNION ALL SELECT C.ValFROM dbo.Cheap AS C WHERE C.Val BETWEEN 751000 AND 751005OPTION (FAST 1);

den estimerede eksekveringsplan, der er produceret på en forekomst af SDR-Server 2008 R2, er:

union alle med et rækkemål på 2008 R2

bemærk, at sammenkædningsindgangene er blevet omordnet for at reducere de anslåede omkostninger ved at returnere den første række. Bemærk også, at det manglende indeks og resterende I/O-advarsler er forsvundet. Ingen af problemerne er af betydning med denne planform, når målet er at returnere en enkelt række så hurtigt som muligt.

den samme forespørgsel, der udføres på SDC Server 2016 (ved hjælp af en af kardinalitetsestimeringsmodellerne) er:

UNION alle med et rækkemål på 2016

SDC Server 2016 har ikke omordnet sammenkædningsindgangene. Planen opdagelsesrejsende i/O advarsel er vendt tilbage, men desværre optimeringen har ikke produceret en manglende indeks advarsel denne gang (selvom det er relevant).

generel genbestilling

som nævnt er postoptimeringsskrivningen, der genbestiller sammenkædningsindgange, kun effektiv til:2008 R2 og tidligere

  • et rækkemål på nøjagtigt et
  • Hvis vi virkelig kun vil have en række returneret, snarere end en plan optimeret til at returnere den første række hurtigt (men som i sidste ende stadig vil returnere alle rækker), kan vi bruge enTOP klausul med en afledt tabel eller fælles tabeludtryk (CTE):

    SELECT TOP (1) UA.ValFROM( SELECT E.Val FROM dbo.Expensive AS E WHERE E.Val BETWEEN 751000 AND 751005 UNION ALL SELECT C.Val FROM dbo.Cheap AS C WHERE C.Val BETWEEN 751000 AND 751005) AS UA;

    :

    UNION alle med TOP på 2008 R2

    på Server 2012, 2014 og 2016 Ingen post-optimering genbestilling forekommer:

    UNION alle med TOP på 2012-2016

    hvis vi vil have mere end en række returneret, for eksempel ved hjælp afTOP (2), vil den ønskede omskrivning ikke blive anvendt på kvm Server 2008 R2, selvom etFAST 1 tip bruges også. I den situation er vi nødt til at ty til tricks som at bruge TOP med en variabel og en OPTIMIZE FOR tip:

    DECLARE @TopRows bigint = 2; -- Number of rows actually needed SELECT TOP (@TopRows) UA.ValFROM( SELECT E.Val FROM dbo.Expensive AS E WHERE E.Val BETWEEN 751000 AND 751005 UNION ALL SELECT C.Val FROM dbo.Cheap AS C WHERE C.Val BETWEEN 751000 AND 751005) AS UAOPTION (OPTIMIZE FOR (@TopRows = 1)); -- Just a hint

    forespørgslen antydning er tilstrækkelig til at indstille en række mål for en, mens runtime værdien af den variabel, der sikrer, at de ønskede antal rækker (2) er vendt tilbage.

    den faktiske eksekveringsplan på Server 2008 R2 er:

    UNION alle med variabel og optimer for på 2008 R2

    begge rækker returneres kommer fra den omordnede søgeindgang, og Bordscanningen udføres slet ikke. Planstifinder viser rækketællingerne i rødt, fordi estimatet var for en række (på grund af antydningen), mens der blev fundet to rækker på kørselstidspunktet.

    uden UNION alle

    dette problem er heller ikke begrænset til forespørgsler skrevet eksplicit medUNION ALL. Andre konstruktioner såsom EXISTSog OR kan også resultere i, at optimeringen introducerer en sammenkædningsoperatør, som kan lide af manglen på omregning af input. Der var et nyligt spørgsmål om databaseadministratorer Stakudveksling med netop dette problem. Omdanne forespørgslen fra dette spørgsmål til at bruge vores eksempel tabeller:

    / p >

    sagsforespørgsel på 2016

    på KVL-Server 2008 R2 rækkefølgen af indgangene er optimeret til at afspejle det enkelte række mål for semi-sammenføjningen:

    sagsforespørgsel på 2008 R2

    i den mere optimale plan, heap scanningen udføres aldrig.

    løsninger

    i nogle tilfælde vil det være tydeligt for forespørgselsforfatteren, at en af sammenkædningsindgangene altid vil være billigere at køre end de andre. Hvis det er sandt, er det ret gyldigt at omskrive forespørgslen, så de billigere sammenkædningsindgange først vises i skriftlig rækkefølge. Det betyder selvfølgelig, at forespørgselsforfatteren skal være opmærksom på denne optimeringsbegrænsning og parat til at stole på udokumenteret adfærd.

    et vanskeligere problem opstår, når omkostningerne ved sammenkædningsindgange varierer med omstændighederne, måske afhængigt af parameterværdier. Brug af OPTION (RECOMPILE) hjælper ikke på Server 2012 eller senere. Denne mulighed kan hjælpe på Server 2008 R2 eller tidligere, men kun hvis kravet om enkelt række mål også er opfyldt.

    hvis der er bekymringer om at stole på observeret adfærd (forespørgselsplan sammenkædningsindgange, der matcher forespørgslens tekstrækkefølge), kan en planguide bruges til at tvinge figuren plan. Hvor forskellige inputordrer er optimale til forskellige omstændigheder, kan der anvendes flere planguider, hvor betingelserne kan kodes nøjagtigt på forhånd. Dette er dog næppe ideelt.

    Final Thoughts

    serverforespørgselsoptimering indeholder faktisk en omkostningsbaseret efterforskningsregel,UNIAReorderInputs, som er i stand til at generere sammenkædningsinputordrevariationer og udforske alternativer under omkostningsbaseret optimering (ikke som en enkelt-shot post-optimering omskrivning).

    denne regel er i øjeblikket ikke aktiveret til generel brug. Så vidt jeg kan fortælle, aktiveres den kun, når en planguide eller USE PLAN hint er til stede. Dette gør det muligt for motoren at tvinge en plan, der blev genereret til en forespørgsel, der kvalificerede sig til omskrivning af input-omstilling, selv når den aktuelle forespørgsel ikke kvalificerer sig.

    min mening er, at denne udforskningsregel bevidst er begrænset til denne brug, fordi forespørgsler, der ville drage fordel af sammenkædning af input omregning som en del af omkostningsbaseret optimering, betragtes som ikke tilstrækkeligt almindelige, eller måske fordi der er en bekymring for, at den ekstra indsats ikke ville betale sig. Min egen opfattelse er, at Sammenkædning operatør input genbestilling bør altid undersøges, når en række mål er i kraft.

    det er også en skam, at den (mere begrænsede) omskrivning efter optimering ikke er effektiv i Server 2012 eller senere. Dette kunne have været på grund af en subtil fejl, men jeg kunne ikke finde noget om dette i dokumentationen, videnbasen eller på Connect. Jeg har tilføjet et nyt Connect-element her.

    opdatering 9. August 2017: Dette er nu rettet under sporingsflag 4199 for Server 2014 og 2016, se KB 4023419:

    rettelse: Forespørgsel med UNION All og et rækkemål kan køre langsommere i Server 2014 eller nyere versioner, når det sammenlignes med Server 2008 R2