7 web view2004/2005. saturs. 1.neparastās savienojumu diagrammas4. 1.1.ciklisko savienojumu...

83
RĪGAS TEHNISKĀ UNIVERSITĀTE DATORZINĀTNES UN INFORMĀCIJAS TEHNOLOĢIJAS FAKULTĀTE LIETIŠĶO DATORSISTĒMU INSTITŪTS Sistēmu teorijas un projektēšanas katedra Patstāvīgais darbs “Saliktu SQL vaicājumu attēlošana diagrammu veidā” mācību priekšmetā “Informācijas sistēmas un CASE rīki” Izstrādāja: Ieva Valkovska, 2 DMD-3 Pārbaudīja: asoc. prof. J.Eiduks

Upload: nguyenngoc

Post on 06-Feb-2018

241 views

Category:

Documents


9 download

TRANSCRIPT

RĪGAS TEHNISKĀ UNIVERSITĀTE

DATORZINĀTNES UN INFORMĀCIJAS TEHNOLOĢIJAS FAKULTĀTE

LIETIŠĶO DATORSISTĒMU INSTITŪTS

Sistēmu teorijas un projektēšanas katedra

Patstāvīgais darbs

“Saliktu SQL vaicājumu attēlošana diagrammu veidā”

mācību priekšmetā“Informācijas sistēmas un CASE rīki”

Izstrādāja: Ieva Valkovska, 2 DMD-3

Pārbaudīja: asoc. prof. J.Eiduks

2004/2005

SATURS

1. Neparastās savienojumu diagrammas......................................................................................41.1. Ciklisko savienojumu grafi.............................................................................................4

1.1.1. 1.gadījums. Divas galvenās tabulas ar attiecību „viens pret vienu” kopīgi izmanto vienu un to pašu detaļu tabulu..................................................................................................41.1.2. 2.gadījums. Galvenajā un detaļu tabulās glabājas ārējās atslēgas kopijas, kuras norāda uz vienu un to pašu trešās tabulas primāro atslēgu......................................................61.1.3. 3.gadījums. Divmezglu filtrs (nav unikāls abos galos) jau sasaistīts ar vienkāršo savienojumu palīdzību.............................................................................................................71.1.4. 4.gadījums. Kompozītsavienojums no divām ārējām atslēgām uz primāro kompozītatslēgu sadalīts divās tabulās....................................................................................91.1.5. Kopsavilkums par cikliskiem savienojumiem......................................................11

1.2. Nesaistītas vaicājumu diagrammas...............................................................................111.3. Vaicājumu diagrammas ar vairākiem sakņu mezgliem.................................................14

1.3.1. 1.gadījums. Iztrūkstošais savienojuma nosacījums..............................................151.3.2. 2.gadījums. Dekarta reizinājuma sadalīšana vairākos vaicājumos.......................161.3.3. 3.gadījums. Attiecība ar sakņu detaļu tabulām ne vairāk kā „viens pret vienu”. .161.3.4. 4.gadījums. Eksistences pārbaudes pārvēršana par neslēptu apakšvaicājumu.....17

1.4. Savienojums bez primārām atslēgām............................................................................181.5. Savienojums „viens pret vienu”....................................................................................19

1.5.1. Savienojums „viens pret vienu” ar tabulu - apakškopu........................................191.5.2. Precīzie savienojumi „viens pret vienu”...............................................................201.5.3. Savienojums „viens pret vienu” ar ievērojamāki mazāku datu kopu...................211.5.4. Savienojumi „viens pret vienu” ar slēpto savienojuma filtru abos virzienos.......211.5.5. Vienošanās par savienojumu „viens pret vienu” attēlošanu.................................22

1.6. Ārējie savienojumi........................................................................................................231.6.1. Filtrētie ārējie savienojumi...................................................................................231.6.2. Ārējie savienojumi, kas ved pie iekšējiem savienojumiem..................................261.6.3. Ārējie savienojumi, kas norāda uz detaļu tabulu..................................................271.6.4. Ārējie savienojumi ar detaļu tabulu ar filtru.........................................................28

2. Vaicājumi ar apakšvaicājumiem............................................................................................292.1. Vaicājumu ar apakšvaicājumiem attēlošana uz diagrammām.......................................29

2.1.1. Apakšvaicājumu EXISTS diagrammu attēlojums..................................................302.1.2. Apakšvaicājuma NOT EXISTS diagrammu attēlojums..........................................36

2.2. Vaicājumu ar apakšvaicājumiem regulēšana................................................................373. Vaicājumi ar attēlojumiem.....................................................................................................40

3.1. Vaicājumu, kuri izmanto attēlojumus, diagrammu attēlošana......................................413.2. Vaicājumu ar attēlojumiem regulēšana.........................................................................44

3.2.1. Ārējie savienojumi ar attēlojumiem.....................................................................453.2.2. Liekie nolasījumi vaicājumos, izmantojošiem attēlojumus..................................473.2.3. Liekie mezgli un savienojumi...............................................................................48

4. Vaicājumi ar operācijām uz kopām.......................................................................................495. Vingrinājums..........................................................................................................................50

5.1.1. Risinājums uzdevumam no nodaļas.....................................................................51

2

Komplicētu SQL-vaicājumu attēlošana diagrammu veidā un regulēšana

Grāmatas iepriekšējās nodaļās ir apskatīts kā izveidot diagrammu un pielāgot vaicājumus reālām tabulām, kad diagramma atbilst vairākām prasībām pret parastu biznesa vaicājumu.■ Vaicājums tiek attēlots uz viena koka.■ Kokam ir viens saknes mezgls, t.i. viena tabula bez savienojumiem izmantojot tās primāro atslēgu. Visiem pārējiem mezgliem, izņemot saknes mezglu, ir pa vienai bultai, kas norāda uz tiem tādējādi savienojot ar detaļas mezglu augšā. Jebkurš mezgls var atrasties jebkāda skaita uz leju norādošo bultiņu augšdaļā. ■ Visiem savienojumiem ir uz leju norādošas bultiņas (savienojumi ir unikāli vienā galā).■ Ārējie savienojumi netiek filtrēti un norāda uz leju; Zem ārējiem savienojumi var atrasties tikai ārējie savienojumi.■ Jautājums, uz kuru atbild vaicājums, parasti ir jautājums par koka saknes mezgla būtību vai par šīs būtības agregāciju.■ Pārējās tabulās glabājas papildus informatīvie dati, kas izvietoti šajās tabulās normalizācijas mērķiem.

Vaicājumus, atbilstošus augstāk minētiem kritērijiem, sauc par vienkāršiem vaicājumiem, kaut gan tie var saturēt jebkādu daudzumu apakšvaicājumu, un var gadīties, ka to optimizācijai vajadzēs pielietot kaut kādas viltības, it īpaši speciālos gadījumos izvēloties starp filtrēšanas koeficientiem, vai arī gadījumos, kad eksistē savienojumu slēptie filtri.

Vaicājumi ne vienmēr atbilst vienkāršotai standarta formai. Šajos gadījumos vaicājumi tiek saukti par komplicētiem. Šajā nodaļā tiks nodemonstrēts, kā atsevišķi komplicēti vaicājumi rodas kā sekas kļūdām datu bāzes dizainā vai papildinājumos. Tāpat par komplicētu vaicājumu iemeslu varbūt būt realizācijas kļūdas. Bieži vien šāda veida kļūdas tik tiešām noved pie nepareizu vaicājumu rašanās. Šajā nodaļā tiks apskatītas anomālijas, ar kādām var saskarties vaicājumu diagrammās un kuras skaidri norāda par kļūdu vaicājumā vai dizainā. Tāpat tiks apskatīts, kā izlabot šīs funkcionalitātes vai dizaina kļūdas, reizēm vienlaicīgi uzlabojot veiktspēju. Parasti labojumi ļauj pārveidot vaicājumu vienkāršā formā vai, vismaz formā, kas ir pietiekami tuva vienkāršai, lai varētu izmantot metodes, kas aprakstītas šajā grāmatā iepriekš.

Atsevišķi komplicētie vaicājumi iziet ārpus jebkādu formu robežām, kad tajos tiek izmantoti apakšvaicājumi, skati (jeb attēlojumi, angl. views) vai operācijas ar kopām, piemēram, UNION un UNION ALL. Parasti šādi komplicēti vaicājumi ir izplatīti un daudzfunkcionāli, tāpēc ir vajadzīgs paņēmiens kā veidot tiem diagrammas un optimizēt. Šādu iemeslu dēļ ir nepieciešams paplašināt iepriekš grāmatā apskatītās metodes vienkāršiem vaicājumiem.

3

T1

T2 T3

1. Neparastās savienojumu diagrammas

Ja vaicājumā ir tikai vienkāršas tabulas (ne skati), nav apakšvaicājumu un operāciju ar kopām, tādu kā UNION, vienmēr var izveidot noteiktu vaicājuma diagrammu, pielietojot metodes no šīs grāmatas 5.nodaļas. Taču reizēm diagrammai piemīt neparasti raksturojumi, kuri neatbilst nevienam kokveida savienojumu šablonam. Tālāk tiks aprakstītas arī šāda veida novirzes un paskaidrots kā tikt galā ar katru no tām.

Neparastu gadījumu ilustrācijai tiks parādītas daļējas vaicājumu diagrammas. Tās diagrammas daļas, kās nav svarīgas apskatāmajam jautājumam, būs nosegtas ar pelēkiem mākoņiem. Tas pievērsīs uzmanību svarīgākajai vaicājuma daļai un padarīs piemēru vispārinošāku. Pelēkā krāsā tiks attēlotas arī saites ar savienojuma skeleta daļām, kas noslēptas aiz mākoņiem, ja tās nav svarīgas apskatāmajā gadījumā. Piemēros pelēko saišu daudzumam un pat to eksistēšanai nav nozīmes, tie vienkārši ilustrē papildus savienojumu potenciālo eksistenci reālajos gadījumos. Dažreiz pie slēptām vaicājuma skeleta daļām būs saites, kas nokrāsotas melnā krāsā. Melno saišu eksistence ir svarīga konkrētajā gadījumā.

1.1. Ciklisko savienojumu grafi

Kā ir jāapstrādā savienojumu skeleti, kurus nevar attēlot ar vienkāršu koku un kuros saites kādā skeleta daļā noslēdzas ciklā? Šādu diagrammu ir iespējams sastapt vairākos gadījumos. Nākošajās grāmatas sadaļās tiks apskatīti četri gadījumi ar dažādiem risinājumiem.PIEZĪME----------------------------------------------------------------------------------------------Grafu teorija ir matemātikas disciplīna, kas apraksta abstraktus jēdzienus, sauktus par grafiem, to saišu un mezglu stāvokli. Šajā grāmatā apskatītās diagrammas arī ir grafi. Grafu teorijā cikliskajā grafā ir saites, kuras formē noslēgtu ciklu. Turpmākajos piemēros, līdz 8.att., Ir jāpievērš uzmanība tam, ka uz diagrammas ir reāli un domājami cikli, kas pārvērš šos grafus cikliskos.

1.1.1. 1.gadījums. Divas galvenās tabulas ar attiecību „viens pret vienu” kopīgi izmanto vienu un to pašu detaļu tabulu

1. att. ir parādīts pirmais gadījums, kad vienīgā ārējā atslēga savienojas ar divu dažādu galveno tabulu primārām atslēgām.

1. att. Ciklisko vaicājuma diagrammu pirmais gadījums

4

T1

T2 T3

T1

T2 T3

T1

T2 T3

SQL-kods šim gadījumam var izskatīties šādi:SELECTFROM …T1, …T2, … T3, …WHERE … T1. FKey1 = T2. FKey2AND T1. FKey1 = T3. PKey3AND T2. PKey2 = T3. PKey3 …

Šeit tiek nosaukta vienīgā ārējā atslēga tabulai T1 (FKey1), kas norāda uz abām tabulām, un attiecīgi arī primārās atslēgas T2 un T3 – PKey2 un PKey3. Ja visi šie trīs savienojumi ir atklāti pierakstīti SQL, tad cikliskās saites ir acīmredzamas, taču ir jāpievērš uzmanību tam, ka viena no šīm saitēm vaicājumā varētu būt izlaista un neesošā savienojuma nosacījums būtu izgūstams pēc transivitātes nosacījuma (ja a = b un b = c, tad a = c). Ja viens no savienojumiem būtu izlaists, tad tam pašam vaicājumam varētu izveidot diagrammu vienā no trim iespējamām formām, kas parādītas 2.att.

2. att. Tas pats cikliskais vaicājums, kurā viens no savienojuma nosacījumiem ir izlaists

Ir jāpievērš uzmanību tam, ka šī vaicājuma variantos A un B par iztrūkstošās bultiņas esamību var iedomāties pēc fakta, ka saitei starp T2 un T3 ir bultiņas smaile abos galos, bet bultiņa abos galos paredz savienojumu „viens pret vienu”. No otras puses, variants C izskatās kā parasts savienojumu koks, un ir grūti iedomāties, ka tajā eksistē ciklisks savienojums, ja neievēro, ka T1 izmanto vienu un to pašu ārējo atslēgu savienojumam ar T2 un T3.

Kad ir tabulas ar attiecībām „viens pret vienu”, tad cikliskie savienojumi, kura piemērs ir apskatīts 1.att., ir sastopami bieži. Tā vietā lai uzskatītu šos savienojumus par problēmu, tos var uzskatīt par veiksmīgu iespēju vaicājuma optimizēšanai. Ja jau ir apstrādāts T1, tad ir svarīgi izvēlēties kam tālāk pievērsties – T2 vai T3, apskatot kuram no tiem var būt labāks filtrēšanas koeficients, vai arī tas var sniegt pieeju pie labākiem filtriem virzoties zemāk pa koku. Ja savienojumu secībā tiek apstrādāti T2 vai T3 līdz T1, tad iespēja veikt savienojumu „viens pret vienu” ar pretējo tabulu (no T2 uz T3 vai no T3 uz T2) arī ir lietderīga. Tas ļauj izmantot jebkādu filtru, kāds var būt otrai tabulai, līdz savienojumam ar T1. Bez horizontālas saites var savienot T2 ar T3 un otrādi tikai caur T1 – iespējams, ar augstāku vērtību.

Atsevišķi optimizatori ir uzrakstīti pietiekoši viltīgi, lai izmantotu transivitāti neesošā savienojuma nosacījuma atjaunošanai, pat, ja tas ir izlaists, un izmantot papildus brīvības pakāpju priekšrocības, kādas dod savienojuma secība. Taču ja ir ievērots, ka divi savienojumi pēc transivitātes likuma paredz trešo, tad drošumam labāk visus trīs

A B C

5

T1

T2 T3

savienojumus pārvērst par atklātiem. Vismaz SQL operatorā ir jāpārvērš par atklātiem visus savienojumus, kādi ir nepieciešami optimālajam plānam.

Eksistē speciāls gadījums, kad tabulas ar attiecībām „viens pret vienu”, apzīmētas kā T2 un T3, ir viena un tā pati tabula. Šajā gadījumā katra rinda no T1 savienojas ar vienu un to pašu rindu no T2 divas reizes. Tas ir absolūti neefektīvi. Acīmredzamais gadījums, kad viens tabulas vārds divas reizes atkārtojas sadaļā FROM un tai tiek piešķirti pseidonīmi T2 un T3, ir maz iespējams, tikai tāpēc, ka tas ir pārāk acīmredzami, lai paliktu neievērots. Taču savienojums ar vienu tabulu divas reizes var notikt neievērots, un izstrādātājs to var palaist garām pie kodu pārlūkošanas. Piemēram, tas var gadīties, ja sinonīms vai vienkārša attēlošana slēpj galvenās tabulas īsto būtību, vismaz ar vienu pseidonīmu vaicājumā. Jebkurā gadījumā labāk atbrīvoties no liekas norādes uz tabulu vaicājumā.

1.1.2. 2.gadījums. Galvenajā un detaļu tabulās glabājas ārējās atslēgas kopijas, kuras norāda uz vienu un to pašu trešās tabulas primāro atslēgu

3.att. parādīts otrais no galvenajiem ciklisko savienojumu gadījumiem. Šeit identiskas ārējās atslēgas tabulās T1 un T2 norāda uz vienu un to pašu primārās atslēgas vērtību tabulā T3.

Šajā gadījumā SQL-kods izskatās sekojoši:SELECTFROM …T1, …T2, … T3, …WHERE … T1. FKey1 = T2. PKey2AND T1. FKey2 = T3. PKey3AND T2. FKey2 = T3. PKey3 …

3.att. Cikliskais savienojums, kas paredz denormalizāciju Šajā SQL operatorā tiek nosauktas ārējās atslēgas, kas norāda no T1 uz T2 un T3,

attiecīgi FKey1 un FKey2. Pēc transivitātes likuma ārējās atslēgas T2. FKey2 stabiņa vērtība vienāda ar T1. FKey vērtību, tā kā abas atslēgas savienojas ar T3. PKey3. T2 un T3 primārās atslēgas tiek sauktas attiecīgi PKey2 un PKey3. Visticamākais izskaidrojums tam, ka T1 un T2 savienojas ar vienu tabulu, T3, pēc tās pilnas primārās atslēgas ir tāds, ka T1 un T2 satur liekas ārējās atslēgas, kuras norāda uz šo tabulu. Šajā scenārijā tabulas T1 stabiņš FKey2 satur denormalizētos datus no tās galvenās tabulas T2. Šie dati vienmēr ir vienādi ar FKey2 vērtību attiecīgajā tabulas T2 galvenajā rindā.

PIEZĪME----------------------------------------------------------------------------------------------

6

T1

T2 T3

Tiek pieņemts, ka FKey2 vērtības sakrīt, taču parasti tas nav tā, tāpēc, ka denormalizētie dati visbiežāk nav sinhronizēti.

10. nodaļā ir uzskaitīti visi par un pret denormalizāciju līdzīgos gadījumos. Īsumā, ja denormalizācija sevi attaisno, iespējams, ka papildus saite vaicājum diagrammā sniegs jums papildus pieeju labākam izpildes plānam. Taču pastāv lielāka varbūtība, ka denormalizācija ir kļūda, kuras riski ir lielāki nekā priekšrocības. Atteikšanās no denormalizācijas nozīmē izņemt ārējo atslēgu FKey2 tabulā T1, tādā veidā novācot saiti no T1 uz T3 un pārvēršot vaicājuma diagrammu kokā.

1.1.3. 3.gadījums. Divmezglu filtrs (nav unikāls abos galos) jau sasaistīts ar vienkāršo savienojumu palīdzību

4.att. parādīts trešais no galvenajiem ciklisko savienojumu gadījumiem. Šoreiz mums ir parastas norādošas uz leju bultiņas no T1 uz T2 un T3, bet eksistē arī trešais, neparasts nosacījums savienojumam starp T2 un T3, kurš neizmanto primāro atslēgu ne no vienas no divām tabulām.

PIEZĪME----------------------------------------------------------------------------------------------Tā kā neviena primārā atslēga netiek izmantota savienojumā starp T2 un T3, tad saitei starp tām nav bultiņas nevienā galā.

Šajā gadījumā SQL-kods izskatās sekojoši:SELECTFROM …T1, …T2, … T3, …WHERE … T1. FKey1 = T2. PKey2

AND T1. FKey2 = T3. PKey3AND T2, Col2<Kaut kādā veidā tiek salīdzināts ar >T3.Col3 …

4.att. Cikliskais savienojums ar divmezglu filtru

Piemēram, ja T1 ir pseidonīms tabulai Orders, kura savienojas ar Customers (T2) un Salespersons (T3), tas varētu nozīmēt, ka vaicājumam ir nepieciešami pasūtījumi, kuros pircēji un atbildīgie pārdevēji ir saistīti ar dažādiem reģioniem:SELECTFROM Orders T1, Customers T2, Salespersons T3WHERE T1. Customer_ID = T2. Customer_ID

AND T1. Salesperson_ID = T3. Salesperson_IDAND T2. Region_ID! = T3. Region_ID

7

T1

T2 T3

0.01

T40.2 0.5 0.3

T5 0.4

Šeit noteikums T2. Region_ID! = T3. Region_ID stingri runājot ir savienojums, taču labāk to ir apskatīt kā filtrēšanas noteikumu, kuram rindas no divām dažādām tabulām ir nepieciešamas vēl pirms tam, kad to var pielietot. Ja tiks ignorēta šī neparastā saite starp T2 un T3, tad vēršanās pie T1 notiks līdz divmezglu filtram pēc Region_ID pielietošanas. Vienīgās savienojumu secības, kuras izvairās no tieša neparastā savienojuma izpildes starp T2 un T3, ir:(T1. T2. T3)(T1. T3. T2)(T2. T1. T3)(T3. T1. T2)

Jebkāda cita kārtība (piemēram, (T2. T3. T1)), pēc otrās tabulas apstrādes izveidotu šausminošu rindu kombināciju „daudzi pret daudziem”, praktiski T2 un T3 rindu Dekarta reizinājumu. Visas augstākminētās savienojumu secības apstrādā T1 kā pirmo vai otro, pirms tiek uzsākta abu tabulu T2 un T3 apstrāde. Tādējādi, šīs savienojumu secības izpilda tikai divus vienkāršos savienojumus „daudzi pret vienu” starp tabulu T1 un tabulām T2 un T3.

Neparastais divmezglu filtrs neuzvedas kā parasts filtrs, kad tiek sasniegta pirmā no divām filtrējamām tabulām. Taču pēc tam, kad tiek apstrādāta otrā tabula, tas strādā kā parasts filtrs, atmetot kādu daļu no rindām. No šāda redzes viedokļa tāda gadījuma apstrāde ir vienkārša: uzskatīt, ka filtrs neeksistē (vai nav tieši sasniedzams), pirms nav veikts savienojums ar vienu no filtrējamām tabulām. Taču tiklīdz tiks veikts savienojums ar jebkuru divmezglu filtra galu, pretējais mezgls nekavējoties saņems labāko filtrācijas koeficientu un kļūs par labāko izvēli nākošajam pievienojumam.

5.att. parādīts specifisks piemērs ar divmezglu filtru, kurā vienkāršo savienojumu no T1 uz T2 un T3 rindu daļa, kas apmierina nosacījumus, sastāda 0,2. Šajā gadījumā vispirms izvēlas savienojuma secību neatkarīgi no šī filtra eksistences, sekojot tikai pa vienkāršām saitēm. Taču tiklīdz notiks savienojums ar T2 vai T3, pretējās tabulas filtrācijas koeficients (0,1 priekš T2 un 0,5 priekš T3) kļūs vienāds ar izejas koeficientu pareizinātu ar 0,2, kļūstot par pievilcīgu izvēli nākamajiem savienojumiem.

5.att. Divmezglu filtrs ar atklātu divmezglu filtrācijas koeficientu

Ir jāseko parastai procedūrai, lai pielāgotu (iestatītu) diagrammu, kas parādīta 5.att., ignorējot divmezglu filtru starp T2 un T3, līdz nebūs sasniegta viena no šīm tabulām. Vadošā tabula – T1, aiz viņas T4 tabula, pēc T1 tā ir ar vislabāko parasto filtru. Tālāk T3 ir labākais parastais filtrs ar filtrācijas koeficientu 0,5, tāpēc tā tiek novietota kā nākošā savienojumu secībā. Tagad nepieciešams izvēlēties starp T2 un T5, taču priekš T2 ir aktivizēts divmezglu filtrs, jo T3 ir jau apstrādāta, kas tai dod efektīvāku filtrācijas

8

T1

T2 T3

koeficientu (0,2) nekā T5, tāpēc pievienojam T2 kā nākamo. Rezultātā labākā savienojumu secība (T1, T4, T3, T2, T5).

PIEZĪME------------------------------------------------------------------------------------------------Savienojums ar T2 iepriekšējā piemērā ir vienkāršs savienojums, kurš tiek izpildīts ar iegulto ciklu metodi no ārējās atslēgas, kas norāda uz leju no T1, uz indeksu pēc primārās atslēgas T2. Ir jāizvairās no iegultajiem cikliem tabulai, ar kuru ir saistīts divmezglu filtrs. Atgriežoties atpakaļ pie SQL-koda pirms 5.att. var ievērot, ka daudz izdevīgāk ir vērsties pie tabulas Customers ar iegulto ciklu metodi, izpildot savienojumu T1. Customer_ID = T2. Customer_ID, nekā divmezglu filtra nosacījumus T2.Region_ID! = T3. Region_ID.

1.1.4. 4.gadījums. Kompozītsavienojums no divām ārējām atslēgām uz primāro kompozītatslēgu sadalīts divās tabulās

Visbeidzot, 6.att. parādīts ceturtais no galvenajiem ciklisko savienojumu gadījumiem. Šeit ir divi neparasti savienojumi ar T3, un nevienā no tiem netiek izmantota ne šīs tabulas pilna primārā atslēga, ne arī tabulu primārās atslēgas savienojumu pretējos galos. Ja tādi gadījumi, kad neizdodas veikt savienojumu ar pilnu primāro atslēgu kaut vai vienā savienojuma pusē, ir kļūdas, tad 4.gadījums ir gadījums, kad divas kļūdas kompensē viena otru.

6.att. Ciklisks savienojums ar diviem neparastiem savienojumiem

Situācijā, kāda ir parādīta 6.att. SQL parasti izskatās šādi:SELECTFROM …T1, …T2, … T3, …WHERE … T1. FKey1 = T2. PKey2

AND T1. FKey2 = T3. PKeyColumn1AND T2. FKey3 = T3. PKeyColumn2 …

Šāds kods parasti parādās, kad T3 primārā atslēga sastāv no divām daļām, bet sastāvot no divām daļām ārējā atslēga kaut kādā veidā ir sadalīta pa divām tabulām, kur eksistē attiecība starp galveno un detaļu tabulām.

Šis gadījums tiks apskatīts konkrētā piemērā. Apskatīsim datu vārdnīcas tabulas: Tables, Indexes, Table_Columns un Index_Columns. Priekš Table_Columns var izvēlēties primāro atslēgu, sastāvošu no divām daļām, tādu kā (Table_ID. Column_Number), kur Column_Number apzīmē vietu, kādu tabulas kolona pieņem dabīgajā secībā. Vieninieks pirmajam stabiņam, divnieks – otrajam un tā tālāk. Ārējā atslēga tabulai Tables tabulā Indexes sastāv no lauka (kolonas) Table_ID. Tabulai Index_Columns primārā atslēga

9

IC

TC

Ind 0.0002

T1

T2 T3

T1

T2 T3

(Index_ID. Column_Number) arī sastāv no divām daļām. Column_Number vērtība, kas atrodas Index_Columns, ir tāda pati vērtība kā Column_Number, kas atrodas Table_Columns,- vietā, kādu kolona ieņem dabīgajā secībā (bet ne tā vietu indeksā, kurš tiek apzīmēts kā Index_Position). Ja ir zināms indeksa vārds un ir nepieciešams uzzināt vārdu sarakstu kolonām, kuras sastāda indeksu, kārtībā, kurš norādīts Index_Position, tad ir jāuzraksta šādu vaicājumu:SELECT TC.Column_NameFROM Indexes Ind. Index_Columns IC. Table_Columns TCWHERE Ind. Index_Name = 'EMPLOYEES_X1'

AND Ind. Index_ID = IC. Index_IDAND Ind. Table_ID = IC. Table_IDAND IC. Column_Number – TC. Column_Number

ORDER BY IC. Index_ Position ASC

PIEZĪME-----------------------------------------------------------------------------------------------Pirms sākat lasīt tālāk, vingrinājumam ir jāpamēģina patstāvīgi izveidot diagrammu šī vaicājuma skeletam.

Ja filtrācijas koeficients pēc nosacījuma Index_Name ir vienāds ar 0,0002, tad vaicājuma diagramma bez savienojuma koeficientiem izskatās kā parādīts 7.att.

Šeit divas kļūdas (tas nozīmē divi savienojumi, kuru galos nav pilnu primāro atslēgu) kompensē viena otru, ja apskata savienojumus ar TC kopā, jo kopā tās izmanto šīs tabulas pilnu primāro atslēgu.Var transformēt šī retā gadījuma diagrammu kā parādīts 8.att.

7.att. Konkrēts piemērs cikliskā savienojuma ceturtajam gadījumam

8.att. Kompozītsavienojumu no ārējām atslēgām, kuras sadalītas pa divām tabulām, kombinēšana

Ja tiks izpildīts īkšķa likums, kurš liek veikt savienojumu no pilnām primārām atslēgām (vai virzītu uz tām), tad labākā savienojumu secība 7 attēlam kļūst acīmredzama. Ir jāsāk no filtra priekš Ind un jāpāriet pa saitēm uz augšu uz IC. Tikai pēc

10

tam, kad ir saņemtas primārās atslēgas abas daļas priekš TC, var izpildīt savienojumu ar TC. Patiesībā tas ir labākais izpildes plāns šim piemēram. Īkšķa likums šādos gadījumos – sekot pa šīm neparastām saitēm uz primāro kompozītatslēgu pēc tam, kad datu bāze apstrādās visus mezglus augšā, kuri ir nepieciešami pilnas primārās atslēgas izmantošanai.

1.1.5. Kopsavilkums par cikliskiem savienojumiemZemāk dotajā sarakstā tiek vispārīgi apskatītas apstrādes metodikas katram no četriem ciklisko savienojumu tipiem.

1. Divas galvenās tabulas (T2 un T3) ar attiecībām „viens pret vienu” sadala vienu un to pašu detaļu tabulu (T1). Šajā gadījumā ir iespēja noregulēt un palielināt brīvības pakāpju skaitu savienojumu secībā, taču nepieciešams izskatīt savienojumu „viens pret vienu” papildus apstrādes variantus, kas minēti tālāk šajā nodaļā.

2. Galvenajā un detaļu tabulās uzglabājas kopijas ārējai atslēgai, kura norāda uz vienu un to pašu trešās tabulas primāro atslēgu.Šajā gadījumā arī ir iespēja palielināt brīvības pakāpju skaitu savienojumu secībā, taču tā paredz denormalizāciju, kura parasti sevi neattaisno. Ja ir izvēle, labāk atbrīvoties no denormalizācijas, izņemot gadījumus kad priekšrocības, iegūtas šim vai kādam citam vaicājumam, neattaisno denormalizāciju. Šīs grāmatas 10. nodaļā ir apskatīts, kā novērtēt denormalizācijas priekšrocības un trūkumus.

PIEZĪME-----------------------------------------------------------------------------------------------Grāmatā tiek rekomendētas darbības ideālā gadījumā, kas paredz, ka jums ir pilnīga kontrole par pielikumu, datu bāzes dizainu un SQL-kodu. Ir doti arī piemēri kompromisa risinājumiem, kurus var izmantot, ja jums ir tikai ierobežota kontrole. Kad ir redzama neattaisnota denormalizācija jau izveidotā un ekspluatācijā izlaistā datu bāzē, kuru nepārvaldāt un kuru nevarat ietekmēt, tad vislabākais kompromiss ir nedarīt neko.

3. Divmezglu filtrs (neunikāls abos galos) jau savienots ar vienkāršo savienojumu palīdzību.Šajā neparastajā savienojumā ir jāuzskata, ka nekāda filtra nav, kamēr nebūs apstrādāts viens no mezgliem. Pēc tam meklējot savienojumu secības atlikušās daļas ir jāapstrādā otro mezglu, it kā tam būtu bijis labākais filtrācijas koeficients.

4. Kompozītsavienojums no divām ārējām atslēgām uz primāro kompozītatslēgu sadalīts divās tabulās. Ir jāizpilda savienojumu pēc primārās atslēgas tikai tad, kad ir iegūtas abas atslēgas daļas.

Šīs apstrādes metodes ļauj tikt galā ar visiem iespējamiem ciklisko savienojumu gadījumiem.

1.2. Nesaistītas vaicājumu diagrammas

9.att. ir parādīti nesaistītu vaicājumu diagrammu divi gadījumi. Tie ir vaicājumi, kas neapvieno visas tabulas vienā saistītā struktūrā. Katrā no šiem gadījumiem ir redzami divi neatkarīgi vaicājumi; katram no tiem eksistē atsevišķa diagramma, kuru var optimizēt neatkarīgi no otra vaicājuma.

11

T1 T2

Gadījums A Gadījums B

9.att. Nesaistītas vaicājumu diagrammas

Gadījumā A tiek demonstrēts vaicājums, kas sastāv no diviem (kā izskatās neatkarīgiem) vaicājumiem un kur katram ir savienojumi. Gadījumā B tiek demonstrēts nedaudz citāds parasts vaicājums, kuram viena no tabulām (tabula T2) nav saistīta ar savienojuma koku (tas nozīmē, ka nav saistīta ne ar vienu citu tabulu). Abi gadījumi atbilst diviem neatkarīgiem vaicājumiem, kuri izpildās vienā. Kas notiek, kad tiek apvienoti neatkarīgi, nesaistīti vaicājumi vienā vaicājumā? Kad divas tabulas tiek apvienotas vienā vaicājumā bez savienojuma nosacījumiem, datu bāze atgriež atpakaļ Dekarta reizinājumu – visas iespējamās kombinācijas no pirmās tabulas rindām ar otrās tabulas rindām. Nesaistītu vaicājumu diagrammu gadījumā vaicājumu rezultātus, parādītus ar neatkarīgiem vaicājuma skeletiem (vai ar izolētu mezglu), ir jāapskata kā atsevišķu virtuālo tabulu. No šī redzes viedokļa datu bāze atgriezīs visas rindu kombinācijas no diviem neatkarīgiem vaicājumiem.

Saskaroties ar Dekarta reizinājumu, piemēram, ar parādīto 9.att., nepieciešams izpētīt tā rašanās iemeslus. Atrodot iemeslu – ar kuru no nesaistītu vaicājumu četriem gadījumiem uz doto brīdi ir saskare ir iespējams nolemt, kādas darbības ir jāveic:■ Vaicājumā nav savienojuma starp nesaistītām daļām. Šajā gadījumā nepieciešams vienkārši pievienot iztrūkstošo savienojumu. ■ Vaicājums apvieno divus neatkarīgus vaicājumus, kurā katrs atgriež vairākas rindas. Šeit izvairīties no Dekarta reizinājuma parādīšanās var izpildot neatkarīgos vaicājumus katru atsevišķi.■ Viens no neatkarīgiem vaicājumiem atgriež vienu rindu. Ir jāizskata vaicājumu sadalīšanas variantu, lai saglabātu datu bāzes veiktspēju, it īpaši ja otrs neatkarīgais vaicājums atgriež daudz rindu. Vispirms ir jāizpilda vienrindas vaicājumu.■ Abi neatkarīgie vaicājumi atgriež pa vienai rindai. Šajā gadījumā vienkārši ir jāatstāj vaicājumu nesaistītu, ja vien tas neizveido strupceļa situāciju vai to arī nav sarežģīti apstrādāt.

Pirms nesaistīta vaicājuma pārvēršanas divos dažādos vaicājumos, ir jāaplūko, vai izstrādātājs gadījumā nav aizmirsis kādu no savienojumiem. Izstrādes cikla agrīnajās stadijās visizplatītākais nesaistītu vaicājumu diagrammu rašanās iemesls it tāds, ka izstrādātāji vienkārši aizmirst atsevišķus savienojuma operatorus, kuri sasaista atvienotos apakškokus. Šajā gadījumā vienkārši ir jāpievieno neesošo savienojuma nosacījumu, pēc kā vairāk nebūs nesaistīta koka. Ja kādai tabulai kokā ir ārējā atslēga, kura norāda uz otra koka saknes mezgla primāro atslēgu, tad praktiski tieši šis savienojums bija aizmirsts neuzmanības dēļ.

T1 T2

12

Ja katrs no neatkarīgajiem vaicājumiem atgriež vairākas rindas, tad kombināciju skaits pārsniegs rindu skaitu, kuras tiktu iegūtas izpildot divus vaicājumus neatkarīgi. Taču divu rezultātu kombināciju sakopojums nesatur vairāk informācijas, kā būtu iegūts pie dalītas vaicājumu izpildes, tāpēc darbs pie lieku datu veidošanas ir tikai nevajadzīgs laika patēriņš, vismaz no negatavu datu saņemšanas viedokļa. Tāpēc varbūt labāk izpildīt divus vaicājumus atsevišķi.

Reizēm ir iemesli, kuri kaut kādā veidā attaisno Dekarta reizinājuma kombināciju izveidošanu programmēšanas ērtības dēļ. Taču vienmēr ir apvedceļi, kas ļauj izvairīties no liekiem datiem, ja to vērtība nav attaisnojama.PIEZĪME------------------------------------------------------------------------------------------------Ja uztrauktos tikai par fizisko ievadu – izvadu, tad Dekarta reizinājums būtu pieļaujams, tā kā liekā datu nolasīšana no atkārtota vaicājuma praktiski vienmēr ir pilnīgi kešēta pēc pirmās nolasīšanas. Patiesībā atsevišķi izstrādātāji pat aizstāv šādus ilgi izpildāmus vaicājuma piemērus, attaisnojot tos ar fiziskā ievada – izvada lētumu. Šādi vaicājumi ir lielisks veids kā noslogot procesoru un izveidot milzīgu loģiskā ievada – izvada operāciju skaitu, ja tas ir vajadzīgs – piemēram, slodzes izmēģinājumiem vai citiem laboratoriskiem pētījumiem, taču tiem nav vietas biznesa pielietojumos.

Ja viens no neatkarīgajiem vaicājumiem garantēti atgriež vienīgo rindu, tad Dekarta reizinājums būs vismaz drošs un garantēti atgriezīs ne vairāk rindu, kā otrais neatkarīgais vaicājums. Pie vaicājumu kombinēšanas potenciāli eksistē arī nelielas darba izmaksas, saņemot datus pa tīkla savienojumu ar serveri, jo kombinētā vaicājuma izvēles saraksts var atgriezt datus no neliela vaicājuma vairākas reizes pa vienam katrai rindai, kura tiek atgriezta lielam vaicājumam. Bet tas prasa lielāka baitu daudzuma pārsūtīšanu, nekā izmantojot sadalītos vaicājumus. Šis caurlaides spējas izlietojums noteiktā veidā tiek pretstatīts tīkla gaidīšanas laika ekonomijai. Kombinētais vaicājums ietaupa atkārtotu vēršanos pie datu bāzes pa tīklu, tāpēc izvēle ir atkarīga no vaicājuma detaļām. Ja netiks sadalīti vaicājumi, tad optimālais plāns ir vienkāršs. Vispirms ir jāizpilda optimālais plāns vaicājumam, kurš atgriež vienu rindu. Pēc tam ar ielikto ciklu, kurš izpildās tikai vienu reizi, jāizpilda optimālais plāns vaicājumam, kurš atgriež vairākas rindas. Šis kombinētais izpildes plāns maksā tik pat daudz, cik neatkarīgu divu vaicājumu izpilde. Ja tā vietā kā pirmo izpildīs plānu vaicājumam, kurš atgriež vairākas rindas, tad plāns ar ieliktiem cikliem prasīs atkārtotu plāna izpildi vaicājumam, kurš atgriež vienu rindu, - pa vienai reizei katrai rindai, atgrieztai ar citu vaicājumu.

Vaicājuma, kurš atgriež vienu rindu, kombinēšana ar vaicājumiem, kuri atgriež vairākas rindas, reizēm ir gan ērta, gan attaisnota. Eksistē speciāls gadījums, kas atbilst 9.att. labajai pusei, kad vaicājums, kurš atgriež vienu rindu – ir tikai vienas rindas nolasīšana no izolētas tabulas T2, kurai vispār nav savienojumu. Dekarta reizinājums reizēm ir lietderīgs lai izvēlētos parametrus, kas glabājas vienrindas parametru tabulā. It īpaši, ja šie dati tiek pieminēti tikai sadaļā WHERE, bet ne sarakstā SELECT. Ja vaicājums neatgriež datus no parametru tabulas, tad lētāk izpildīt pareizi sakombinētu vaicājumu, nekā atsevišķus vaicājumus.

Vēl retāks gadījums garantē, ka abi izolētie vaicājumi atgriež pa vienai rindai. Šajā gadījumā, kad nepastāv nekādas briesmas, kādas ir pārējos gadījumos, vaicājumu kombinēšana būs absolūti droša no veiktspējas puses. Taču no programmēšanas un programmatūras uzturēšanas puses šādu vaicājumu kombinēšana var būt pārāk komplicēta, bet ekonomija būs neliela.

13

1.3. Vaicājumu diagrammas ar vairākiem sakņu mezgliem

10.att. parādīts vaicājuma diagrammas piemērs, kas apgāž pieņēmumu par viena sakņu mezgla eksistēšanu vaicājuma kokam. Šis gadījums ir radniecīgs iepriekšējam gadījumam (nesaistītas vaicājumu diagrammas). Šeit katrai tabulas Master rindai, kas apmierina vaicājuma nosacījumu, vaicājums atgriezīs visas attiecīgo detaļu rindu kombinācijas no Root1 un Root2. Ar dotajiem savienojuma detaļu koeficientiem var sagaidīt, ka visas 5 detaļu rindu no Root1 un 30 rindu no tabulas Root2 kombinācijas dos 150 kombinētu rindu katrai atbilstošai rindai no Master. Šīs 150 rindas satur ne vairāk izejas datu, kā 5 rindas no Root1 un 30 rindas no Root2 kopā ņemot, tāpēc ātrāk būs nolasīt 5 un 30 rindas atsevišķi, izvairoties no Dekarta reizinājuma. Tad, kad nesaistītas vaicājuma diagrammas ģenerē vienu lielu Dekarta reizinājumu, vairāki sakņu mezgli noved pie veselas virknes nelielu Dekarta reizinājumu rašanās, pa vienam katrai atbilstošai galvenajai rindai.

10.att. Vaicājuma diagramma ar vairākām saknēm

Ir četri iespējamie gadījumi, kad parādās vaicājuma diagrammas ar vairākām saknēm. Zemāk minētajā sarakstā ir uzskaitīti šie gadījumi un aprakstīti piemērotākie risinājumi.

1. Iztrūkstošais nosacījums. Šajā vaicājumā iztrūkst nosacījums, kurš pārveidotu vienu no mezgla detaļu tabulām par galveno tabulu, pārvēršot savienojumu „viens pret daudziem” par „viens pret vienu”. Risinājums: pievienot iztrūkstošo savienojuma nosacījumu.

2. Dekarta reizinājums „daudzi pret daudziem”. Šāds vaicājums ir Dekarta reizinājums „daudzi pret daudziem” katrai galvenajai rindai, kas rodas starp detaļu tabulām, kuras attiecas uz vienu galveno tabulu. Šis gadījums slēpjas zem maskas par pārsniegtajiem 1,0 detaļu filtrācijas koeficientiem no vienas galvenās tabulas pret divām dažādām sakņu detaļu tabulām.Risinājums: atbrīvoties no Dekarta reizinājuma, sadalot vaicājumu uz neatkarīgajiem vaicājumiem, kuri nolasa divas sakņu detaļu tabulas atsevišķi.

3. Detaļu savienojuma koeficients mazāks par 1,0. Šajā gadījumā viena no sakņu detaļu tabulām savienojas ar kopējo galveno tabulu ar detaļu savienojuma koeficientu mazāku par 1,0.Risinājums: kaut arī šis gadījums nerada problēmas veiktspējai, ir jāapskata variantu par vaicājuma daļu sadalīšanu vai par vienas no vaicājuma daļas pārvēršanu apakšvaicājumā funkcionālu iemeslu dēļ.

14

4. Tabula tiek izmantota tikai lai pārbaudītu kaut kādas būtības eksistēšanu. Viena no sakņu detaļu tabulām nepiegādā nekādus datus, nepieciešamus sarakstā SELECT, un ir iekļauta tikai eksistences pārbaudei.Risinājums: pārvērst eksistences pārbaudi par neslēptu apakšvaicājumu.

1.3.1. 1.gadījums. Iztrūkstošais savienojuma nosacījumsVisbiežāk otra sakņu mezgla klātbūtne norāda uz kādu iztrūkstošu savienojuma nosacījumu, kurš pārvērstu vienu no sakņu mezgliem par galveno mezglu. 11.att. parādīts šis pārveidojums, kad savienojums no Master uz Root1 pārvēršas par savienojumu „viens pret vienu”, pievienojot kādu papildus nosacījumu priekš Root1 (pārdēvētu par R1), kurš garantē, ka datu bāze atradīs katrai rindai no Master maksimums vienu rindu no R1. Tas it īpaši ir iespējams, kad R1 glabājas kādi detalizēti dati, atkarīgi no laika intervāliem (piemēram, dažādas nodokļu likmes), kas atbilst galvenajam ierakstam (piemēram, nodokļu būtībai), bet pievienojot nosacījumu par datumu (piemēram, vaicājums par tekošo nodokļa likmi) pārvērš savienojumu par „viens pret vienu”.

11. Vaicājuma ar vairākiem sakņu mezgliem izlabošana

Bieži vien nosacījums, kas pārvērš savienojumu par „viens pret vienu”, jau ir, un var redzēt, ka savienojuma „daudzi pret daudziem” kombinācija ar mānīgo filtru vienkārši atceļ detaļu filtrācijas koeficientu.

PIEZĪME-----------------------------------------------------------------------------------------------Šajā piemērā filtrācijas koeficients šādam filtram bija 0,2, bet detaļu savienojuma koeficients ar Root1 – 5.

Citādi nosacījums, kurš pārvērš savienojumu par „viens pret vienu”, var vienkārši vaicājumā iztrūkt, it īpaši, ja izstrāde tika veikta testa sistēmā, kur attiecība „viens pret daudziem” bija noslēpta.

15

PIEZĪME-----------------------------------------------------------------------------------------------Tas ilustrē iepriekšējo piemēru par dažādām nodokļu likmēm. Izstrādes vidē var būt ieraksti tikai par tekošo likmi, noslēpjot kļūdu pie nosacījuma par datumu pazaudēšanu likmju tabulā.

Ir vai nu pazaudēts nosacījums, kurš pārvērš savienojumu par „viens pret vienu”, vai vienkārši nav acīmredzams, ka tas ir saistīts ar savienojumu, tāpēc ir nepieciešams ieslēgt šo nosacījumu un atpazīt to kā savienojuma daļu, bet ne kā neatkarīgu filtrācijas nosacījumu. Tāds iztrūkstošs savienojuma nosacījums ir īpaši iespējams tad, kad tiek atklāts, ka ārējā atslēga vienai no sakņu tabulām, kas norāda uz leju uz kopējo galveno tabulu, arī ir šīs sakņu tabulas primārās kompozītatslēgas daļa.

1.3.2. 2.gadījums. Dekarta reizinājuma sadalīšana vairākos vaicājumos12.att. parādīts cits risinājums uzdevumam ar vaicājuma diagrammu ar vairākiem sakņu mezgliem. Šis risinājums radniecīgs atsevišķu vaicājumu atklātai izpildei uz nesaistītas vaicājuma diagrammas. Tas paredz sadalīt Dekarta reizinājumu un nomainīt to ar divām atsevišķām kopām. Šajā piemērā mēs nomainām vaicājumu, kurš atgrieztu pa 150 rindām katrai rindai no Master, ar diviem vaicājumiem, kuri kopā atgriezīs pa 35 rindām katrai rindai no Master. Ja ir redzama galvenās tabulas attiecība „viens pret daudziem” ar divām dažādām sakņu detaļu tabulām, tad var iegūt tieši tos pašus datus, nolasot ievērojami mazāk rindu ar atsevišķiem vaicājumiem, kā parādīts attēlā. Tā kā rezultāti pieņems nedaudz citu formu, vajadzēs izmanīt pielikuma loģiku, lai apstrādātu datus jaunā formā.

12. att. Dekarta reizinājuma izlabošana uz atsevišķu vaicājuma rēķina

1.3.3. 3.gadījums. Attiecība ar sakņu detaļu tabulām ne vairāk kā „viens pret vienu”

13.att. parādīts gadījums diagrammai ar vairākām saknēm, kad izejas vaicājuma veiktspēja nesastāda problēmu. Tā kā detaļu savienojuma koeficients Master ar Root1 vienāds ar 0,5, Dekarta reizinājums nenoved pie strauja rindu skaita pieauguma Dekarta reizinājumā, kad tiek kombinēti piemērotie ieraksti no Root1 un Root2 vidējam piemērotam ierakstam no Master. Var uzskatīt savienojumu ar Root1 par savienojumu uz leju un pat dot tam priekšroku, it kā tas 0,5 reizes uzlabotu filtrēšanas savienojuma

16

filtrācijas koeficientu, sekojot 6.nodaļas noteikumiem speciālajiem gadījumiem (šinī gadījumā detaļu filtrācijas koeficientiem, mazākiem par 1,0).

13.att. Dekarta reizinājums ar nelielu detaļu savienojuma koeficientu

Kaut arī šis vaicājums nesastāda problēmu iestatīšanai, tas tomēr var būt nepareizs. Savienojums „viens pret nulli” vai „viens pret daudziem” no Master uz Root1, acīmredzami parasti pārvēršas par „viens pret nulli” vai „viens pret vienu”, nodrošinot drošu Dekarta reizinājumu. Bet tā kā savienojums retos gadījumos tomēr var pārvērsties par „viens pret daudziem”, ir jāņem vērā, ka rezultāts var atgriezt Dekarta reizinājumu ar atkārtojumu dotajai rindai no Root2. Tā kā šāds gadījums ir reti iespējams, visvairāk iespējams, ka vaicājums patiesība tika izstrādāts un testēts, lai atgrieztu rezultātus, viennozīmīgi atspoguļotiem uz rindām no Root2 (viens pret vienu), bet pielikums visos pārējos, retos gadījumos var vispār nestrādāt.UZMANĪBU-------------------------------------------------------------------------------------------Jo mazāka varbūtība ir situācijai „viens pret daudziem”, jo lielāka varbūtība, ka šis gadījums ir izlaists pielikuma dizainā.

Piemēram, ja pielikums izmainīs datus Root2 pēc to nolasīšanas no tabulas ar šo vaicājumu un mēģinās nosūtīt izmaiņas atpakaļ uz datu bāzi, tad tam vajadzēs risināt, kādu atkārtojamās Root2 rindas kopiju ir jānosūta. Vai pielikumam ir jābrīdina gala lietotājs, ka ir noticis mēģinājums nosūtīt pretrunīgas kopijas? Ja pielikums savāc datus Root2 ar vaicājuma palīdzību, vai tas izvairās no datu papildināšanas no atkārtojamām Root2 rindām?

1.3.4. 4.gadījums. Eksistences pārbaudes pārvēršana par neslēptu apakšvaicājumu

Viens no 13 att. funkcionālā uzdevuma risinājumiem jau parādīts 12.att. Viens vaicājums vienkārši tika sadalīts divos apakšvaicājumos. Cits risinājums, kurš bieži vien ir labāks, ļauj izolēt zaru apakšvaicājumā ar nosacījumu EXISTS. Šis risinājums strādā sevišķi labi, ja izejošais vaicājums neizvēlas stabiņus no Root1 (vai no jebkādām tabulām, kas pievienotas zemāk ar slēptām pelēkām saitēm 13.attēlā). Šajā samērā bieži sastopamā specifiskā gadījumā patiesībā interesē tikai tas, vai eksistē piemērota rinda tabulā Root1 un vai tā apmierina kādiem filtrēšanas nosacījumiem, bet ne šīs rindas saturs vai rindu sakrišanas skaits, ja tādi ir. Vēlāk šajā nodaļā ir iespējams uzzināt, kā veidot diagrammas un regulēt vaicājumus ar līdzīgiem apakšvaicājumiem.

17

2T1 T25

1.4. Savienojums bez primārām atslēgām

Tiek izmantotas saites bez bultiņām, lai apzīmētu savienojumus, kuriem abās pusēs nav izmantotas primārās atslēgas. Kopumā tie ir neparasti savienojumi „daudzi pret daudziem”, kaut gan atsevišķos gadījumos tie pārvēršas par „daudzi pret nulli” vai „daudzi pret vienu”. Ja tie nekad nav kā „daudzi pret daudziem”, tad vienkārši nav ievēroti unikalitātes nosacījumi un ir nepieciešams pievienot bultiņu pie savienojuma unikālā gala. Ja kaut vai kādreiz šie savienojumi mēdz būt kā „daudzi pret daudziem”, tad parādās arī tās pašas problēmas (un tātad arī tie paši risinājumi), kā vaicājumu diagrammām ar vairākiem sakņu mezgliem. 14.att. parādīts savienojums „daudzi pret daudziem” starp T1 un T2, kur detaļu savienojuma koeficients abos galos ir lielāks par 1,0. Galvenie savienojuma koeficienti ir tikai saites unikālajā galā, kas apzīmēts ar bultiņu, tāpēc šai saitei ir divi detaļu savienojuma koeficienti.

14.att. Savienojums „daudzi pret daudziem”

Šis gadījums sastopams daudz biežāk, nekā iepriekšējie neparasto savienojumu diagrammu piemēri. Kaut gan tajā ir tie paši iespējamie problēmu (un risinājuma) avoti, kā vairāku sakņu mezglu gadījumā, lielākais vairums savienojumu „daudzi pret daudziem” parādās vienkārši tāpēc, ka nav savienojuma nosacījumu. Ir jāuzsāk ar pārbaudi, apskatot, vai nevajadzētu filtrācijas nosacījumus vaicājumā uzskatīt par savienojuma daļu, tāpēc, ka tie nobeidz pilnas primārās atslēgas specifikāciju vienai savienojuma pusei. Piemērs 5.2. nodaļā 5 – tas ir tāds gadījums, kurā nosacījums OT.Code_Type = 'ORDER_STATUS' ir vajadzīgs lai pabeigtu unikālu savienojumu ar pseidonīmu OT. Ja šo nosacījumu apskatītu kā parastu filtrēšanas nosacījumu pseidonīmam OT, tad savienojums ar OT pārvērstos savienojumā „daudzi pret daudziem”. Pat ja netiek atrasta iztrūkstošā savienojuma daļa starp vaicājuma filtrēšanas nosacījumiem, vienmēr vajag domāt, ka tā kļūdas pēc nebija norādīta vaicājumā.

Šāds gadījums, kad iztrūkst savienojuma nosacījums, īpaši bieži sastopams tad, kad datu bāzes dizains atļauj eksistēt vairākiem būtības tipiem vai skaldīšanai tabulas robežās, bet izstrādātājs aizmirst ierobežot skaldīšanu vai tipu vaicājumā. Piemēram, iepriekšējā piemērā ar tabulu Code_Translations katram Code_Type eksistēja dažādi pārveidošanas būtības tipi (translation), un ja nosacījums priekš Code_Type nebūtu norādīts, tad savienojums ar Code_Translations pārvēstos savienojumā „daudzi pret daudziem”. Bieži vien testēšana neatļauj atklāt šo kļūdu agrīnā stadijā, jo, ja datu bāze pat pieļauj dažādus tipus vai skaldīšanu, tad testa vidē var būt tikai viens tips vai skaldīšana, bet izstrādātāji var pieņemt šādu lietu kārtību, ka tā tam jābūt. Pat tad, ja reālos datos eksistē dažādi tipi vai skaldīšanas, tad cita, selektīvākā atslēgas daļa pati par sevi parasti var būt unikāla. Tā vienlaicīgi var būt gan veiksme, gan problēma. Kaut gan lielākās nepatikšanas sakarā ar savienojuma nosacījuma iztrūkumu tiek novērstas, problēmu kļūst

18

1T1 T20.7

grūtāk atpazīt un izlabot, un tas noved pie maldīgas sajūtas, ka pielikums ir pareizs. Iztrūkstošā savienojuma nosacījuma meklēšana un izlabošana var tikai mazliet uzlabot veiktspēju, padarot savienojumu selektīvāku, bet var kļūt arī par milzīgu atbalstu, ja tiek izlabota fatāla slēptā kļūda.

Pēc analoģijas, ar vaicājumu diagrammām ar vairākiem sakņu mezgliem, risinājumi savienojumiem „daudzi pret daudziem” atbilst dažādu diagrammu ar vairākiem sakņu mezgliem risinājumiem.

1.5. Savienojums „viens pret vienu”

Eksistē joks par vecīti, kurš žēlojies, ka bērnībām viņam nācies iet uz skolu pa pieciem kilometriem kāpjot kalnā turp un atpakaļ. Kaut kādā nozīmē savienojumi „viens pret vienu” apgriež šo bildi kājām gaisā. Pēc heiristikas likuma, kas pasaka, kādu tabulu pievienot kā nākošo, savienojums „viens pret vienu” izrādās „no kalna lejā” uz abām pusēm. Kā tādi, šie savienojumi nerada nekādas problēmas iestatīšanai, un tie sagādā vismazāk rūpju no visām neparastajām situācijām, kādas iespējamas vaicājumu diagrammās. Taču šādi savienojumi reizēm norāda uz iespējām uzlabot datu bāzes dizainu, ja uz doto brīdi ir tāda izstrādes stadija, kad dizains vēl nav nofiksēts. Taču ir lietderīgi zināt standarta paņēmienu, kā atspoguļot savienojumu „viens pret vienu” uz vaicājumu diagrammas, tāpēc tiks aprakstīti dažādi paņēmieni.

1.5.1. Savienojums „viens pret vienu” ar tabulu - apakškopu15.att. parādīts tipisks savienojums „viens pret vienu”, iebūvēts lielā vaicājumā. Tai pat laikā kad savienojumam „daudzi pret daudziem” abos galos ir detaļu savienojuma koeficienti, savienojumam „viens pret vienu” tie ir galvenie savienojuma koeficienti. Šajā piemērā galvenie savienojuma koeficienti parāda, ka savienojums starp T1 un T2 patiesībā mēdz būt tikai „viens pret nulli” vai „viens pret vienu”; gadījums „viens pret nulli” rodas tikai 30% rindu no T1.

15.att. Tipisks savienojums „viens pret vienu”

Tā kā tas ir iekšējais savienojums, tad savienojuma „viens pret vienu” gadījumi starp T1 un T2 ir savienojuma slēptais filtrs, kurš ir jāapstrādā tā, kā aprakstīts 6.nodaļas beigās. Ir jāpievērš uzmanību arī tam, ka tas var būt slēpta cikliska savienojuma gadījums, kad galvenā tabula viennozīmīgi („viens pret vienu”) savienojas ar citu tabulu. Ja virs T1 ir detaļu tabula, kas ir domājama ar pelēkā krāsā iekrāsotu saiti uz augšu, un ja šī detaļu tabula savienojas ar T1 pa to pašu unikālo atslēgu, kā ar T2, tad pēc transivitātes likuma ir domāts savienojums no detaļu tabulas uz T2. 16.att. domājamā saite parādīta pelēkā krāsā. Par to, kā ir jāapstrādā cikliskie savienojumi, tika stāstīts nedaudz agrāk šajā nodaļā.

19

T1 T21 0.7

D

1T1 T21

16.att. Domājamā saite, kas rada ciklisku savienojumu

Vai ir ciklisks savienojums vai nav, vienmēr var uzlabot datu bāzes dizainu. Ar gadījumu 16.att. tiek domāta būtību kopa, kuras viennozīmīgi attēlojas uz T1, un to pašu būtību apakškopa, kuras viennozīmīgi attēlojas uz T2, turklāt tabula T2 ir būvēta no primārās atslēgas T1 un stabiņiem, kuri tiek izmantoti tikai šai apakškopai. Šajā gadījumā nav nekādas stingras nepieciešamības pēc divām tabulām. Ir jāpamēģina vienkārši pielikt papildus stabiņus pie T1 un piešķirt tiem vērtību null priekš lielās kopas locekļiem, kuri neieiet apakškopā. Reizēm ir arī citi iemesli, kādēļ izstrādātājs ērtības labad līdzīgās situācijās izvēlas divas tabulas. Taču skatoties no iestatīšanas redzes viedokļa šo samērīgo tabulu kombinēšana praktiski vienmēr ir lietderīga, tāpēc ir jāpadomā kaut vai par to izmantošanu, ja ir iespēja iespaidot datu bāzes dizainu.

1.5.2. Precīzie savienojumi „viens pret vienu”17. att. Ir parādīts gadījums, kas prasa obligātu divu tabulu savienošanu vienā, kad tas ir iespējams. Šeit filtrācijas galvenie koeficienti ir precīzi 1,0, un starp tabulām eksistē precīza attiecība „viens pret vienu”. Šādā veidā abas tabulas attēlojas uz vienu un to pašu būtību kopu, un savienojums ir tikai nevajadzīgas izmaksas salīdzinājumā ar kombinēto tabulu izmantošanu.

17. att. Precīzs savienojums „viens pret vienu”

Vienīgā situācija, kad no veiktspējas redzes viedokļa ir nepieciešams sadalīt šī tabulas ir gadījumā, kad vaicājumiem praktiski vienmēr nepieciešami dati tikai no vienas tabulas, un reti nepieciešams veidot savienojumu. Visizplatītākais šāda gadījuma piemērs - dati no vienas tabulas tiek pieprasīti ievērojami retāk nekā no otras. Šajā gadījumā, it īpaši, ja katra rinda reti pieprasīto datu aizņem daudz vietas, var atklāt, ka bieži aptaujājamās tabulas kompaktums, kas palielina koeficientu par veiksmīgu nokļūšanu kešā, tikai tik-tikko attaisnos reti izpildāmā savienojuma izmaksas. Pat no funkcionalitātes vai izstrādes viedokļa, domājams, ka izmaksas par rindu papildināšanas un anulēšanas kodēšanu vienlaicīgi abām tabulām, un reizēm, par abu tabulu atjaunošanu, būs lielas. Iespējams,

20

1T1 T20.01

ka izvēle būs uzturēt vienu kombinētu tabulu. Parasti, ja jūs redzat precīzu savienojumu „viens pret vienu”, tas ir radies kādas stingras funkcionalitātes rezultātā, kura pieprasa jaunus stabiņus jau esošām būtībām, un kādus iedomājamus vai reālus izstrādes ierobežojumus, kuri neļauj izmainīt izejas tabulu. Kad iespējams, labāk ir atrisināt problēmu novācot šos ierobežojumus.

1.5.3. Savienojums „viens pret vienu” ar ievērojamāki mazāku datu kopuOtrajā spektra galā atrodas gadījums, parādīts 18.att. – savienojums „viens pret nulli” vai „viens pret vienu”, kurš praktiski vienmēr strādā kā „viens pret nulli”. Šis gadījums ideāli attaisno tabulu sadalīšanu. Būtību niecīgai apakškopai, kas dota tabulā T2, var eksistēt citas optimizācijas prasības, atšķirīgas no prasībām pret paplašināto kopu, kas dota tabulā T1. Iespējams, ka T1 parasti tiek aptaujāta bez savienojuma ar T2, un šajā gadījumā nevajadzīgo stabiņu T2 izslēgšana un tikai to indeksu uzturēšana, kuriem ir jēga kopējām būtībām, ir lietderīga. Šeit slēptais savienojuma filtrs, pārstāvēts ar zemu savienojuma galveno koeficientu savienojuma T2 pusē, teicami strādā. Tas ir tik labs, ka var pat sākt vaicājuma izpildi no nefiltrētas pilnas tabulas T2 skanēšanas un tomēr atrast vislabāko ceļu pie pārējiem datiem. Ja tiks apvienotas šīs tabulas vienā, tad panākt šādu izpildes plānu būs grūti, ja nu vienīgi uz indeksu izveidošanas rēķina, kuri visiem pārējiem gadījumiem ir lieki.

18. Savienojums „viens pret nulli” vai „viens pret daudziem” starp stipri atšķirīgām tabulām (pēc izmēriem)

Šeit galvenais uzdevums – neaizmirst ievērot slēpto savienojuma filtru no T1 uz T2, vai nu sākot vaicājumu no T2, vai arī apstrādājot to pēc iespējas ātrāk tā, lai pēc iespējas ātrāk izmantotu slēpto filtru.

1.5.4. Savienojumi „viens pret vienu” ar slēpto savienojuma filtru abos virzienos

19.att. parādīts rets savienojuma veids „(nulle vai viens) pret (nulli vai vienu)”, kurš filtrējas abos virzienos. Ja savienojums „viens pret vienu” – ir kustība no kalna lejup abos virzienos, tad šie savienojumi – stāva nokāpšana no kalna abos virzienos. Ja tikai dati nav bojāti (piemēram, vienā no tabulām nav kaut kādu datu), tad šis retais gadījums iespējams paredz, ka eksistē vai vajag eksistēt arī vēl kādai trešajai tabulai, kas dod šo pārklājkopu paplašinātu kopu. Ja tiks atrasta vai izveidota šāda tabula, tad tie paši argumenti, kas bija iepriekš, runās par labu tās kombinēšanai ar vienu vai abām apakškopas tabulām.

21

0.7T1 T20.9

0.7T1 T20.9

19.att. Savienojums „(nulle vai viens) pret (nulli vai vienu)”

1.5.5. Vienošanās par savienojumu „viens pret vienu” attēlošanuIr lietderīgi, ja pastāv noteikta vienošanās par vaicājumu diagrammas vienotu attēlošanu. Šādas vienošanās palīdz attīstīt intuīciju, vienveidīgi parādot atslēginformāciju. Vienvirziena bultiņas vienmēr norāda uz leju.20.att. parādīti divi alternatīvi varianti, labi piemēroti savienojumiem „viens pret vienu”, kuri atrodas zem sakņu detaļu tabulas. Pirmajā variantā īpaši uzsvērta divpusēja bultiņa, kurai galos mezgli izvietoti vienā līmenī. Otrajā variantā uzsvērts parastais norādes virziens – uz leju no sakņu detaļu tabulas. Jebkurš no variantiem ir labs, ja atceras, ka savienojums „viens pret vienu” kaut kādā veidā no abām pusēm norāda uz leju.

20.att. Diagrammas attēlojums savienojumiem „viens pret vienu”, kuri atrodas zem sakņu detaļu tabulas

Šim gadījumam, kad abas tabulas, kas piedalās savienojumā, atrodas zem saknes, ir jāatceras, ka, ja vienlīdzīgas tabulas izmanto kopēju primāro atslēgu, tad saite no augšas no T1 pēc transivitātes likuma tieši tāpat var attiekties arī uz T2, ja tikai tā neved pie kādas alternatīvas unikālas atslēgas pēc T1, kura T2 netiek izmantota. Šis slēptais cikliska savienojuma gadījums ir parādīts 2.att. variantā B.

21.att. parādītas alternatīvas savienojumu diagrammas „viens pret vienu” divām sakņu detaļu tabulām (šādas tabulas atrodas augšā, un ar tām nav savienojumu), kad kaut vai viens savienojuma virziens raksturojas ar galveno savienojuma koeficientu, mazāku par 1,0. Un atkal var uzsvērt savienojuma raksturu vai nu ar horizontālu izvietojumu, vai norādīt, kāda no tabulām ir lielāka (un kurš no savienojuma virzieniem ir „stāvāks no kalna”), novietojot mezglu ar lielāku galveno savienojuma koeficientu augstāk. Mezgls ar lielāku galveno savienojuma koeficientu attēlojas kā tabula, kuras lielākā daļa rindu piedalās šajā savienojumā „(nulle vai viens) pret (nulli vai vienu)”.

22

0.7T1 T20.9

21.att. Alternatīvi diagrammas attēlošanas paņēmieni sakņu detaļu tabulām ar attiecību „(nulle vai viens) pret (nulli vai vienu)”

22. attēls ilustrē gadījumu, līdzīgu ar 21.att., bet ar mezgliem ar precīzu attiecību „viens pret vienu”, kas nozīmē tabulas, kuras vienmēr savienojas veiksmīgi. Un atkal jūs varat uzsvērt savienojuma virzienu ekvivalentumu, izvietojot mezglus blakus pa horizontāli. Vai arī ir jāizvēlas virzienu, kas ļaus attēlot koku vairāk sabalansētu, lai tas labāk novietotos uz lapas, novietojot mezglu ar garākiem zariem augstāk. Šajā gadījumā izvēlei ir maza nozīme, ja atceras, ka abi virzieni ved „no kalna”, neatkarīgi no tā, kā izvietoti uz diagrammas.

22.att. Sakņu detaļu tabulu ar precīzu attiecību „viens pret vienu” alternatīvi diagrammas

attēlošanas paņēmieni

1.6. Ārējie savienojumi

Praktiski vienmēr ārējā savienojuma jēga un uzdevums ir novērst vajadzīgas informācijas zudumus no tabulas, kas atrodas savienojuma sākumā, neatkarīgi no ārpusē pievienojamās tabulas satura. Neparasti ārējie savienojumi, kuri tiks aprakstīti nākošajās nodaļās, paredz zināmas pretrunas pašam ārējo savienojumu izmantošanas iemeslam.

1.6.1. Filtrētie ārējie savienojumiApskatīsim 23.att., kur ārējais savienojums notiek ar tabulu filtrēšanas nosacījumu. Ārējā gadījumā, t.i. gadījumā, kad T1 rindai nav atbilstošas rindas no T2, datu bāze rezultātu rindā katram T2 stabiņam nozīmē vērtību null. Tādā veidā, izņemot T2.Kāds_stabiņš IS NULL, praktiski jebkāds filtrēšanas nosacījums priekš T2 noved pie rezultātu rindas izslēgšanas, kura veidojas ārējā savienojuma ārējā gadījumā.

23

T1

T2 0.5

23.att. Ārējais savienojums ar filtrētu mezglu

Pat tādiem nosacījumiem, kā T2.Unpaid_Flag ! = 'Y' vai NOT T2. Unpaid_Flag = 'Y', kuriem, kā jūs sagaidiet, ir jābūt patiesiem ārējā gadījumā, īstenībā nemaz nav patiesi.

UZMANĪBU-------------------------------------------------------------------------------------------Kad lieta nonāk līdz nosacījumiem sadaļā WHERE, datu bāzes interpretē vērtību null neintuitīvā veidā. Ja tiek uzskatīts, ka null attiecībā pret tabulas stabiņu nozīmē „nav zināms”, bet ne „nav piemērots”, tad iespējams var noprast, kā datu bāzes apstrādā vērtību null nosacījumos. Bez jautājumiem par to, vai vērtība stabiņā ir null, praktiski jebkurš jautājums, kuru var uzdot par nezināmo vērtību, dos atbildi „nav zināms”, kas patiesībā arī ir īstenā vērtība vairums nosacījumiem pa null. No viedokļa par rindu atmešanu vaicājumā, datu bāze apstrādā īsteno vērtību „nav zināms” kā FALSE, atmetot rindas ar nezināmām īstenām vērtībām frāzē WHERE. Un kaut gan NOT FALSE = TRUE, jūs atklāsiet, ka NOT „nav zināms” = „nav zināms”!

Tā kā vairums filtru ārējai tabulai atmet ārējo savienojumu ārējos gadījumus, un ārējo savienojumu uzdevums ir tieši šo gadījumu saglabāšana, ir jāpievērš sevišķa uzmanība uz jebkādiem filtriem priekš ārējām tabulām. Eksistē vairāki scenāriji, un ir jāpatērē pietiekami daudz laika, lai noteiktu, kāds ir pielietojams konkrētam gadījumam.■ Filtrs pietiekoši rets, piemēram, Kāds_stabiņš IS NULL, un var atgriezt vērtību TRUE laukiem, vienādiem ar NULL, piespiedu kārtā ievietotiem ārējā gadījumā, un tāpēc filtrs ir funkcionāli pareizs.■ Izstrādātājs nav plānojis atmest ārējo savienojumu, un filtrējošo nosacījumu ir jānovāc.■ Filtrējošais nosacījums ir paredzēts lai atmestu ārējo savienojumu, un savienojums ar tādiem pašiem panākumiem var būt arī iekšējais. Šajā gadījumā nav nekādas funkcionālas atšķirības starp vaicājumu ar savienojumu, kas izteikts kā ārējais vai iekšējais savienojums. Tomēr, pataisot to par formālu iekšējo savienojumu, datu bāzei tiks iedots vairāk brīvības pakāpju, lai veidotu izpildes plānus, kuri var veikt savienojumu jebkurā virzienā. Kad labākais filtrs tiek atrasts tajā pašā savienojuma pusē, kurā ir arī iepriekš ārēji pievienojamā tabula, papildus brīvības pakāpes var ļaut izvēlēties labāku izpildes plānu. No otras puses, savienojuma pārveidošana par iekšējo var piespiest optimizatoru izdarīt kļūdu, no kādas tas būtu izvairījies ar ārējo savienojumu. Ārējie savienojumi – tas ir viens no veidiem ierobežot savienojuma secību, kad to vēlas izdarīt apzināti, pat ja nepavisam nav nepieciešamības saglabāt ārējo gadījumu.■ Filtrējošais nosacījums ir pievienots tīšām, bet tam ir jābūt savienojuma daļai! Ja filtrējošo nosacījumu pārveido par savienojuma daļu, tad vaicājums datu bāzei skanēs kā „Detaļu tabulas katrai rindai atrast piemērotu rindu no šī tabulas, kas apmierina filtru, ja tāds eksistē; citādi, ievietot atbilstošu pseidorindu, sastāvošu no vērtībām null”.

24

ĀRĒJĀ SAVIENOJUMA NOSACĪJUMI VIENAI TABULAI---------------------------------------------Oracle vecajā pieraksta stilā filtrējošā nosacījuma pārveidošana par savienojuma daļu tiek veikta pievienojot (+). Piemēram, divdaļīgais ārējais savienojums ar tabulu Code_Translations, kura tika izmantota iepriekšējos piemēros, izskatītos šādi:WHERE …

AND O.Order_Type_Code = OTypeTrans.Code(+)AND OTypeTrans. Type(+) = 'ORDER_TYPE'

ANSI jaunajā savienojumu pieraksta stilā, kurš vienīgais ir atļauts DB2 ārējo savienojumu pierakstīšanai, filtrējošais nosacījums pāriet uz sadaļu FROM, lai kļūtu par atklātu savienojuma nosacījumu:FROM … Orders O …LEFT OUTER JOIN Code_Translations OTypeTrans

ON O.Order_Type_Code = OTypeTrans.CodeAND OTypeTrans. Type= 'ORDER_TYPE'

Sākotnējā ārējo savienojumu pierakstā SQL Server datu bāze vienkārši uzskata, ka filtrējošais nosacījums ir savienojuma daļa:WHERE …

AND O.Order_Type_Code *= OTypeTrans.CodeAND OTypeTrans. Type = 'ORDER_TYPE'

Ir jāpievērš uzmanību tam, ka tas padara apskatīto problēmu par neiespējamu ārējiem savienojumiem SQL Server vecajā stilā; datu bāze automātiski pārveido filtru par savienojuma daļa. Tāpat jāpievērš uzmanību tam, ka retos gadījumos, kad filtrs patiešam ir filtrs, nepieciešamā rezultāta iegūšanai vajag vai nu pārveidot pierakstu jaunajā stilā, vai nu pārveidot savienojumu ekvivalentā vaicājumā NOT EXISTS, par ko tiks pastāstīts vēlāk.

Pirmais scenārijs tiks aplūkots sīkāk. Tiks ņemts šāda veida vaicājums:SELECT …FROM Employees E

LEFT OUTER JOIN Departments DON E. Department_ID = D.Department_ID

WHERE D.Dept_Manager_ID IS NULL

Ko vaicājums patiesībā vēlas saņemt no datu bāzes? Semantiski tas pieprasa divas dažādas rindu kopas. Viena kopa satur datus par visiem darbiniekiem, kuriem nav norādīta nodaļa, bet otra meklē visus darbiniekus, kam ir norādīta nodaļa, kurai nav priekšnieka. Eksistē varbūtība, ka pielikums patiešām grib vienlaicīgi saņemt šādas divas dažādas kopas, taču ir lielāka varbūtība, ka izstrādātājs nav pamanījis, ka tik vienkāršam vaicājumam ir tik sarežģīts rezultāts, un viņam nav vajadzīga viena no šīm rindas kopām.

Jāaplūko nedaudz atšķirīgu piemēru:SELECT … FROM Employees E

LEFT OUTER JOIN Departments DON E. Department_ID = D.Department_ID

WHERE D. Department_ID IS NULLNo pirmā acu uzmetiena liekas, ka tas ir nedabīgs vaicājums, tāpēc, ka tabulas

Departments primārā atslēga (Department_ID) nevar būt vienāda ar null. Pat ja null būtu primārās atslēgas pieļaujamā vērtība, šāds savienojums ar otru tabulu nekad nebūtu veiksmīgs šādai atslēgvērtībai (jo pieņemtā izteiksme NULL = NULL atgriež patieso vērtību „nav zināms”). Taču, tā kā tas ir ārējais savienojums, eksistē saprātīga šā jautājuma interpretācija – „Atrast visus darbiniekus, kuriem neeksistē atbilstošu nodaļu”. Šo ārējo savienojumu ārējā gadījumā visi stabiņi Departments, ieskaitot pat stabiņus, kas obligāti nav vienādi ar null, iegūst vērtību null, tāpēc nosacījums D. Department_ID IS NULL būs patiess tikai ārējā gadījumā. Ir arī plašāk izplatīts un vienkāršāks uztverei šāda vaicājuma pieraksta veids:

25

SELECT … FROM Employees EWHERE NOT EXISTS (SELECT *

FROM Departments DWHERE E. Department_ID = D.Department_ID)

Kaut gan šāda veida vaicājumu forma NOT EXISTS ir dabīgāka un to ir vieglāk lasīt un saprast, SQL iestatīšanā ir vieta arī citai formai (labākai saprašanai ir iesakāmi to labi komentēt). Priekšrocība, ka nosacījums NOT EXISTS izteikts kā ārējs savienojums, kuram seko Primārā_atslēga IS NULL, ir tāda, ka šāda forma ļauj precīzāk kontrolēt, kad tieši izpildes plānā tiks izpildīts savienojums, un kad tiks izmantota šā nosacījuma selektivitāte. Parasti nosacījumi NOT EXISTS tiek vērtēti pēc visiem parastajiem savienojumiem, vismaz, pie Oracle. Tas ir viens no piemēriem, kad filtrs (kas nav ārēja savienojuma daļa) uz pievienojamās ārējās tabulas patiešām var būt paredzēts un pareizs.

PIEZĪME------------------------------------------------------------------------------------------------Ārējo savienojumu vecajā pierakstā SQL Serverī ārējā savienojuma kombinācija ar nosacījumu „vienāds ar null” nestrādā. Piemēram, pārveidojot iepriekšējo piemēru SQL Server pierakstā, var izmēģināt šādu vaicājumu:SELECT … FROM Employees E. Departments DWHERE E. Department_ID * = D.Department_ID

AND D.Department_ID IS NULLTaču rezultāts būtu pavisam ne tāds, kā domā sagaidīt! Ir jāatceras, ka SQL Server interpretē visus filtrējošos nosacījumus pievienojamai ārējai tabulai kā savienojuma daļu. SQL Server mēģinās veikt savienojumu ar rindām Departments, kurām eksistē vienādas ar null primārās atslēgas (piemēram, D.Department_ID vērtības, vienādas ar null). Pat ja šādas rindas eksistētu, izjaucot datu bāzes pareizo dizainu, tās nekad nevarētu veiksmīgi pievienot pie tabulas Employees, jo savienojums pēc vienlīdzības noteikuma nevar būt veiksmīgi izpildīts priekš atslēgvērtībām, vienādām ar null. Tā vietā vaicājums neatfiltrēs nekādas rindas, bet atgriezīs visus darbiniekus, turklāt visi savienojumi būs ārējie.

1.6.2. Ārējie savienojumi, kas ved pie iekšējiem savienojumiemTālāk tiks aplūkots 24.att., kurā ārējais savienojums ved pie iekšēja savienojuma.

24.att. Ārējais savienojums ved pie iekšēja savienojuma

Oracle SQL vecajā stilā šāds savienojums tiek pierakstīts kā:

SELECT …

26

FROM Table1 T1, Table2 T2, Table3 T3WHERE T1. FKey2 = T2. PKey2(+)

AND T2. FKey3 = T3. PKey3

Pirmā savienojuma ārējā gadījumā datu bāze ģenerēs pseidorindu no T2, turklāt visu stabiņu, tajā skaitā T2. FKey3, vērtība būs vienāda ar null. Taču vienāda ar null ārējā atslēga nekad nevar būt veiksmīgi pievienota pie citas tabulas, tāpēc rinda, kas parādās kā savienojuma ārējs gadījums, tiks atmesta pie mēģinājuma izpildīt iekšēju savienojumu ar T3. Tādā veidā, ārējais savienojums, kas ved pie iekšēja savienojuma, dod tieši tādu pašu rezultātu, kādu varētu saņemt, ja abi savienojumi būtu iekšējie. Taču tā izmaksas ir augstākas, jo datu bāze atmet rindas, kas neapmierina savienojumu, vēlāk izpildīšanas plānā. Tā vienmēr būs kļūda. Ja izstrādātājs pieprasa saglabāt šāda veida savienojumu, tad ir jānomaina ārējo savienojumu, kas ved pie iekšējā, ar ārējo savienojumu, kas ved pie cita ārējā savienojuma. Pretējā gadījumā ir jāizmanto divus iekšējos savienojumus.

1.6.3. Ārējie savienojumi, kas norāda uz detaļu tabuluAplūkosim 25.att., kur bultiņas rādītājs saites vidū apzīmē ārēju savienojumu, kas norāda uz detaļu tabulu.

25.att. Ārējais savienojums virzienā uz detaļu tabuluJaunajā pierakstu stilā ANSI tas varētu būt šāda veida vaicājums:

SELECT … FROM Departments D

LEFT OUTER JOIN Employees EON D. Department_ID = E.Department_ID

Vai Oracle vecajā pierakstā:SELECT … FROM Departments D. Employees EWHERE D. Department_ID = E.Department_ID(+)

SQL Server vecajā pierakstāSELECT … FROM Departments D. Employees EWHERE D. Department_ID *= E.Department_ID

Jebkurā gadījumā, ko semantiski nozīmē šis vaicājums? To var iztēloties kā aicinājumu: ”Nosauc man visus darbiniekus, kuriem ir norādītas nodaļas (iekšējais gadījums), kā arī datus par viņu nodaļām, un vēl pievieno datus par nodaļām, kurās nav darbinieku (ārējais gadījums)”. Iekšējā gadījumā rezultāts salīdzina katru rindu ar detaļu

27

būtību (darbinieks, piederīgs kādai nodaļai), bet ārējā gadījumā rezultāts atspoguļo katru rindu uz galveno būtību (nodaļa, nepiederoša nevienam darbiniekam). Maz ticams, ka šāds bezjēdzīgs būtību maisījums būs lietderīgs un nepieciešams vienā vaicājumā, tāpēc tamlīdzīgi vaicājumi, kuros ārēji savienojumi ved pie detaļu tabulām, reti mēdz būt patiesi. Visizplatītākais šādas kļūdas gadījums – tas ir savienojums ar detaļu tabulu, kura parasti piedāvā nulli vai vienu detaļu rindu katrai galvenajai, un tikai reizēm šis savienojums piedāvā vairākas detaļu rindas galvenajai tabulai. Reizēm izstrādātāji izlaiž no redzes viedokļa šī retā gadījuma „daudzi pret vienu” sekas, bet testēšanas laikā kļūda var arī neparādīties.

1.6.4. Ārējie savienojumi ar detaļu tabulu ar filtruUz 26. att. parādīts ārējais savienojums ar detaļu tabulu, kurai arī eksistē filtrējošais nosacījums. Reizēm divas kļūdas kompensē viena otru. Ārējais savienojums ar detaļu tabulu, kurai ir filtrs, ir divkārša kļūda un tai piemīt visi trūkumi, aprakstīti divās pēdējās apakšnodaļās. Reizēm filtrs kompensē problemātiskā ārējā savienojuma efektu, funkcionāli to pārvēršot par iekšējo. Šādos gadījumos ir jāizvairās no filtra novākšanas, ja vienīgi jūs vienlaicīgi nepārvēršat ārējo savienojumu par iekšējo.

26. att. . Ārējais savienojums ar filtrētu detaļu tabulu

Visinteresantākais gadījums, ko var ilustrēt 26. att., kad filtram ir jēga tikai ārējā savienojuma kontekstā. Tas ir gadījums, kad filtrējošais nosacījums priekš T1 ir patiess tikai ārējā gadījumā – piemēram, T1. Fkey_ID IS NULL. (Šeit T1. Fkey_ID - ir ārējā atslēga, kas norāda uz T2. PKey_ID diagrammā parādītajā savienojumā.) Tāpat kā iepriekšējā piemērā nosacījums IS NULL savienojuma atslēgas vērtībai (tad tā bija primārā atslēga), šis gadījums ir ekvivalents apakšvaicājumam NOT EXISTS. Tāpat kā tajā piemērā, šī nosacījuma NOT EXISTS neparastā izpausme reizēm nodrošina papildus kontroles pakāpi pār vietu izpildes plānā, kad datu bāze izpilda savienojumu un atmet rindas, kuras neapmierina nosacījumu. Tā kā visas rindas, pievienotas iekšējā gadījumā, tiek atmestas ar nosacījumu IS NULL, tad izvairās no parastās problēmas, kas rodas pie ārējā savienojuma ar detaļu tabulām, dažādu būtību samaisīšanas rindās, kas iegūtas iekšējā un ārējā savienojuma gadījumos. Atkal divas kļūdas kompensē viena otru.

28

2. Vaicājumi ar apakšvaicājumiem

Praktiski visi reālie vaicājumi ar apakšvaicājumiem ietver speciāla veida nosacījumus rindām ārējā, galvenajā vaicājumā; tām ir jāatbilst vai nav jāatbilst piemērotām rindām saistītā vaicājumā. Piemēram, ja ir vajadzīgi dati par nodaļām, kurās ir darbinieki, var izmantot šādu vaicājumu:SELECT … FROM Departments D. WHERE EXISTS (SELECT NULL

FROM Employees EWHERE E. Department_ID = D.Department_ID)

Vai arī var pieprasīt datus par nodaļām, kurās nav darbinieku:SELECT … FROM Departments D. WHERE NOT EXISTS (SELECT NULL

FROM Employees EWHERE E. Department_ID = D.Department_ID)

Savienojums E. Department_ID = D.Department_ID katrā no šiem vaicājumiem – tas ir korelācijas savienojums, kurš nostāda rindas no ārējā vaicājuma un apakšvaicājuma saskaņā vienai ar otru. Vaicājumam EXISTS ir alternatīva ekvivalentā forma:SELECT … FROM Departments D. WHERE D.Department_ID IN (SELECT E. Department_ID FROM Employees E)

Tā kā funkcionāli šīs formas ir ekvivalentas, bet diagrammai ir jābūt objektīvai attiecībā pret abām formā, tad diagrammas tām izskatās vienādas. Tikai pēc diagrammas izvērtēšanas ir jāizvēlas, kāda no formām labāk risina iestatīšanas problēmu un izsaka labāko ceļu pie datiem.

2.1. Vaicājumu ar apakšvaicājumiem attēlošana uz diagrammām

Ignorējot savienojumu, kurš saista ārējo vaicājumu ar apakšvaicājumu, vienmēr var izveidot atsevišķas, neatkarīgas vaicājumu diagrammas katram no diviem vaicājumiem. Vienīgais atklātais jautājums – kā nepieciešams attēlot attiecību starp šīm divām diagrammām, kura apvieno tās vienā. Kā paskaidro iepriekšējā vaicājuma forma EXISTS, ārējais vaicājums ir saistīts ar apakšvaicājumu, izmantojot korelācijas savienojuma palīdzību. Šim savienojumam ir sevišķa īpašība – katrai ārējā vaicājuma rindai datu bāze pārtrauc attiecīgo rindu meklēšanu, uzskata nosacījumu EXISTS par apmierinātu un nodot ārējā vaicājuma rindu uz izpildes plāna nākamo etapu, tiklīdz atradīs pirmo atbilstību dotajam savienojumam. Kad tā atrod atbilstību korelētajam apakšvaicājumam NOT EXISTS, tā pārtrauc darbu, uzskatot nosacījumu NOT EXISTS par neapmierinātu, un nekavējoties atmet rindu no ārējā vaicājuma, neveicot ar to vairāk nekādas darbības. Ar šādu rīcību ir jāsaprot, ka vaicājumu diagrammai ir jāatbild uz četriem speciāliem jautājumiem par korelācijas savienojumu. Šie jautājumi nav pieņemami pie parastiem savienojumiem.■ Vai tas ir parasts savienojums? (Nē, tas ir korelācijas savienojums ar apakšvaicājumu.)

29

■ Kāda savienojuma puse ir apakšvaicājums, bet kāda – ārējais vaicājums?■ To var izteikt kā vaicājumu EXISTS vai kā vaicājumu NOT EXISTS?■ Cik drīz izpildes plānā ir jāveic apakšvaicājums?

Strādājot ar apakšvaicājumiem un apskatot šos jautājumus, ir jāatceras, ka tāpat ir jāatspoguļo uz diagrammas īpašības, kas raksturīgas jebkuriem savienojumiem – kāds savienojuma gals attiecas uz galveno tabulu un kādi ir savienojuma koeficienti.

2.1.1. Apakšvaicājumu EXISTS diagrammu attēlojumsUz 27.att. tika parādīti pieņemtie apzīmējumi, kādi bija izmantoti vaicājuma ar EXISTS tipa apakšvaicājumu (kurš var būt izteikts ekvivalenta apakšvaicājuma IN veidā) diagrammu attēlojumam. Šis attēls attiecas uz iepriekšējo apakšvaicājumu EXISTS:SELECT … FROM Departments D. WHERE EXISTS (SELECT NULL

FROM Employees EWHERE E. Department_ID = D.Department_ID)

27.att.Parasts vaicājums ar apakšvaicājumu

Korelācijas savienojumam (tāpat sauktam par pussavienojumu attiecībā uz EXISTS tipa apakšvaicājumiem) Departments ar Employees diagramma sākas ar tādu pašu savienojuma statistiku, kāda dota 5.1.att.

Pussavienojums, kas saista iekšējo vaicājumu ar ārējo, ir saite ar rādītāju tajā galā (vai abos galos), kurš norāda uz primāro atslēgu. Tāpat kā katram savienojumam, pussavienojuma abos galos norādīti koeficienti, ar tādām pašām statistikas īpašībām, kādas šim savienojumam būtu vienkāršā vaicājumā. Saites vidū ir iezīmēta bultiņa, kas norāda no korelācijas mezgla ārējā vaicājumā uz korelācijas mezglu apakšvaicājumā. Blakus bultas centrālajam rādītājam tiek rakstīts burts E, lai parādītu, ka šis pussavienojums ir apakšvaicājumam EXISTS vai IN.

Šajā gadījumā diagrammas daļa, kas attēlo apakšvaicājumu, ir viens mezgls, kas nozīmē, ka apakšvaicājumam nav savu savienojumu. Retākos gadījumos ārējais vaicājums arī atspoguļojas kā vienīgais mezgls, kas attēlo ārējo vaicājumu bez saviem savienojumiem. Sintakse ar nolūku netiek ierobežota, atļaujot tādas situācijas, kā vairāki apakšvaicājumi, saistīti ar ārējo vaicājumu, apakšvaicājumi ar savu sarežģītu savienojumu skeletu un pat apakšvaicājumi, norādoši uz vēl dziļāk ievietotiem saviem apakšvaicājumiem.

Saitei, kas attēlo pussavienojumu, ir nepieciešami līdz diviem jauniem skaitļiem, lai nodotu apakšvaicājuma īpašības, kas vienkāršo vislabākā plāna izvēli. 2att. parādīti abi papildus lielumi, kuri reizēm ir nepieciešami pie optimāla apakšvaicājuma apstrādes plāna izvēles.

Pirmais lielums, blakus burtam E (20 2attēlā), ir prioritātes korelācijas koeficients. Prioritātes korelācijas koeficients ir vienāds ar I/E. E ir noteikts vai izmērīts

30

labākā plāna izpildes laiks gadījumā, kad tas izpildās no ārējā vaicājuma uz apakšvaicājumu (sekojot EXISTS loģikai). I ir noteikts vai izmērīts labākā plāna izpildes laiks gadījumā, kad tas izpildās no iekšējā vaicājuma uz ārējo vaicājumu (sekojot IN loģikai). Vienmēr var aprēķināt šo koeficientu, izmērot abu formu izpildes laiku. Parasti tas nesastāda lielas problēmas, ja tikai dzīvi nesarežģī daudzu apakšvaicājumu kombinācija. Drīzumā tiks paskaidroti vairāki īkšķa likumi, lai izmērītu attiecību I/E ar lielāku vai mazāku precizitāti, taču pat aptuvens novērtējums ir pieņemams plāna izvēlei, jo kā tas bieži notiek, lielums ir vai nu daudz mazāks par 1,0, vai arī daudz lielāks par 1,0. Kad prioritātes korelācijas koeficients ir lielāks par 1,0, ir jāizvēlas korelācijas apakšvaicājumu ar nosacījumu EXISTS un plānu, kurš sāk ar ārējo vaicājumu un iet uz apakšvaicājumu.

Otrs jaunais lielums ir precizētais apakšvaicājuma filtrācijas koeficients (0,8 2attēlā), kurš tiek pierakstīts blakus savienojuma detaļu koeficientam. Tas ir noteikts lielums, kas palīdz izvēlēties labāko vietu savienojumu secībā lai pārbaudītu apakšvaicājuma nosacījumu. Tas tiek izmantots tikai vaicājumos, kas sākas ar ārējo vaicājumu, tāpēc ir jāizslēdz to no pussavienojuma saites (ar prioritātes korelācijas koeficientu, mazāku par 1,0), kuru pārveido par vadošo vaicājumu plānā.

PIEZĪME-----------------------------------------------------------------------------------------------Ja ir vairāki pussavienojumi ar prioritātes korelācijas koeficientu, mazāku par 1,0, tad ir jāsāk ar apakšvaicājumu kam vismazākais koeficients, un tieši tāpat būs vajadzīgi precizētie filtrācijas koeficienti pārējiem apakšvaicājumiem.

Pirms izskaidrot apakšvaicājumu prioritātes korelācijas koeficientu un precizēto filtrācijas koeficientu aprēķināšanu, tiks noskaidrots, kad tie ir vajadzīgi. 28.att. parādīta daļēja vaicājuma diagramma EXISTS tipa apakšvaicājumam, kurā apakšvaicājuma saknes detaļu tabula atrodas pussavienojuma galā, kurš norāda uz primāro atslēgu.

28.att. Pussavienojums ar primāro atslēgu

Šeit pussavienojums funkcionāli ne ar ko neatšķiras no parasta savienojuma, jo vaicājums nekad neatradīs dotajai rindai no ārējā vaicājuma vairāk par vienu atbilstību tabulā M.

PIEZĪME-----------------------------------------------------------------------------------------------Tiek pieņets, ka viss apakškoks zem virsotnes M atbilst normālai formai (t.i. visas saites norāda uz leju uz primārajām atslēgām), bet pilns apakšvaicājums viennozīmīgi atspoguļojas uz rindām no apakškoka sakņu detaļu tabulas M.

31

Tā kā pussavienojums funkcionāli ne ar ko neatšķiras no parasta savienojuma, var panākt augstāku brīvības pakāpi izpildes plānā, atklāti izslēdzot nosacījumu EXISTS un savienojot apakšvaicājumu ar ārējo vaicājumu. Piemēram, tiks apskats šāds vaicājums:SELECT < Stabiņi tikai no ārējā vaicājuma>FROM Order_Details OD. Products P. Shipnemts S.

Addresses A. Code_Translations ODTWHERE OD. Product_ID = P. Product_ID)

AND P.Unit_Cost > 100AND OD.Shipment_ID = S. Shipment_IDAND S. Address_ID = A. Address_ID(+)AND OD.Status_Code = ODT. CodeAND ODT. Code_Type = 'Order_Detail_Status'AND S.Shipment_Date > :now – 1AND EXISTS (SELECT null

FROM Orders O, Customers C. Code_Translations OT.Customer_ Types CT

WHERE C. Customer_ Type_ID = CT. Customer_ Type_IDAND CT.Text = 'Government'AND OD.Order_ID = D. Order_IDAND O. Customer_ID = C. Customer_IDAND O. Status_Code = OT. CodeAND O.Completed_Flag = 'N'AND OT. Code_Type = 'ORDER_STATUS'AND OT.Text ! = 'Canceled'

ORDER BY < Stabiņi tikai no ārējā vaicājuma>

Izmantojot jaunos pieņemtos apzīmējumus pussavienojumiem, šo vaicājumu var attēlot 29.att. parādītās diagrammas veidā.

29.att. Sarežģīts piemērs pussavienojumam ar korelācijas saiti ar apakšvaicājuma sakņu detaļas tabulas primāro atslēgu

Ja šo vaicājumu vienkārši pārrakstīs, pārvietojot savienojumus un apakšvaicājuma tabulu nosacījumus uz ārējo vaicājumu, tad iegūs funkcionāli identisku vaicājumu, jo pussavienojums tiek veikts ar primāro atslēgu un apakšvaicājums viennozīmīgi atspoguļojas uz savu sakņu detaļu tabulas:SELECT < Stabiņi tikai no izejošā ārējā vaicājuma>FROM Order_Details OD. Products P. Shipnemts S.

Addresses A. Code_Translations ODTOrders O. Customerc C. Code_Translations OT. Customer_ Types CT

WHERE OD. Product_Id = P. Product_IdAND P.Unit_Cost > 100

32

AND OD.Shipment_Id = S. Shipment_IdAND S. Address_Id = A. Address_Id(+)AND OD.Status_Code = ODT. CodeAND ODT. Code_Type = 'Order_Detail_Status'AND S.Shipment_Date > :now – 1

AND C Customer_Type_Id = CT. Customer_Type_IdAND CT.Text = 'Government'AND OD.Order_Id = D. Order_IdAND O. Customer_Id = C. Customer_IdAND O. Status_Code = OT. CodeAND O.Completed_Flag = 'N'AND OT. Code_Type = 'ORDER_STATUS'AND OT.Text ! = 'Canceled'

ORDER BY < Stabiņi tikai no izejošā ārējā vaicājuma>

Šī versija speciāli ir pierakstīta ar atkāpēm, lai pāreja no iepriekšējās versijas būtu acīmredzama. Vaicājumu diagramma arī praktiski identiska, kas redzams pēc 30.att.

30.att. Tas pats vaicājums, pārveidots, lai savienotu apakšvaicājumu ar ārējo vaicājumu

Šai jaunajai formai ir ievērojamas papildus brīvības pakāpes, kas ļauj veikt savienojumu ar filtrēto mezglu P pēc savienojuma ar labi filtrēto mezglu O, taču līdz savienojumam ar praktiski nenofiltrēto mezglu OT. Izejošā formā datu bāzei vajadzētu pilnībā apstrādāt visu apakšvaicājuma zaru pirms tam, kad pāriet pie savienojumiem ar nākošajiem ārējā vaicājuma mezgliem.

Teorētiski var izmantot to pašu triku ar EXISTS tipa apakšvaicājumu saplūšanu, kad pussavienojuma bultiņa norāda uz savienojuma detaļu galu, taču tas ir sarežģīti un mazāk iespējams, ka tas palīdzēs uzlabot vaicājuma veiktspēju. Tiks apskatīts iepriekšējais vaicājums ar nosacījumu EXISTS priekš Employees:SELECT … FROM Departments D. WHERE EXISTS (SELECT NULL

FROM Employees EWHERE E. Department_ID = D.Department_ID)

Nākošās problēmas rodas mēģinot izmantot šo pašu triku šajā gadījumā.■ Izejošais vaicājums atgriež maksimums vienu rindu uz katru rindu no galvenās tabulas katrai nodaļai. Lai iegūtu tādu pašu rezultātu no pārveidota vaicājuma ar parastu savienojumu ar detaļu tabulu (Employees), nepieciešams iekļaut sarakstā SELECT galvenās tabulas unikālo atslēgu un izpildīt operāciju DISTINCT ar iegūtajām vaicājuma

33

rindām. Šie soļi atmet dublikātus, kuri rodas, kad vienam galvenajam pierakstam ir vairāki piemēroti detaļu pieraksti.■ Kad galvenajai rindai ir vairākas piemērotas detaļu rindas, tad bieži vien visu atbilstību meklēšana iznāk dārgāk, nekā pussavienojuma apstādināšana pēc tam, kad atrasta pirmā atbilstība.

Šādā veidā reti rodas nepieciešamība pārveidot pussavienojumu parastos savienojumos, kad pussavienojuma bultiņa norāda augšup, ja tikai tajos gadījumos, kad savienojuma detaļu koeficients pussavienojumam tuvs 1,0 vai pat mazāks.

Lai pabeigtu diagrammu EXISTS tipa apakšvaicājumam, nepieciešami tikai apakšvaicājuma prioritātes korelācijas koeficienta un precizētā filtrācijas koeficienta aprēķināšanas noteikumi. Lai atrastu prioritātes korelācijas koeficientu, ir jāizpilda šādas darbības:

1. Lai D ir savienojuma detaļu koeficients pussavienojumam, bet M – galvenais savienojuma koeficients. Lai S – labākais (vismazākais) filtrācijas koeficients starp visiem mezgliem apakšvaicājumā, bet R - labākais (vismazākais) filtrācijas koeficients starp visiem mezgliem ārējā vaicājumā.

2. Ja D x S < M x R, tad prioritātes korelācijas koeficients ir vienāds ar (DxS)/(MxR).

3. Citādāk, ja S > R, tad prioritātes korelācijas koeficients ir vienāds ar S/R.4. Citādāk, lai E –vislabākā izpildes plāna izmērītais izpildes laiks, kurš sāk ar ārējo

vaicājumu un pāriet pie apakšvaicājuma (sekojot EXISTS loģikai). Lai I - vislabākā izpildes plāna izmērītais izpildes laiks, kurš sāk ar iekšējo vaicājumu un pāriet pie ārējā (sekojot IN loģikai). Lai prioritātes korelācijas koeficients ir vienāds ar I/E. Ja var novērtēt prioritātes korelācijas koeficientu ar soļu 2 un 3 palīdzību, tad balstoties uz šīm vērtībām var pārliecinoši izvēlēties apakšvaicājuma apstrādes virzienu, nemērot reālo izpildes laiku.

PIEZĪME------------------------------------------------------------------------------------------------Vērtība, aprēķināta 2. un 3. solī, var nesakrist ar precīzu izpildes laiku, kādu var iegūt ar mērījumu. Tomēr novērtējums ir pietiekoši precīzs, ja tas ir mērens un izvairās no vērtībām, kuras var novest pie nepareizas vadošā vaicājuma izvēles starp ārējo vaicājumu un apakšvaicājumu. Noteikumi soļos 2 un 3 paredzēti gadījumiem, kad šādas cerības, mērens novērtējums ir pilnīgi pieņemams.

Ja soļos 2 un 3 nevar iegūt pareizu novērtējumu, tad drošāk un vieglāk ir izmantot vērtību, iegūtu reālā mērījumā. Šādā retā gadījumā drošas aprēķinātās vērtības meklēšana būs daudz sarežģītāka, un rezultāts neattaisnos pieliktās pūles.

Pēc tam, kad ir atrasts prioritātes korelācijas koeficientu, ir jāpārbauda, vai ir nepieciešams apakšvaicājuma precizētais filtrācijas koeficients, un ja tas ir nepieciešams, tad tas ir jāatrod, izpildot šādas darbības:

1. Ja prioritātes korelācijas koeficients mazāks par 1,0 un mazāks par visiem pārējiem prioritātes korelācijas koeficientiem (gadījumam, kad ir vairāki apakšvaicājumi), ir jāapstājas. Šajā gadījumā apakšvaicājuma prioritātes koeficients nebūs vajadzīgs, tā kā tas ir vajadzīgs lēmuma pieņemšanai tikai tad, kad sāk no ārējā vaicājuma, bet šis nav tas gadījums.

2. Ja apakšvaicājums ir vienas tabulas vaicājums bez filtrējošā nosacījuma, tikai ar korelācijas savienojuma nosacījumu, ir jāizmēra q (rindu skaitu, atgrieztu ar ārējo vaicājumu, ja novāktu apakšvaicājuma nosacījumu) un t (rindu skaitu, atgrieztu ar

34

pilnu vaicājumu, ieskaitot apakšvaicājumu). Precizētais apakšvaicājuma filtrācijas koeficients būs vienāds ar t/q. Šajā gadījumā nosacījums EXISTS ir pietiekoši viegli pārbaudāms. Datu bāze vienkārši meklē pirmo sakrišanu savienojuma indeksā.

3. Citādi, pussavienojumam, lai D ir savienojuma detaļu koeficients. Lai s ir korelācijas mezgla (t.i. mezgla, kurš pievienots pussavienojuma saitei) filtrācijas koeficients detaļu galā, t.i. galā, kas pieder apakšvaicājumam.

4. Ja D ≤ 1, tad apakšvaicājuma precizētais filtrācijas koeficients ir vienāds ar s x D.5. Citādāk, ja s x D < 1, tad apakšvaicājuma precizētais filtrācijas koeficients ir

vienāds ar (D – 1 + (s x D))/D.6. Citādāk, lai apakšvaicājuma precizētais filtrācijas koeficients būtu vienāds ar

0,99. Pat ļoti slikti filtrējošs nosacījums EXISTS patiesībā ļaus izvairīties no rindu skaita palielināšanās un nodrošinās labāku filtrācijas vērtību uz mērījuma vienību, nekā savienojums uz leju pavisam bez filtra. Šis pēdējais noteikums attiecas uz gadījumiem „labāk, nekā nekas” (patiesībā mazliet labāk).

PIEZĪME------------------------------------------------------------------------------------------------Kā visi pārējie noteikumi šajā grāmatā, šie apakšvaicājuma korelācijas koeficienta un precizētā filtrācijas koeficienta aprēķināšanas noteikumi ir heiristiski. Tā kā precīzi cipari ir reti vajadzīgi pareiza izpildes plāna izvēlei, šie rūpīgi izprojektētie, drošie heiristiskie noteikumi ļauj pieņemt pareizo lēmumu vismaz 90% gadījumos, un praktiski nekad nedod ļoti sliktus risinājumus. Tāpat kā daudzās citās grāmatas daļās precīzu koeficientu aprēķināšana komplicētam vaicājumam atrodas tālu aiz manuālo regulēšanas metožu iespēju robežām.

Ir jāpārbauda, kā ir izprasti noteikumi, aprēķinot prioritātes korelācijas koeficientu un precizēto filtrācijas koeficientu 31.att., kurā iztrūkst šo divu skaitļu.

31.att. Komplicēts vaicājums, kurā iztrūkst vajadzīgās pussavienojuma vērtības

Tālāk ir izskaidrojums kā aprēķināt prioritātes korelācijas koeficientu. 1. Lai D = 2 un M = 1 (kas nozīmē, ka šī skaitļa nav uz diagrammas). Lai S = 0,015

(labākais filtrācijas koeficients starp visiem apakšvaicājumā, kas pieder tabulai S3, kura atrodas par diviem līmeņiem zemāk par apakšvaicājuma sakņu detaļu tabulu D). Lai tagad R = 0,01, t.i. būtu vienāds labākā filtra vērtībai starp visiem koka mezgliem zem ārējā vaicājuma sakņu detaļu tabulas M, ieskaitot šo mezglu.

2. Tiek atrasts D x S = 0,03 un M x R = 0,01; tātad, D x S > M x R. Pāriet pie soļa 3.3. Tā kā S > R, tad prioritātes korelācijas koeficients ir vienāds ar S/R, tātad 1,5.Lai atrastu apakšvaicājuma precizēto filtrācijas koeficientu jādara sekojošo:

35

1. Jāpievērš uzmanību tam, ka prioritātes korelācijas koeficients ir lielāks par 1, tāpēc ir jāpāriet pie soļa 2.

2. Jāpievērš uzmanību tam, ka apakšvaicājums ietver vairākas tabulas un satur filtrus, tāpēc ir jāpāriet pie soļa 3.

3. Atrod D = 2, un filtrācijas koeficientu mezglam D, s = 0,1.4. Tā kā D > 1, tad nepieciešams pāriet pie soļa 5.5. Aprēķina s x D, kas mazāks par 1, tāpēc precizēto filtrācijas koeficientu ir

jāaprēķina kā (D – 1 + (s x D))/D = (2 – 1 + (0,1 x 2))/2 = 0,6.

Nākamajā nodaļā, kas veltīta apakšvaicājuma EXISTS optimizācijai, tiks parādītas pilnas diagrammas, attēlojot 32.att., optimizāciju.

2.1.2. Apakšvaicājuma NOT EXISTS diagrammu attēlojumsApakšvaicājuma nosacījumi, kurus var izteikt ar NOT EXISTS vai NOT IN, ir vienkāršāki, nekā EXISTS tipa apakšvaicājumi, attiecībā uz vienu – nevar pāriet ārā no apakšvaicājuma pie ārējā vaicājuma. Tas novērš nepieciešamību pēc prioritātes korelācijas koeficienta. Burts E, kas norāda uz EXISTS tipa apakšvaicājuma nosacījumu, tiek nomainīts ar burtu N, lai apzīmētu NOT EXISTS tipa apakšvaicājuma nosacījumu, bet korelācijas savienojums tagad saucas par antisavienojumu, nevis par pussavienojumu, tā kā tas ir paredzēts lai meklētu gadījumu, kad savienojumam ar rindām no apakšvaicājuma nav atrodamas atbilstības.

Izrādās, ka praktiski vienmēr NOT EXISTS tipa apakšvaicājuma nosacījumus labāk ir izteikt ar NOT EXISTS palīdzību, bet nevis ar NOT IN palīdzību. Tālāk tiks apskatīts šāds šablons NOT IN apakšvaicājumam:SELECT … FROM … Outer_Anti_Joined_Table OuterWHERE …

AND Outer.Some_Key NOT IN (SELECT Inner.Some_KeyFROM … Subquery_Anti_Joined_Table Inner WHERE<Nosacījumi un savienojumi apakšvaicājuma tabulām>

…Var un vajag šo šablonu pārfrāzēt ekvivalentā formā NOT EXISTS.

SELECT … FROM … Outer_Anti_Joined_Table OuterWHERE …

AND Outer.Some_Key IS NOT NULLAND NOT EXISTS (SELECT null

FROM … Subquery_Anti_Joined_Table Inner WHERE<Nosacījumi un savienojumi apakšvaicājuma tabulām>AND Outer.Some_Key = Inner.Some_Key)

PIEZĪME----------------------------------------------------------------------------------------------Lai pārveidotu NOT IN par NOT EXISTS neizmainot funkcionalitāti, ir jāpieliek nosacījums NOT null korelācijas savienojuma atslēgai ārējā tabulā. Iemesls tam ir tāds, ka nosacījums NOT IN ir ekvivalents nosacījumu kopai „nav vienāds”, kas savienoti ar nosacījumu VAI, taču datu bāze neuzskata izteiksmi NULL ! = <Kāda vērtība> par patiesu, tāpēc forma NOT IN atmet visas rindas no ārējā vaicājuma ar vienādām ar null korelācijas savienojuma atslēgām. Šis fakts ir maz zināms, tāpēc iespējams, par šāda vaicājuma izstrādātāja patieso nolūku ir vaicājuma rezultātā iekļaut rindas, kuras forma NOT IN nemanāmi izslēdz. Pārveidojot formas parādās lieliska iespēja atrast un izlabot šo iespējamo kļūdu.

36

EXISTS un NOT EXISTS tipa apakšvaicājuma nosacījumi izbeidz atbilstību meklēšanu uzreiz pēc tam, kad atrod pirmo atbilstību, ja tāda eksistē. Apakšvaicājuma NOT EXISTS nosacījumi ir potenciāli lietderīgāki, ja tos izmanto izpildes plānā, tā kā, kad tie ātri apstājas ar atrasto atbilstību, tad atmet attiecīgo rindu, bet nesaglabā to, kas padara nākošos plāna soļus ātrākus. Turpretī, lai atmestu rindu ar nosacījumu EXISTS, datu bāzei ir jāpārbauda visas potenciāli piemērotās rindas un jāizslēdz tās – tā ir dārgāka operācija, ja pussavienojumā katrai galvenajai rindai eksistē daudz detaļu pierakstu. Ir jāatceras sekojošus noteikumus, lai salīdzinātu nosacījumus EXISTS un NOT EXISTS, kas norāda uz detaļu tabulām no galvenās tabulas ārējā vaicājumā:■ Neselektīva nosacījuma EXISTS pārbaude nav dārga (tā kā atbilstība atrodas viegli, parasti jau pirmajā pārbaudītajā pussavienojuma rindā), taču atmet nedaudz rindu no ārējā vaicājuma. Jo vairāk rindu atgriezīs apakšvaicājums, jo lētāka un mazāk selektīva ir nosacījuma EXISTS pārbaude. Taču ja nosacījums EXISTS ir selektīvs, tad tā pārbaude, iespējams, ir dārgāka, jo ir jāizslēdz atbilstība katrai detaļu rindai.■ Selektīva nosacījuma NOT EXISTS pārbaude nav dārga (tā kā atbilstība atrodas viegli, parasti jau pirmajā pārbaudītajā pussavienojuma rindā) un atmet daudz rindu no ārējā vaicājuma. Jo vairāk rindu atgriezīs apakšvaicājums, jo lētāka un selektīvāka ir nosacījuma NOT EXISTS pārbaude. No otras puses, neselektīvo nosacījumu NOT EXISTS pārbaude arī ir dārga, tā kā katrai detaļu rindai ir nepieciešams apstiprinājums, ka atbilstība neeksistē.

Tā kā apakšvaicājuma NOT EXISTS nosacījumu pārveidošana ekvivalentos vienkāršos vaicājumos bez apakšvaicājumiem gan dārga, gan ne sevišķi lietderīgi, labāk izmantot apakšvaicājuma NOT EXISTS abos antisavienojuma galos: tur, kur atrodas galvenā tabula, un tur, kur detaļu tabula. Ļoti reti rodas nepieciešamība meklēt alternatīvus nosacījuma NOT EXISTS izteiksmes veidus.

Tā kā selektīvo nosacījumu NOT EXISTS pārbaude nav dārga, izrādās, ka aprēķināt apakšvaicājuma precizēto filtrācijas koeficientu ir viegli.

1. Jāizmēra q (rindu skaitu, ko atgrieza ārējais vaicājums, ja noņemtu apakšvaicājuma NOT EXISTS nosacījumu) un t (rindu skaitu, ko atgrieza pilns vaicājums, ieskaitot apakšvaicājumu). Lai C – tabulu skaits apakšvaicājuma sadaļā FROM (parasti nosacījumiem NOT EXISTS šis skaitlis ir vienāds ar vieninieku).

2. Lai precizētais filtrācijas koeficients ir vienāds ar (C – 1 + (t/q))/C.

2.2. Vaicājumu ar apakšvaicājumiem regulēšana

Tāpat kā vienkāršiem vaicājumiem, arī komplicētiem vaicājumiem ar apakšvaicājumiem optimizācija izpildās vienkārši, ja ir pareiza vaicājuma diagramma. Tālāk ir uzskaitīti sarežģītu vaicājumu, ieskaitot apakšvaicājumus, optimizācijas soļi, balstoties uz pilnu vaicājuma diagrammu.

1. Jāpārveido visus nosacījumus NOT IN ekvivalentos nosacījumos NOT EXISTS sekojot iepriekš aprakstītajam šablonam.

2. Ja korelācijas savienojums ir EXISTS tipa savienojums, un apakšvaicājums atrodas šā savienojuma galvenajā galā (t.i. bultiņas rādītājs saites vidū norāda uz leju), ir

37

jāpārveido komplicēto vaicājumu vienkāršos, kā aprakstīts augstāk, un jānoregulē to, sekojot vienkāršo vaicājumu parastiem noteikumiem.

3. Citādāk, ja korelācijas savienojums ir EXISTS tipa savienojums, ir jāatrod vismazāko prioritātes korelācijas koeficientu starp visiem EXISTS tipa apakšvaicājumiem (ja to ir vairāk nekā viens). Ja šī koeficienta vērtība ir mazāka par 1,0, jāpārveido šo apakšvaicājuma nosacījumu ekvivalentā nosacījumā IN un jāizsaka visus pārējos EXISTS tipa apakšvaicājuma nosacījumus, atklāti pielietojot nosacījumu EXISTS. Jāoptimizē nekorelēto apakšvaicājumu IN, tā it kā tas būtu atsevišķs vaicājums; tas ir visa vaicājuma izpildes plāna sākums. Pēc nekorelētā apakšvaicājuma apstrādes datu bāze izpildīs šķirošanas operāciju, lai izmestu korelētā savienojuma atkārtojošās atslēgas no saraksta, ko izveidojis apakšvaicājums. Nākošais savienojums pēc šī pirmā apakšvaicājuma apstrādes tiek veikts ar korelēto atslēgu ārējā vaicājumā, sekojot indeksam pēc šī savienojuma atslēgas, kuru vajag indeksēt. Sākot no šī punkta, ir jāapstrādā ārējo vaicājumu tā, it kā vadošais apakšvaicājums neeksistētu, bet pirmais mezgls būtu ārējā vaicājuma vadošā tabula.

4. Ja visi prioritātes korelācijas koeficienti lielāki vai vienādi ar 1,0 vai arī vaicājumā ir tikai NOT EXISTS tipa apakšvaicājuma nosacījumi, jāizvēlas vadošo tabulu no ārējā vaicājuma tā, it kā ja tajā nebūtu apakšvaicājuma nosacījumu, sekojot vienkāršo vaicājumu parastajiem noteikumiem.

5. Kad tiks sasniegti ārējā vaicājuma mezgli, kuri ietver pussavienojumus vai antisavienojumus ar vēl neizpildītiem apakšvaicājumiem, jāapstrādā katru apakšvaicājumu tā, it kā tas būtu viens zemāk stāvošais mezgls (pat ja korelācijas savienojums patiesībā būtu uz augšu). Jāizvēlas pāri palikušo apakšvaicājumu izpildes punktus tā, it kā šiem virtuālajiem mezgliem būtu filtrācijas koeficients, kas vienāds ar apakšvaicājuma precizēto filtrācijas koeficientu.

PIEZĪME-----------------------------------------------------------------------------------------------Tā kā korelācijas apakšvaicājumi apstājas, tikko ir atraduši pirmo piemēroto rindu, ja tāda eksistē, tad tie izvairās no rindu palielināšanās riska un var tikai samazināt tekošo rindu skaitu. Taču tā kā tiem nākas izpētīt daudz rindas lai izpildītu filtrāciju, apakšvaicājuma precizētā filtrācijas koeficienta pareizā vērtība bieži vien šo virtuālo mezglu padara ekvivalentu praktiski nefiltrētam mezglam attiecībā uz priekšrocībām izmaksu ziņā.

6. Tiklīdz, izpildot soli 5, ievieto savienojumu secībā korelēto savienojumu, uzreiz jāizpilda visu doto korelēto apakšvaicājumu, optimizējot šī apakšvaicājuma izpildes plānu, uzskatot korelācijas mezglu par šī neatkarīgā vaicājuma vadošo mezglu. Pabeidzot šī apakšvaicājuma apstrādi, jāatgriežas pie ārējā vaicājuma un jāturpina optimizēt tālāko savienojumu secību.

Kā piemērs tiks ņemts 32.att., kas ir 31.att. ar norādītiem: apakšvaicājuma prioritātes korelācijas koeficientu un precizēto filtrācijas koeficientu.

38

32.att. Uzdevums komplicēta vaicājuma ar apakšvaicājumu optimizācijai

Tā kā korelācijas savienojums attiecas pie EXISTS tipa, tad solis 1 netiek izmantots. Tā kā bultiņas rādītājs pussavienojuma vidū norāda uz augšu, tad solis 2 netiek izmantots. Pats mazākais (un vienīgais) prioritātes korelācijas koeficients vienāds ar 1,5 (blakus ar E), tāpēc solis 3 netiek izmantots. Izpildot soli 4, atrodam, ka labākais vadošais mezgls ārējā vaicājumā ir M. Izpildot soli 5, izvēlas starp savienojumiem uz leju ar A1 un A2 ar filtrācijas koeficientiem 0,2 un 0,7 attiecīgi, un virtuālo savienojumu uz leju ar virtuālo mezglu, kas pārstāv pilnu apakšvaicājumu, ar virtuālo filtrācijas koeficientu 0,6. A1 ir labākais no trim kandidātiem, kuriem ir labākais filtrācijas koeficients, tāpēc to pievieno kā nākošo. Tā kā no A1 nav savienojuma uz leju, tad par nākošo labāko izvēli savienojumu secībā uzskata apakšvaicājumu (atkal izmantojot soli 5), tāpēc izpilda pussavienojumu ar D.

Izpildot soli 6, jau uzsākot apakšvaicājuma apstrādi, nepieciešams to pabeigt, sākot ar D kā no vadošā mezgla. Sekojot vienkāršo vaicājumu noteikumiem, tālāk pievieno S1, S3, S2 un S4 norādītajā secībā. Atgriežoties pie ārējā vaicājuma un pielietojot vienkāršo vaicājumu noteikumus atrod atlikušo savienojumu secību kā A2, B1, B2. Pilna optimālā savienojumu secība, ieskaitot pussavienojumus, ir (M, A1, D, S1, S3, S2, S4, A2, B1, B2).

KĀDĒĻ IR TĀ JĀUZTRAUCAS PAR APAKŠVAICĀJUMIEM?---------------------------------------------Apakšvaicājumu noteikumi ir pietiekoši sarežģīti, lai apmulsinātu. Grāmatas autors jau vairāk nekā 10 gadus veic SQL ar apakšvaicājumiem iestatīšanu, neizmantojot formālos noteikumus, bet tikai ieklausoties savā intuīcijā un pielietojot vispārējos noteikumus sākuma punkta izvēlei no apakšvaicājuma vai no ārējā vaicājuma, balstoties uz to, kuriem ir selektīvāki nosacījumi. Parasti viņš nerūpējas par to, kad tieši tiks izpildīti apakšvaicājumi, izņemot gadījumus, kad ar tiem sākas visa vaicājuma izpilde, tā kā to ir grūti vadīt, bet uzlabojumi salīdzinot ar automātiskā optimizatora izvēli ir minimāli.Laiku pa laikam viņš sastopas ar robežgadījumiem, kad ir nozīme izmēģināt dažādus alternatīvus variantus un izvēlēties visātrāko. Autora metode var lieliski noderēt. Ja neuzticas intuīcijai vai arī grib stingru pamatu, kas ietver autora pieredzi, tad formālie noteikumi būs noderīgi. Formālie noteikumi, kuri doti šajā nodaļā un kurus autors noformulējis speciāli šai grāmatai, ir paredzēti lai apstrādātu visu reālo vaicājumu diapazonu ar saprātīgu kompromisu starp matemātisko precizitāti un ērtībām. Tikai apjomīgi aprēķini „pa tiešo” var tikt galā ar tik sarežģītu uzdevumu, nepielietojot kļūdu un izmēģinājumu metodi, taču šie noteikumi piedāvā izmantot kaut kādu automātisku intuīciju, kura ir tik pat laba, bet varbūt pat vēl labāka par autora „slinko” pieeju.

39

3. Vaicājumi ar attēlojumiem

Izmantojot attēlojumus var izdarīt tā, ka ļoti sarežģīts vaicājums izskatītos kā vienkārša tabula no tā cilvēka puses, kurš raksta vaicājumu izmantojot attēlojumus. Kad vairums vaicājumu izmanto lielu skaiti bāzes SQL-kodu, tad daudzkārtējās izmantošanas vispārēji attēlojumi var kļūt par spēcīgu mehānismu pielikuma koda vienkāršošanai. Par nožēlošanu, vienkārša darbību slēpšana no pielikuma izstrādātāja nemazina šo darbību komplicētību, kas paredzēti faktisko datu iegūšanai. No otras puses, komplicētības slēpšana no izstrādātāja ar lielu varbūtību sarežģīs regulēšanas problēmu, kuru optimizatoram nāksies pārvarēt meklējot ātrāko izpildes plānu. Šajā nodaļā tiks pieminēti divu veidu vaicājumi, kas ir nozīmīgi regulēšanai.

1. Vaicājumi, kuri nosaka attēlojumus.Tie ir vaicājumi, kas atrodas attēlojumu pamatā (t.i. vaicājumi, kuri tiek izmantoti attēlojumu veidošanai ar CREATE VIEW < Attēlojuma_nosaukums > AS <Attēlojumu_noteicošais_vaicājums>).

2. Vaicājumi, kuri izmanto attēlojumus.Tie ir vaicājumi, kurus var regulēt un kurus datu bāze faktiski izpilda. Šajos vaicājumos attēlojumi tiek pieminēti frāzē FROM (piemēram, SELECT … FROM View1 V1, View2 V2, … WHERE …).

Pie SQL regulēšanas attēlojumi parasti sagādā grūtības trijos aspektos.■ Nepieciešams pārveidot vaicājumus, kuri izmanto attēlojumus, ekvivalentos vaicājumos pret reālām tabulām, lai veidotu un optimizētu savienojumu diagrammas.■ Vaicājumi attēlojumiem parasti satur nevajadzīgus un liekus mezglus vaicājuma skeletā. Katrs attēlojums atnes sev līdzi arī visu to nosakošo vaicājumu, kopā ar apakškoku, kas ietver visus attēlojumu nosakošos mezglus un savienojumus. Attēlojuma izmantošana nosaka arī pilna apakškoka izmantošanu. Taču izstrādātājam, kurš pielieto attēlojumu, bieži vien ir vajadzīgi tikai pāris stabiņi no attēlojuma, un viņš vaicājumā varētu izlaist atsevišķus mezglus un savienojumus, kuri nosaka attēlojumu, veidojot ekvivalentus vaicājumus pie vienkāršām tabulām. Kad pielikumam nepieciešami visi attēlojuma mezgli, vaicājums, kurš izmanto attēlojumu, tomēr var pārmērīgi bieži vērsties pie šiem mezgliem, pievienojot to pašu galveno tabulu tās pašas rindas dažādos slēptos kontekstos. Šāds piemērs tiks sniegts nodaļā „Liekie nolasījumi vaicājumos, kuri izmanto attēlojumus”.■ Reizēm vaicājumus, kas izmanto attēlojumus, nav iespējams izteikt vienkārši kā ekvivalentus vaicājumus pie parastām tabulām. Parasti gadījumi, kad attēlojumu izmantojošs vaicājums atgriež dažādus rezultātus no vaicājuma pie vienkāršas tabulas, ir slēpti un rodas reti. Taču pareizie rezultāti šajos slēptajos gadījumos – tie nav tie rezultāti, kādus saņem attēlojumu izmantojošs vaicājums! Ja vaicājumu, kas izmanto attēlojumus, nevar viegli sadalīt ekvivalentā vienkāršā vaicājumā pie tabulām, visbiežāk no tā cieš veiktspēja, bet slēptie gadījumi, kuri nosaka uzvedību, kas attiecas tieši uz attēlojumiem, satur kļūdas. Taču, veiktspējas uzlabošana ar praktiski ekvivalentu vienkāršu vaicājumu pie tabulām nedrīkst novest pat pie nelielām funkcionalitātes izmaiņām, un ir ļoti jāuzmanās, lai neienestu kļūdu. Šis gadījums tiks ilustrēts nodaļā „Ārējie savienojumu ar attēlojumiem”.

40

UZMANĪBU-------------------------------------------------------------------------------------------Autors ir bieži lūgts noregulēt vai noteikt veiktspēju vaicājumam, kas nosaka attēlojumu, neizsniedzot sarakstu visiem vaicājumiem, kuri izmanto šo attēlojumu. Tāpat ir lūgts noregulēt vaicājumus, kuri izmanto attēlojumus, neparādot vaicājumu, kas nosaka attēlojumu. Abi šie lūgumi nav izpildāmi. Lieta tāda, ka neviens nosakošs attēlojumu vaicājums, nedaudz sarežģītāks kā SELECT <Parastu_stabiņu_saraksts> FROM <Viena_tabula>, nevar labi izpildīties visos iespējamos vaicājumos, kas izmanto attēlojumu. Un neviens izmantojošs attēlojumu vaicājums nevarēs labi izpildīties, ja vaicājumā, kas nosaka attēlojumu, netiek izmantots efektīvs ceļš pēc nepieciešamajiem datiem.Šim attēlojumam ir jāzina un jānoregulē visi vaicājumi, kas izmanto attēlojumu, lai būtu pārliecība, ka nosakošais attēlojumu vaicājums ir absolūti pareizs attiecīgajā kontekstā. Ir nepieciešams zināt vaicājumu, kas nosaka attēlojumu, priekš visiem izmantotajiem attēlojumiem, lai būtu pārliecība, ka attēlojumu izmantojošs vaicājums ir pareizs.

3.1. Vaicājumu, kuri izmanto attēlojumus, diagrammu attēlošana

Attēlojumus izmantojošu vaicājumu diagrammu attēlošana ir samērā vienkārša, kaut gan reizēm var būt nogurdinoša.

1. Jāizveido diagrammu visiem nosakošiem attēlojumu vaicājumiem tā, it kā tie būtu atsevišķi vaicājumi. Visām vaicājumu, kas nosaka attēlojumu, diagrammām ir jābūt normālām tādā nozīmē, ka tām ir jābūt vienai sakņu detaļu tabulai un tikai uz leju norādošam savienojumam „daudzi pret vienu” no šī augšējā mezgla, atbilstošam koka struktūrai. Ja nosakošais attēlojumu vaicājums neatspoguļojas uz normāla vaicājuma skeleta, tad vaicājumi, kuri izmanto šo attēlojumu, iespējams slikti strādās un atgriezīs nepareizus rezultātus. Ir jāuzskata vaicājuma, kas nosaka attēlojumu, sakņu detaļu tabulas primāro atslēgu par visa attēlojuma virtuālo primāro atslēgu.

2. Jāizveido diagrammu vaicājumam, kas izmanto attēlojumu, uzskatot, ka visi attēlojumi ir tikai vienkāršas tabulas. Savienojumam ar attēlojumu ir jābūt bultiņai galā, kas atbilst attēlojumam (un jums jānovieto attēlojums saites apakšējā galā), tikai ja savienojums tiek veikts ar attēlojuma virtuālo primāro atslēgu. Simboliski jānorāda attēlojuma filtrācijas nosacījumus vaicājumā, kas izmanto attēlojumu, burta F veidā, pagaidām nedomājot par filtrācijas koeficienta aprēķināšanu. Jāapvelk ar punktētu aploci katru mezglu.

3. Jāpārveido diagrammu vaicājumam, kas izmanto attēlojumu, izveidotu solī 2, nomainot visus mezglus, atbilstošus attēlojumiem, ar pilnu diagrammu vaicājumam, kas nosaka attēlojumu, no soļa 1. Pēc tam jāapvelk ar punktotu līniju apakškoku vaicājumam, nosakošam attēlojumu. Jebkurš savienojums no augšas tiks pievienots pie attēlojumu nosakoša apakškoka kā tā sakņu detaļu tabula. Savienojumi, kas iet no attēlojuma uz leju, var sākties no jebkura attēlojuma mezgla, atkarībā no tā, kura no vaicājuma, nosakošam attēlojumu, tabulām satur savienojuma ārējo atslēgu (sarakstā SELECT, nosakošam attēlojumu). Jebkurš attēlojuma filtrācijas nosacījums kļūst par filtrējošo nosacījumu attiecīgam vaicājuma, nosakošam attēlojumu, mezglam, atkarībā no tā, uz kura mezgla stabiņu darbojas šis nosacījums. Jāatrod faktisko filtrācijas koeficientu visiem līdzīgiem gadījumiem parastā veidā (papildinot simbolu F sākuma vaicājumu diagrammā). Ja nepieciešams, jākombinē filtrācijas koeficientus no nosakošajiem

41

un izmantojošiem attēlojumu vaicājumiem, ja šie vaicājumi uzliek dažādus filtrus uz vieniem un tiem pašiem mezgliem.

Iespējams, ka šie noteikumi izliekas par abstraktiem un sarežģītiem, taču dotajam piemēram vajadzētu apskaidrot procesu.

Tiek paņemti divi attēlojuma noteikšanas veidi:CREATE VIEW Shipment_V ASSELECT A.Address_ID Shipment_ Address_ID. A. Street_Addr_Line1

Shipment_ Street_Address_Line1. A. Street_Addr_Line2Shipment_ Street_Address_Line2. A.City_Name Shipment_City_Name.A.State_Abbreviation Shipment_State. A.ZIP_Code Shipment_ZIP.S. Shipment_Date. S. Shipment_ID

R\FROM Shipments S. Addresses AWHERE S. Address_ID = A. Address_ID

CREATE VIEW Recent_Order_V ASSELECT O.Order_ID. O.Order_Date. O.Customer_ID.

C.Phone_Number Customer_Main_Phone. C.First_Name Customer_First_Name.C.Last_Name Customer_Last_NameC.Address_ID Customer_Address_ID. OT.Text Order_Status

FROM Orders O. Customers C. Code_Translations OTWHERE O. Customer_ID = C. Customer_ID

AND O.Status_Code = OT.CodeAND OT. Code_Type = 'ORDER_STATUS'AND O.Order_Date > SYSDATE - 366

Solis 1 prasa izveidot diagrammas abiem nosakošiem attēlojumu vaicājumiem, kā parādīts 33.att. Šo diagrammu izveidošanai izmanto metodi, aprakstītu 5.nodaļā, un izmanto to pašu statistiku filtrācijas un savienojuma koeficientiem, kādu izmantoja arī attiecīgajam piemēram, parādītam 5.5.att.

Vaicājums, kas nosaka Vaicājums, kas nosakaattēlojumu, Shipment_V attēlojumu, Order_V

33.att. Vaicājumu diagrammas attēlu nosakošam vaicājumam

Lūk, šādi izskatās vaicājums, izmantojošs attēlojumu:SELECT OV.Customer_Main_Phone. C.Honorific. OV. Customer_First_Name.

OV.Customer_Last_Name. C.Suffix. OV. Customer_Address_ID.SV.Shipment_Address_ID. SV. Shipment_Street_Adress_Line1.SV.Shipment_ Street_Adress_Line2. SV. Shipment_City_Name.SV.Shipment_State. SV.Shipment_Zip. OD.Deferred_ Shipment_Date.OD.Item_Count. ODT.Text. P.Product_Description. SV. Shipment_Date

FROM Recent_Order_V OV. Order_Details OD. Products P. Shipment_V SV.Code_Translations ODT. Customers C

WHERE UPPER(OV.Customer_Last_Name) LIKE : last_name Ι Ι '%'AND UPPER(OV.Customer_First_Name) LIKE : first_name Ι Ι '%'AND OD.Order_ID = OV.Order_ID

42

AND OV.Customer_ID = C.Customer_IDAND OD.Product_ID = P. Product_ID(+)AND OD. Shipment_ID = SV. Shipment_ID(+)AND OD.Status_Code = ODT.CodeAND ODT. Code_Type = 'ORDER_DETAIL_STATUS'

ORDER BY OV. Customer_ID. OV.Order_ID Desc. SV.Shipment_ID. OD.Order_Detail_ID

Pārejot pie soļa 2, tiks izveidota vaicājuma sākuma diagrammu tā, it kā attēlojumi būtu vienkāršas tabulas, kā parādīts 34.att.34.att. visi redzamie attēlojumu mezgli tiks nomainīti ar vaicājumu diagrammām, kas nosaka attēlojumus, no 33.att. Bet šo vaicājumu skeletus apvilks ar punktotu līkni, lai apzīmētu attēlojumu robežas. Pievienos attēlojumu nosakošu vaicājumu skeletus pie pilnas vaicājuma diagrammas atlikušās daļas pie piemērotiem mezgliem, atkarībā no tā, kāda tabula no attēlojuma nosacījuma satur savienojuma atslēgu. Parasti jebkādi savienojumi ar attēlojumiem no augšas ir saistīti ar nosakošu attēlojumu vaicājuma sakņu detaļu tabulu. Taču mezgli, attēlojoši galvenās tabulas, kas atrodas zem attēlojuma (piemēram, mezgls C uz 34.att.), var būt pievienoti pie jebkura attēlojumu nosakoša skeleta mezgla, atkarībā no tā, kāda tabula satur ārējo atslēgu, norādošu uz šo galveno mezglu. Pieliks atklātus skaitliskos filtrācijas koeficientus pie visiem skeleta mezgliem vaicājumā, kuriem ir filtri – kā vaicājumā, nosakošā attēlojumu, tā arī vaicājumā, to izmantojošā. 34.attēlā filtrācijas koeficients 0,3 blakus mezglam O parādās pateicoties filtram attēlojumu nosakošā vaicājumā, bet filtrācijas koeficients 0,0002 blakus mezglam C – pateicoties nosacījumiem par pircēju vārdu un uzvārdu attēlojumu izmantojošā vaicājumā.

34.att. Nepaplašinātā diagramma vaicājumam, izmantojošam attēlojumu

Rezultātam ir jāizskatās tādam, kāds tas ir 35.att. Tur ir pielikta zvaigznīte pie kreisā mezgla C, lai norādītu uz atšķirību starp mezgliem, kuriem ir vienādi nosaukumi. Un atkal tiek izmantota tā pati statistika filtram pēc pircēja vārda, kādu izmantoja arī līdzīgā piemērā 5.5.attēlā, lai iegūtu filtrācijas koeficientu 0,0002 blakus C attēlojuma labā skeleta iekšienē.

43

35.att. Paplašinātā diagramma vaicājumam, kas izmanto attēlojumuTātad, tika pabeigta diagramma, kura būs vajadzīga pārejai pie faktiskās

regulēšanas vaicājumam, kas izmanto attēlojumu, kam ir nepieciešams noteicējs, vai vajag optimālā plāna iegūšanai izmainīt attēlojumu nosakošu vai attēlojumu izmantojošu vaicājumu.

3.2. Vaicājumu ar attēlojumiem regulēšana

Parasti optimālais izpildes vaicājumiem, kas izmanto attēlojumus, ir plāns, kuru sastāda attiecīgai vaicājuma diagrammai, pie vienkāršām tabulām. Taču parasti vajadzēs atrisināt četras problēmas:■ Dažus savienojumus ar komplicētiem attēlojumiem grūti iedomāties kā parastus savienojumus ar vienkāršām tabulām. Tā, ārējos savienojumus ar attēlojumiem, kuros ir savienojumi vaicājumos, kas nosaka attēlojumus, ir grūti izteikt, izmantojot vienkāršus savienojumus. Šī problēma skar apskatīto piemēru, tāpēc tā tiks apskata precīzāk nākošajā nodaļā „Ārējie savienojumi ar attēlojumiem”.■ Daži attēlojumi izmanto tieši tās pašas rindas no tās pašas tabulas, kādas izmanto arī cita tabula vaicājumā, kas izmanto attēlojumus. Tas rada datu bāzei lieku darbu, kuru vajag novērst. Tas notiek ar mezgliem C* un C, parādītiem 35.attēlā, tāpēc šī problēma tiks izskatīta vēlāk.Attēlojumu priekšrocība no izstrādes vienkāršošanas redzes viedokļa ir tajā apstāklī, ka tie slēpj vaicājumu sarežģītību, taču šī priekšrocība arī palīdz nemanāmi izveidot kodā liekos savienojumus, kuri būtu acīmredzami un pieprasītu lielāku darbu kodēšanai, ja izstrādātāji izmantotu tikai vienkāršās tabulas.■ Mezgli, attēlojumus nosakošo vaicājumu iekšienē, un savienojumi ar tiem bieži izrādās nevajadzīgi lai iegūtu rezultātu, kas nepieciešams vaicājumā, kas izmanto attēlojumus.■ Attēlojumu izmantošana ierobežo iespējas vadīt izpildes plānu. Ja neizmainīs attēlojumu nosakošo vaicājumu, lai uzlabotu izpildes plānu vaicājumam, kas izmanto attēlojumu, tad var netīšām pasliktināt veiktspēju citiem vaicājumiem, kas izmanto to pašu attēlojumu. Vienmēr var izveidot jaunu attēlojumu, tikai viena vaicājuma izmantošanas ērtībai, taču tas ir pretrunā ar attēlojumu priekšrocību par kopēja koda izmantošanu. Vispārīgi ņemot, SQL uzvednes un pārējās izmaiņas vaicājumā, kas izmanto attēlojumus, nevar uzlabot kontroli pār to, kā datu bāze vēršas pie tabulām vaicājumā. Reizēm, lai iegūtu nepieciešamo plānu, nākas izslēgt attēlojumu izmantošanu.

44

3.2.1. Ārējie savienojumi ar attēlojumiemAtgriežoties pie iepriekšējā piemēra, tiks apskatīts, ko tad nozīmē ārējā

savienojuma esamība ar attēlojumu Shipment_V, kas pats par sevi ir iekšējais savienojums starp tabulām Shipments un Addresses. Tā kā datu bāzei ir jāuzskata, ka eksistē reāla tabula ar tieši tādām pašām rindām, kādas atradīs attēlojums, savienojums atklāj iekšēju savienojumu vērtībām Shipment_ID, kuras iekļautas Shipments un norāda uz piegādēm, kurām lauks Address_ID veiksmīgi savienojas ar tabulu Addresses. Ja datu bāze nevar veikt veiksmīgu savienojumu vienlaicīgi gan ar Shipments, gan ar Addresses, tad savienojums ar attēlojumu kļūst pat pilnībā iekšēju (ar abām tabulām), pat ja pirmais savienojums ar Shipments varētu veiksmīgi iziet. Meklējot plānu ar ieliktiem cikliem datu bāze nevar zināt, vai ārējam savienojumam būs atrasts iekšējais gadījums, kamēr nebūs veikts veiksmīgs savienojums ar abām tabulām vaicājumā, nosakošam attēlojumu.

Diemžēl tas viss ir pārāk sarežģīti, lai šādu gadījumu varētu apstrādāt automātiski ģenerēts kods, tāpēc datu bāze var vienkārši atteikties meklēt plānu ar ieliktiem cikliem. Tā vietā datu bāzes serveris saprot, ka nemaz nav tik svarīgi, cik sarežģīta ir vaicājuma pamatā esošā loģika. Šī loģika funkcionāli nevar izdarīt nekādas kļūdas, ja vienkārši saņems visas rindas no vaicājuma, nosakoša attēlojumu, un apstrādā rezultātu kā reālu tabulu. Ārējam savienojumam ar attēlojumu datu bāze parasti izpilda savienojumu ar kārtošanu metodi sapludināšanai vai savienojumu ar hešēšanu ar pagaidu izveidoto tabulu. Tas ir samērā droši funkcionalitātes plānā, taču parasti kļūst par šausmām veiktspējai, izņemot tos gadījumus, kad pats par sevi vaicājums, nosakošais attēlojumu, ir pietiekami ātrs.

UZMANĪBU-------------------------------------------------------------------------------------------Kā pamata noteikums veiktspējas uzlabošanai ir izvairīties no ārējiem savienojumiem ar jebkādiem attēlojumiem, kuri ir sarežģītāki par SELECT<Parasto_stabiņu_saraksts> FROM <Viena_tabula>.

Līdzīgas problēmas rodas visiem savienojuma veidiem ar attēlojumiem, kuros attēlojumu nosakošā vaicājumā ir UNION vai GROUP BY. Taču savienojumi, kuri izriet no šādiem attēlojumiem, kad tajos ir tabula, kuru var izvēlēties ar vaicājuma vadošo tabulu, parasti strādā lieliski.

Atkal tiks apskatīti attēlojumus izmantojoši vaicājumi no iepriekšējās nodaļas. Ja ievietos attēlojumu izmantojošu vaicājumu priekš Shipment_V vaicājumā, lai atrisinātu veiktspējas problēmu ar ārējo savienojumu, tad iespējams, iegūsiet šādu rezultātu:SELECT OV.Customer_Main_Phone. C.Honorific. OV. Customer_First_Name.

OV. Customer_Last_Name. C.Suffix. OV. Customer_Address_ID.A. Address_ID Shipment_ Address_IDA.Street_Addr_Line1 Shipment_Street_Address_Line1.A.Street_Addr_Line2 Shipment_Street_Address_Line2.A.City_Name Shipment_City_Name. A.State_Abbreviation Shipment_State.A.ZIP_Code Shipment_ZIP. OD.Deferred_Ship_Date. OD.Item_Count.ODT>Text. P.Prod_Description. S. Shipment_Date

FROM Recent_Order_V OV. Order_Details OD. Products P. Shipments S.Addresses A. Code_Translations ODT. Customers C

WHERE UPPER(OV.Customer_Last_Name) LIKE :last_nameΙ Ι ' % 'AND UPPER(OV.Customer_First_Name) LIKE :first_nameΙ Ι ' % 'AND OD.Order_ID = OV. Order_IDAND OV.Customer_ID = C.Customer_IDAND OD.Product_ID = P.Product_ID(+)AND OD. Shipment_ID = S. Shipment_ID(+)

45

AND S.Address_ID = A.Address_ID(+)AND OD.Status_Code = ODT.CodeAND ODT.Code_Type = 'ORDER_DETAIL_STATUS'

ORDER BY OV. Customer_ID. OV.Order_ID Desc. S.Shipment_ID. OD.Order_Detail_ID

Diemžēl šis kods neļauj iegūt to pašu rezultātu, kā izejas vaicājums, jo ārējais savienojums ar attēlojumu ir specifisks. Ja ir pilns attēlojums, ieskaitot savienojumu ar Addresses, nevar veiksmīgi savienoties ar Order_Details tad izejas vaicājums daļēji atgriež Shipment_Date vērtību, vienādu ar null. Tādā veidā, ja pārvadājumam (shipment) nav norādīta pieļaujamā, ne vienāda ar null vērtība Address_ID, izejas vaicājums atgriež null priekš Shipment_Date, neskatoties uz to, ka savienojums ar Shipments pats par sevi ir pieļaujams.

Visdrīzāk, šāda uzvedība – tas nav tas pats, kas bija vajadzīgs izstrādātājam, un tajā nav funkcionālās nepieciešamības, tāpēc jaunā forma, visdrīzāk, strādās brīnišķīgi, pat labāk, nekā izejas, šajā retajā gadījumā. Taču jebkāda funkcionalitātes izmaiņa, izdarīta veiktspējas uzlabošanai, ir bīstama. Tātad, pirms ienest izmaiņas, piemēram, veikt aprakstīto sapludināšanu vaicājumam, noteicošam attēlojumu, ar galveno operatoru SQL, ir jāpārliecinās, ka vaicājuma jaunā uzvedība būs pareiza retajiem gadījumiem, un jābrīdina izstrādātājus, ka izmaiņas var novest pie tā, ka testēšana atgriezīs citus rezultātus. Maz ticams, ka tiešām ievajadzēsies apskatīt tieši vaicājuma izejas uzvedību. Taču ja grib izrādīt piesardzību, neskaidrojot, vai izejas uzvedība bija pareiza retajam gadījumam, tad var lieliski emulēt izejas vaicājuma funkcionalitāti ar šādu kodu:SELECT OV.Customer_Main_Phone. C.Honorific. OV. Customer_First_Name.

OV. Customer_Last_Name. C.Suffix. OV. Customer_Address_ID.A. Address_ID Shipment_ Address_IDA.Street_Addr_Line1 Shipment_Street_Address_Line1.A.Street_Addr_Line2 Shipment_Street_Address_Line2.A.City_Name Shipment_City_Name. A.State_Abbreviation Shipment_State.A.ZIP_Code Shipment_ZIP. OD.Deferred_Ship_Date. OD.Item_Count.ODT>Text. P.Prod_Description.DECODE(A.Address_ID. NULL. TO DATE(NULL).

S.Shipment_Date) Shipment_DateFROM Recent_Order_V OV. Order_Details OD. Products P. Shipments S.

Addresses A. Code_Translations ODT. Customers CWHERE UPPER(OV.Customer_Last_Name) LIKE :last_nameΙ Ι ' % '

AND UPPER(OV.Customer_First_Name) LIKE :first_nameΙ Ι ' % 'AND OD.Order_ID = OV. Order_IDAND OV.Customer_ID = C.Customer_IDAND OD.Product_ID = P.Product_ID(+)AND OD. Shipment_ID = S. Shipment_ID(+)AND S.Address_ID = A.Address_ID(+)AND OD.Status_Code = ODT.CodeAND ODT.Code_Type = 'ORDER_DETAIL_STATUS'

ORDER BY OV. Customer_ID. OV.Order_ID Desc.DECODE(A.Address_ID. NULL. TO NUMBER(NULL). S.Shipment_ID

OD.Order_Detail_ID

Šajā vaicājumā ir divas izmaiņas, kuras piespiež vaicājumu atgriezt rezultātu, it kā savienojums ar Shipments izdotu ārējo gadījumu neatkarīgi no tā, vai radīsies ārējais gadījums savienojumā ar Addresses. Bez attēlojuma vaicājums apstrādās savienojumu ar Shipments neatkarīgi no savienojuma ar Addresses. Tomēr izteiksme DECODE saraksta SELECT beigās un ORDER BY saraksta vidū piespiež pirmā savienojuma iekšējo gadījumu

46

emulēt savienojuma ārējo gadījumu (Shipment_Date un Shipment_ID vietā veidojot null), neatkarīgi no tā, vai pie savienojuma ar Addresses būs atrasts ārējais gadījums.

Reizēm tiešām radīsies labi iemesli izmantot attēlojumus vienkāršo tabulu vietā. Visvairāk izplatītais iemesls – nepieciešamība apiet ierobežojumus automātiski ģenerētā SQL-kodā. Funkcionāli var ievajadzēties kaut kāda komplicēta SQL sintakse, kādu SQL ģenerators apstrādāt nevar. Izplatītākais apvedceļš – noslēpt šo komplicētību attēlojumu noteicošā vaicājumā, kuru izveidos ar rokām, un piespiest SQL ģeneratoru uzskatīt attēlojumu par vienkāršu tabulu, noslēpjot no tā visu komplicētību. Šādos gadījumos var neizdoties izvairīties no attēlojumiem, kā, piemēram, iepriekšējos risinājumos. Tad alternatīva pieeja – paplašināt attēlojuma izmantošanu, slēpjot vairāk SQL attēlojuma nosacījumā. Piemēram, tā kā iepriekšējais uzdevums ietvēra ārējo savienojumu ar attēlojumu, tad varētu to atrisināt, ieslēdzot ārējo savienojumu vaicājumā, kas nosaka attēlojumu. Tad Shipment_V vietā tiktu izmantots OrderDetail_V un sekojošu attēlojumu nosakošs vaicājums:CREATE VIEW OrderDetail_V ASSELECT A. Address_ID Shipment_ Address_ID

A.Street_Addr_Line1 Shipment_Street_Address_Line1.A.Street_Addr_Line2 Shipment_Street_Address_Line2.A.City_Name Shipment_City_Name. A.State_Abbreviation Shipment_State.A.ZIP_Code ZIP. S Shipment_Date. S Shipment_ID.OD.Deferred_Ship_Date. OD. Item_Count. OD.Order_ID.OD. Order_Detail_ID. OD.Product_ID. OD.Status_Code

FROM Shipments S. Addresses A. Order_Details ODWHERE OD. Shipment_ID = S.Shipment_ID(+)

AND S.Address_ID = A. Address_ID(+)

Vaicājums, izmantojot paplašināto attēlojumu, kļūst šāds:SELECT OV.Customer_Main_Phone. C.Honorific. OV. Customer_First_Name.

OV. Customer_Last_Name. C.Suffix. OV. Customer_Address_ID.ODV. Shipment_ Address_ID. ODV. Shipment_Street_Address_Line1.ODV. Shipment_Street_Address_Line2. ODV. Shipment_City_Name.ODV. Shipment_State. ODV. Shipment_Zip. ODV. ODV.Deferred_Ship_Date.

FROM Recent_Order_V OV. Order_Detail_V ODV. Products P.Code_Translations ODT. Customers C

WHERE UPPER(OV.Customer_Last_Name) LIKE :last_nameΙ Ι ' % 'AND UPPER(OV.Customer_First_Name) LIKE :first_nameΙ Ι ' % 'AND ODV.Order_ID = OV. Order_IDAND OV.Customer_ID = C.Customer_IDAND ODV.Product_ID = P.Product_ID(+)AND ODV.Status_Code = ODT.CodeAND ODT.Code_Type = 'ORDER_DETAIL_STATUS'

ORDER BY OV. Customer_ID. OV.Order_ID Desc. ODV. Shipment_ID. ODV. Order_Detail_ID

3.2.2. Liekie nolasījumi vaicājumos, izmantojošiem attēlojumusTagad tiks apskatīts savienojuma gadījums ar mezgliem35.attēlā, kas bija atzīmēti ar C* un C. Šie mezgli pārstāv vienu un to pašu tabulu ar vienādiem savienojuma operatoriem, tāpēc jebkāds izpildes plāns, kas ietver abus mezglus, ir ar redundanci. Tas nolasa vienas un tās pašas tabulas rindas un, iespējams, indeksa pierakstus, divas reizes. Otram, nevajadzīgajam nolasījumam jebkurā gadījumā nav jāpieprasa fizisku ievadu – izvadu, tā kā pirmajam nolasījumam, izpildītam mazāk kā milisekundi agrāk, ir jāievieto tabulas vai indeksa bloku kopīgi izmantojamā keša galvgalī. Ja izpildes plāns tiek stipri filtrēts pirms vēršanās pie otra, redundances mezgla, tad loģiskā ievada – izvada papildus operācijas

47

var ignorēt. Taču lieliem vaicājumiem vai vaicājumiem, kuros lielākais vairums rindu filtrējas tikai pēc līdzīgiem nevajadzīgiem nolasījumiem, loģiskā ievada – izvada lieko operāciju izmaksas ir būtiskas.

Ja izstrādātājs sākumā ir izveidojis vaicājumu pie vienkāršām tabulām, tad varbūtība, ka parādīsies šāda tipa kļūdas, ir samērā maza. Lai ieslēgtu nevajadzīgo savienojumu, viņam nāktos noiet no sava savienojuma veidošanas ceļa, un redundance būtu acīmredzama pie koda apskates. Taču ar attēlojumiem šīs kļūdas ir viegli pielaist, turklāt tās būs labi paslēptas.

Kā tikt vaļā no liekā savienojuma ar tabulu Customers? Ir trīs varianti.■ Pielikt jaunus prasītos stabiņus vaicājumam, kas nosaka attēlojumu, sarakstā SELECT, un izmantot tos atsauču uz liekās tabulas rindām vaicājumā, izmantojošam attēlojumu, vietā. Tas ir droši citiem vaicājumiem, kuriem vajag to pašu attēlojumu, jo izmaiņas ietver tikai stabiņu pielikšanu, bet ne attēlojumu nosakošā vaicājuma diagrammas modifikāciju.■ Izslēgt lieko savienojumu no vaicājuma, kas nosaka attēlojumu, un izmantot tikai stabiņus no vienkāršās tabulas mezgla. Tas ir bīstami, ja eksistē citi attēlojumu izmantojoši vaicājumi, kuriem var ievajadzēties attēlojuma izslēgtie stabiņi.■ Novākt attēlojumu no vaicājuma, kas izmanto attēlojumu, nomainot to ar ekvivalentiem, ne redundances savienojumiem ar vienkāršām tabulām.

3.2.3. Liekie mezgli un savienojumiAplūkosim savienojumu ar mezglu OT pēdējā vaicājumā, izmantojošam attēlojumu. Liekas, ka izejas attēlojumu nosakošais vaicājums ietver šo savienojumu ar mērķi atbalstīt vaicājumus, kuri attiecas uz pasūtījuma stāvokli. Taču patiesībā šis vaicājums pat nepiemin pasūtījuma stāvokli, tāpēc jums var rasties jautājums, vai šis mezgls ir vajadzīgs. Ja jūs neesat ievērojis šo nevajadzīgo mezglu, taču varētu to atpazīt, ievērojot izpildes plānā savienojumu ar indeksu pēc šīs tabulas primārās atslēgas, taču bez nolasīšanas no pašas tabulas. Tikai šādi indeksu nolasījumi pa primāro atslēgu indeksiem parasti norāda uz nevajadzīgajiem savienojumiem.

Šādu nevajadzīgo savienojumu izslēgšana būs pietiekami sarežģīta lieta, tāpēc, ka reizēm tiem ir funkcionāli blakus efekti. Tā kā tas ir iekšējais savienojums, tad vismaz ir iespējams, ka pat bez filtra šim mezglam, pats savienojums atmet rindas, kuras vaicājumam nav jāatgriež. To var izdarīt uz rindu atmešanas rēķina, kur Orders.Status_Code IS NULL vai kur Status_Code norāda uz nepieļaujamiem stāvokļa kodiem, kuriem neeksistē atbilstības tabulā Code_Translations. Pēdējais ir maz iespējams vai to vajag izlabot norādes veseluma atjaunošanas laikā. Taču vienādas ar null ārējās atslēgas ir bieži sastopamas, un ja stabiņa vērtība var būt null, tad jums ir jāizdomājas par atklāta nosacījuma Status_Code IS NOT NULL pievienošanu pirms savienojuma novākšanas, lai emulētu iekšējā savienojuma slēpto filtrējošo funkciju. Lielāka varbūtība ir, ka izstrādātājs, kas pielietoja attēlojumu, pat nepadomāja par attēlojuma slēpto filtrējošo funkciju, un slēptais filtrs ir nevēlama nejaušība. Tāpēc, pirms vaicājumā imitēt iepriekšējo rīcību, vēršoties tikai pie bāzes tabulas bez nevajadzīga savienojuma, ir jāpārbauda, vai iepriekšējā rīcība bija pareiza. Ja izmaiņas nemanāmi izmainīs vaicājuma darbu, pat ja uz labo pusi, ir jābrīdina testētājus, ka šajā gadījumā testēšanas rezultāti var mainīties.

48

4. Vaicājumi ar operācijām uz kopām

Reizēm nākas regulēt kompozītvaicājumus, kuros tiek izmantotas operācijas uz kopām, tādām kā UNION, UNION ALL, INTERSECT un EXCEPT divu vai vairāku vienkāršo vaicājumu rezultātu kombinēšanai. Regulēšanas metodes ar SQL diagrammām paplašināšana uz šiem kompozītvaicājumiem tiek veikta pavisam vienkārši: tiek veidota diagramma un regulēta katra tās daļa neatkarīgi, tā it kā tie būtu atsevišķi vaicājumi. Ja atsevišķās daļas strādā ātri, tad arī rezultātu kombinēšana ar grupu operāciju palīdzību strādā labi.

PIEZĪME-----------------------------------------------------------------------------------------------EXCEPT – tas ir atslēgvārds, aprakstīts standartā ANSI SQL operācijām uz kopām, kas paredzēts lai meklētu atšķirības starp diviem kopumiem. DB2 un SQL Server ievēro standartu, uzturot operatoru EXCEPT. Taču Oracle tās pašās operācijas veikšanai izmanto MINUS, iespējams tādēļ, ka Oracle to uzturēja vēl līdz standarta ieviešanas.

Taču atsevišķas operācijas uz kopām pelna papildus uzmanību. Operācijai UNION, bez daļu kombinēšanas, tās vēl ir jāšķiro un jāatdala dublikāti. Pēdējais solis bieži vien nav vajadzīgs, it īpaši, ja šīs daļas ir tā izstrādātas, lai no pašā sākuma izvairītos no atkārtojumiem. Oracle operāciju UNION var nomainīt ar operāciju UNION ALL, ja jūs atklāsiet, ka dublikātu esamība vai nu ir neiespējama, vai arī tos nav jāaizvāc. Datu bāzēs, kuras neuztur UNION ALL, var izlaist soli, kas paredzēts dublikātu novākšanai, nomainot vienu vaicājumu UNION ar diviem vai vairākiem vienkāršiem vaicājumiem, kombinējot rezultātus pielikuma līmenī, bet ne datu bāzē.

Parasti operāciju INTERSECT var veiksmīgi nomainīt ar apakšvaicājumu EXISTS, kurš meklē piemērotu rindu, kuru izdotu otrā daļa. Piemēram, ja ir divas tabulas Employees, var veikt kopīgi izmantojamu darbinieku pierakstu meklēšanu izmantojot:SELECT Employee_ID FROM Employees1INTERSECTSELECT Employee_ID FROM Employees2

Vaicājumu INTERSECT var vienmēr nomainīt ar šādu konstrukciju:SELECT DISTINCT Employee_IDFROM Employees1 E1WHERE EXISTS (SELECT null

FROM Employees2 E2WHERE E1. Employee_ID = E2. Employee_ID

Izmantojot metodes, aprakstītas nodaļā „Vaicājumi ar apakšvaicājumiem”, var noteikt, vai vajag EXISTS tipa apakšvaicājumu izteikt formā EXISTS vai IN un vai to vajag pārveidot par vienkāršu savienojumu. Ir jāpievērš uzmanību, ka korelācijas savienojuma nosacījumi ļoti paplašinās, ja sarakstā SELECT ir daudz elementu. Tāpat jāpievērš uzmanību tam, ka INTERSECT saskaņā ar stabiņu sarakstu liks vērtības null, ko korelācijas savienojums nedarīs, ja tikai nenorādīs savienojuma nosacījumus speciāli šim mērķim. Piemēram, ja pozitīvai ārējai atslēgai Manager_ID ir atļauta vērtība null (bet Employee_ID vērtība nevar būt null), tad Oracle vaicājuma vietā:SELECT Employee_ID. Manager_ID FROM Employees1INTERSECTSELECT Employee_ID. Manager_ID FROM Employees2

49

var izmantot ekvivalentu vaicājumuSELECT DISTINCT Employee_ID. Manager_IDFROM Employees1 E1WHERE EXISTS (SELECT null

FROM Employees2 E2WHERE E1. Employee_ID = E2. Employee_IDAND NVL(E1.Manager_ID. -1) = NVL(E2.Manager_ID. -1))

Izteiksme NVL( … -1) pie otra korelācijas savienojuma nosacījuma pārveido vērtību null stabiņos, kur tas ir pieļaujams, lai tad, kad vērtība null tiek salīdzināta arī ar null, savienojums tiktu veiksmīgi realizēts.

Operāciju EXCEPT (vai MINUS) parasti veiksmīgi var nomainīt ar NOT EXISTS tipa apakšvaicājumu. Darbinieku pieraksta meklēšanai pirmajā tabulā , bet ne otrajā, var izmantot šādu vaicājumu:SELECT Employee_ID. FROM Employees1MINUSSELECT Employee_ID. FROM Employees2

Taču to vienmēr var nomainīt ar citu vaicājumu:SELECT DISTINCT Employee_ID. FROM Employees1 E1WHERE NOT EXISTS (SELECT null

FROM Employees2 E2WHERE E1. Employee_ID = E2. Employee_ID

Un tad vaicājumu var apstrādāt izmantojot metodes, kas aprakstītas iepriekšējā nodaļā „Vaicājumi ar apakšvaicājumiem”.

5. Vingrinājums

Tālāk ir dots ārkārtīgi sarežģīts vaicājums, kas paredzēts lai pārbaudītu sapratni par vaicājumu ar apakšvaicājumiem regulēšanu. 36.att. ir parādīta daudz komplicētāka un sarežģītāka vaicājumu diagramma, kā jebkura, ar ko var sastapties SQL intensīvas regulēšanas vesela gada laikā. Ja var tikt galā ar šādu diagrammu, tad var atrisināt arī jebkuru scenāriju ar apakšvaicājumiem, ar kādiem varētu nākties sastapties reālajā dzīvē.

PIEZĪME------------------------------------------------------------------------------------------------Ja neizdosies tikt galā ar uzdevumu no pirmās reizes, ir jāatgriežas pie tā vēlreiz pēc papildus prakses un atkārtotas materiāla izpētīšanas.

50

36.att. Komplicēts uzdevums ar vairākiem apakšvaicājumiem

Ir jāatrod iztrūkstošos koeficientus korelācijas savienojumiem. Jāpieņem, ka t = 5 (rindu skaits, ko atgriezis viss vaicājums, ieskaitot apakšvaicājumu NOT EXISTS), bet q = 50 (rindu skaits, ko atgriezis vaicājums, ja no tā aizvāc nosacījumu NOT EXISTS). Jāatrod labāko savienojumu secību, ieskaitot visas tabulas apakšvaicājumā un ārējā vaicājumā.

5.1.1. Risinājums uzdevumam no nodaļasnodaļā ir ietverts viens pietiekami sarežģīts uzdevums, kurš ļauj izmantot lielāko daļu apakšvaicājumu noteikumu. Tālāk ir detalizēts šī uzdevuma atrisinājums soli pa solim. A.9.att. ir parādīti iztrūkstošie koeficienti trim pussavienojumiem un antisavienojumam.

A.9.att. Diagramma no 36.att. ar norādītiem iztrūkstošajiem apakšvaicājuma koeficientiem

51

Risinājums tiks sākts ar iztrūkstošā koeficienta, parādītu A.9.att., aprēķina izskaidrošanu. Lai atrastu prioritātes korelācijas koeficientu pussavienojumam ar D1, vienkārši jāizpilda noteikumus, sniegtus nodaļā, sadaļā „Diagrammu attēlojums apakšvaicājumiem EXISTS”. Pirmajā solī atrod, ka savienojuma ar D1 detaļu koeficients, izejot no 36.att., ir vienāds ar D = 0,8. Tas ir savienojuma „daudzi pret vienu” rets gadījums, kad vienai galvenajai rindai atbilst vidēji mazāk kā viena detaļu rinda. Pieņem, ka M = 1. Tā ir savienojuma galvenā koeficienta parastā vērtība gadījumam, kad tas nav atklāti parādīts uz diagrammas. Labākais filtrācijas koeficients starp mezgliem šajā apakšvaicājumā (D1, S1 un S2) vienāds ar 0,3 priekš D1, tāpēc S = 0,3. Labākais filtrācijas koeficients starp ārējā vaicājuma mezgliem (M, A1, A2, B1 un B2) vienāds ar 0,2 priekš A1, tāpēc R = 0,2. Noteikuma otrajā solī atrod D x S = 0,24, bet M x R = 0,2, tāpēc D x S > M x R. Tātad ir jāpāriet uz soli 3. Atrod, ka S > R, tāpēc prioritātes korelācijas koeficientu vienāds ar S/R = 1,5; pieraksta to blakus pussavienojuma E no M pie D1 rādītājam.

Lai atrastu prioritātes korelācijas koeficientu pussavienojumam ar D2, atkārto procesu. Pirmajā solī atrod savienojuma detaļu koeficientu 36.attēlā (D = 10). Pieņem, ka M = 1, parasts savienojuma galvenais koeficients, kad tas atklāti nav norādīts uz diagrammas. Labākais filtrācijas koeficients starp D2 un S3 vienāds ar 0,0005 priekš S3, tāpēc S = 0,0005. Labākais filtrācijas koeficients starp ārējā vaicājuma mezgliem, tāpat kā iepriekš, vienāds ar R = 0,2. Noteikuma otrajā solī atrodam D x S = 0,0005, bet M x R = 0,2, tāpēc D x S < M x R. Tātad aprēķini apstājas uz soļa 2, un prioritātes korelācijas koeficientu vienāds ar (D x S) / (M x R) = 0,025; pieraksta to blakus pie pussavienojuma, E no M, D2 rādītājam.

Lai atrastu prioritātes korelācijas koeficientu pussavienojumam ar D4, atkārto procesu. Pirmajā solī atrod savienojuma detaļu koeficientu 36.attēlā (D = 2). Pieņem, ka M = 1, parasts savienojuma galvenais koeficients, kad tas atklāti nav norādīts uz diagrammas. Labākais filtrācijas koeficients starp D4, S4, S5, S6 un S7 vienāds ar 0,0001 priekš D4, tāpēc S = 0,0001. Labākais filtrācijas koeficients starp ārējā vaicājuma mezgliem, tāpat kā iepriekš, vienāds ar R = 0,2. Noteikuma otrajā solī atrod D x S = 0,002, bet M x R = 0,2, tāpēc D x S < M x R. Tātad aprēķini apstājas pie soļa 2, un prioritātes korelācijas koeficientu vienāds ar (D x S) / (M x R) = 0,01; pieraksta to blakus pie pussavienojuma, E no M, D4 rādītājam.

Tālāk pāriet pie nākošā noteikumu kopuma, lai atrastu apakšvaicājumu precizētos filtrācijas koeficientus. Solis 1 norāda, ka nav vajadzīgs precizētais filtrācijas koeficients priekš D4, tā kā prioritātes korelācijas koeficients mazāks par 1,0 un mazāks par visiem pārējiem prioritātes koeficientiem. Pāriet uz soli 2 priekš D1 (kura prioritātes korelācijas koeficients lielāks par 1,0) un D2 (kura prioritātes koeficients ir lielāks par to pašu koeficientu priekš D4). Apakšvaicājumos zem mezgliem D1 un D2 ir filtri, tāpēc katram no tiem pāriet pie soļa 3. Priekš D1 atrod D = 0,8 un s = 0,3, tas ir s vērtība ir vienāda ar pašu filtrācijas koeficientu priekš D1. Pie soļa 4 atzīmē, ka D<1, tāpēc apakšvaicājuma precizētais filtrācijas koeficients vienāds ar s x D = 0,24, un to pieraksta blakus skaitlim 0,8 pie pussavienojuma ar D1 augšējā gala.

Pie soļa 3 priekš D2 atrod, ka D = 10 un s = 0,5, s vērtība ir vienāda ar pašu filtrācijas koeficientu priekš D2. Pie soļa 4 atzīmē, ka D>1, tāpēc pāriet pie soļa 5. Ir jāpievērš uzmanību tam, ka s x D = 5, kas ir lielāks par 1,0, tāpēc pāriet pie soļa 6. Lai

52

apakšvaicājuma precizētais filtrācijas koeficients vienāds ar 0,99, un pieraksta to blakus skaitlim 10 pie pussavienojuma ar D2 augšējā gala.

Tagad vienīgais iztrūkstošais koeficients ir apakšvaicājuma precizētais filtrācijas koeficients antisavienojumam ar D3. Sekojot antisavienojuma noteikumiem, pie soļa 1 atrod, ka t = 5 un q = 50 apskatāmajam operatoram. Pie soļa 2 atzīmē, ka šajā apakšvaicājumā ir tikai viens mezgls (kā tas bieži mēdz būt ar nosacījumu NOT EXISTS), tāpēc C = 1, un aprēķin (C – 1 + (t/q))/C = (1 – 1 + (5/50))/1 = 0,1.

Tagad pievēršas pie apakšvaicājumu regulēšanas noteikumiem, ar pilnu vaicājuma diagrammu. Saskaņā ar soli 1, pārliecinās, ka antisavienojums ar D3 ir izteikts kā korelācijas apakšvaicājums NOT EXISTS, bet ne kā korelācijas apakšvaicājums NOT IN. Solis 2 netiek pielietots, jo nav pussavienojumu (ar nosacījumiem EXISTS), kuriem bultiņas rādītāji saites vidū norāda uz leju. Izpildot soli 3, atrod vismazāko prioritātes korelācijas koeficientu – 0,01 pussavienojumam ar D4, tāpēc šo nosacījums ir jāizsaka kā nekorelētu apakšvaicājumu IN un jāpārliecinās, ka pārējie EXISTS tipa nosacījumi ir izteikti kā atklāti EXISTS nosacījumi korelētiem apakšvaicājumiem. Optimizējot apakšvaicājumu uz, it kā tas būtu atsevišķs vaicājums, sekojot vienkāršo vaicājumu noteikumiem, atrod, ka sākotnējā savienojuma secība ir (D4, S4, S6, S5, S7). Sākot ar šo brīdi, datu bāzei ir jāizpilda unikālas kārtošanas operācija pēc ārējās atslēgas D4, kas norāda uz M šajā pussavienojumā. Ieliktie cikli pāries pie M pēc indeksa pēc primārās atslēgas M. Optimizējiet vaicājumu, sākot no M, it kā apakšvaicājuma nosacījumi priekš D4 neeksistētu.

Solis 4 netiek pielietots, jo sāka ar apakšvaicājumu ar nosacījumu IN. Solis 5 ir jāizpilda, jo mezglā M atrod pārējos trīs savienojumus ar apakšvaicājumiem. Pussavienojums ar D1 uzvedas kā mezgls no apakšas ar filtrācijas koeficientu 0,24 – nedaudz sliktāk kā A1, taču labāk kā A2. Pussavienojums ar D2 uzvedas kā mezgls apakšā ar filtrācijas koeficientu 0,99, nedaudz labāk nekā savienojums uz leju ar nefiltrētu mezglu, bet ne tik labi, kā savienojums ar A1 vai A2. Antisavienojums ar D3 izskatās labāk par visiem pārējiem, tāpat kā daudzi selektīvie antisavienojumi, jo uzvedas kā mezgls lejā ar filtrācijas koeficientu 0,1 – labāk nekā pārējiem.

Tādā veidā, tālāk izpilda nosacījumu NOT EXISTS priekš D3 un atrod jauno savienojuma secību (D4, S4, S6, S5, S7, M, D3). Tā kā apakšvaicājums ar D3 sastāv no vienas tabulas, atgriežas ārējā vaicājumā un atrod sekojošu labāko starp esošajiem lejā mezgliem – mezglu A1. Tas ļauj izpildīt savienojumu ar B1, taču B1 ir mazāk pievilcīgs, nekā vēl viens iespējamais variants, D1, kura apakšvaicājuma precizētais filtrācijas koeficients ir vienāds ar 0,24, tāpēc tālāk pievieno D1. Sākot šā apakšvaicājuma apstrādi, nepieciešams to pabeigt, sekojot vienkārša apakšvaicājuma parastiem optimizācijas noteikumiem, un sākot no D1 kā no vadošā mezgla.

Tagad par pieļaujamajiem kļūst mezgli A2, B1 un D2, kurus vislabāk pievienot tieši šādā secībā, par ko rāda to filtrācijas koeficienti vai (priekš D2) apakšvaicājuma precizētais filtrācijas koeficients. Pēc savienojuma ar A2 parādās jauns pieļaujamais mezgls, B2, taču tā filtrācijas koeficients vienāds ar 1,0 un tas nav tik pievilcīgs, kā pārējie. Tātad, pievieno A2, B1 un D2 norādītajā secībā, iegūstot savienojuma secību (D4, S4, S6, S5, S7, M, D3, A1, D1, S1, S2, A2, B1, D2). Sasniedzot D2, ir nepieciešams pabeigt šo apakšvaicājumu, izpildot savienojumu ar S3. Pēc tā ir atlicis tikai pievienot mezglu B2 un iegūt pilnu savienojuma secību kā (D4, S4, S6, S5, S7, M, D3, A1, D1, S1, S2, A2, B1, D2, S3, B2).

53