pirmdiena, 2011. gada 3. janvāris

UNION un UNION ALL ātrdarbības salīdzinājums

Union tiek izmantots, lai no divām vai vairākām rezultātu kopām iegūtu to apvienojumu. Norādot Union (bez All) no rezultāta tiek izslēgtas tās rindas, kas atkārtojas vairākas reizes.

Ideja- manā praksē visbiežāk rezultāts, ko ir jāiegūst rakstot vaicājumu ar Union, ir divu dažādu rezultātu kopu pilnīgi visu rindu apvienojums. Situācijas, kad var rasties dublikātu rindas un kad dublikāti nav pieļaujami, ir salīdzinoši reti. Un tomēr- parasti esmu rakstījis Union nevis Union All. Slikti tas ir tāpēc, ka Union (bez All) nozīmē nevajadzīgu darbu, ja nav nepieciešams izslēgt dublikātus.

Lai ilustrētu situāciju, izmantošu piemēra tabulu, kuras izveides un aizpildīšanas skripti ir atrodami šajā rakstā.
Pirmajā gadījumā izpildot vaicājumu:
select TestTableID, TrisBurti from dbo.TestTable Where Skaitlis = 25
Union
select TestTableID, TrisBurti from dbo.TestTable Where Skaitlis = 12
Tiek iegūts izpildes plāns:


Otrajā gadījumā izpildot vaicājumu:
select TestTableID, TrisBurti from dbo.TestTable Where Skaitlis = 25
Union All
select TestTableID, TrisBurti from dbo.TestTable Where Skaitlis = 12
Tiek iegūts izpildes plāns:
Atšķirība ir tajā, ka rezultātu kopas pirmajā gadījumā tiek apvienotas izslēdzot dublikātus (Merge Join), savukārt otrajā gadījumā- tiek apvienotas dublikātus neizslēdzot (Concatenation). Kā redzams- pirmājā izpildes plānā apvienošanas operācija aizņem procentuāli vairāk laika. Šajā gadījumā gan atšķirība ir šķietami maza, jo, salīdzinoši, daudz vairāk laika patērē vajadzīgo datu atlase (tādēļ, ka nav indeksa uz kolonas "Skaitlis". Ja būtu indekss, tad atšķirība būtu būtiskāka- Merge Join patērētu 9% no resursiem, kas nepieciešami vaicājuma izpildei, savukārt Concatenation 0%- respektīvi, gandrīz nemaz).

Esmu lasījis, ka vaicājuma izpildes laiks var tikt samazināts līdz pat 30% izmantojot Union All nevis Union. Paskatījos dažus vaicājumus ar Union un salīdzinot- tajos atšķirība bija robežās 5%-15% ātrāk ja izmanto Union All.

Vienu vaicājumu pamocīju vairāk. Vaicājums sastāv no vairākām tabulām (deviņām) + viena tabula, kas savukārt ir divu rezultātu kopu apkopojums. Nav nepieciešams izslēgt dublikāta rindas, jo tādas šajā vaicājumā nemaz nevar rasties. Ar Union abas apvienojamās kopas satur attiecīgi 218314 un 6 rindas, tātad kopā- 218320 rindas.
Ar sql profiler palīdzību ieguvu šādus izpildes laiku rezultātus:
Kā redzams, šajā gadījumā ieguvums ir no CPU resursu patēriņa puses. Manuprāt- diezgan labs uzlabojums ņemot vērā to, ka abos gadījumos vaicājums atgriež identiski tos pašus rezultāts, tikai otrajā neveicot pilnīgi lieku dublikātu meklēšanu.

5 komentāri:

  1. Pirmajā rindkopā gan jau bija domāts "Union" nevis "Union All" ;)

    AtbildētDzēst
  2. Kuru rindkopu saskatiji par pirmo - jautajums. Es nekadu kludu nepamaniju...

    AtbildētDzēst
  3. Hmm, man izskatās pareizi. Kuru Tu domāji?

    AtbildētDzēst
  4. Otrais teikums: "Norādot Union All no rezultāta tiek izslēgtas tās rindas, kas atkārtojas vairākas reizes."

    AtbildētDzēst
  5. Jā, ieraudzīju un izlaboju! Paldies!

    AtbildētDzēst