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 = 25Tiek iegūts izpildes plāns:
Union
select TestTableID, TrisBurti from dbo.TestTable Where Skaitlis = 12
Otrajā gadījumā izpildot vaicājumu:
select TestTableID, TrisBurti from dbo.TestTable Where Skaitlis = 25Tiek iegūts izpildes plāns:
Union All
select TestTableID, TrisBurti from dbo.TestTable Where Skaitlis = 12
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.
Pirmajā rindkopā gan jau bija domāts "Union" nevis "Union All" ;)
AtbildētDzēstKuru rindkopu saskatiji par pirmo - jautajums. Es nekadu kludu nepamaniju...
AtbildētDzēstHmm, man izskatās pareizi. Kuru Tu domāji?
AtbildētDzēstOtrais teikums: "Norādot Union All no rezultāta tiek izslēgtas tās rindas, kas atkārtojas vairākas reizes."
AtbildētDzēstJā, ieraudzīju un izlaboju! Paldies!
AtbildētDzēst