You are on page 1of 59

IDZ DO

PRZYKADOWY ROZDZIA
SPIS TRECI

KATALOG KSIEK
KATALOG ONLINE
ZAMW DRUKOWANY KATALOG

SQL. Optymalizacja
Autor: Dan Tow
Tumaczenie: Marek Paczyski (rozdz. 1 ; 6, dod. C),
Tomasz Pdziwiatr (rozdz. 7 ; 10, dod. A, B)
ISBN: 83-7361-423-0
Tytu oryginau: SQL Tuning
Format: B5, stron: 348

TWJ KOSZYK
DODAJ DO KOSZYKA

CENNIK I INFORMACJE
ZAMW INFORMACJE
O NOWOCIACH
ZAMW CENNIK

CZYTELNIA
FRAGMENTY KSIEK ONLINE

Wydawnictwo Helion
ul. Chopina 6
44-100 Gliwice
tel. (32)230-98-63
e-mail: helion@helion.pl

Instrukcje SQL s kluczowymi elementami typowych aplikacji bazodanowych, a wic


efektywno ich wykonywania decyduje w gwnym stopniu o wydajnoci samych
aplikacji. Twrcy aplikacji bazodanowych i administratorzy baz danych czsto spdzaj
dugie godziny w celu upewnienia si, e dostp do danych istotnie odbywa si po
najszybszych ciekach, czyli e plany wykonywania wyrae SQL s optymalne.
Wie si z tym midzy innymi rozwaanie wzajemnego zwizku midzy struktur
wyrae SQL a planami ich wykonywania.
ka ta powicona jest jednemu z kluczowych aspektw tego zwizku, czsto
niedocenianemu, aczkolwiek niezmiernie istotnemu wyborowi odpowiedniego planu
wykorzystywanego przez okrelone zapytanie. Autor prezentuje matematyczn metod
optymalizacji wyrae SQL, opierajc si na dobrze zdefiniowanym algorytmie
postpowania i prowadzc do znajdowania optymalnych (lub niemal optymalnych)
planw wykonania dla okrelonych wyrae; jest to naprawd atrakcyjna alternatywa
dla poszukiwa metod prb i bdw, rzadko dajc optymalne rezultaty. Czytelnik
znajdzie w niniejszej ksice opis wielu szczegowych zagadnie zwizanych
z optymalizacj wyrae SQL i baz danych w oglnoci, midzy innymi takich jak:
Buforowanie danych i zarzdzanie tabelami
Indeksowanie, implementowanie indeksw i zwizane z tym koszty
Filtrowanie zawartoci tabel i jego zwizek z indeksowaniem
Zczenia tabel i metody ich realizacji
Analiza planw wykonywania zapyta i zarzdzanie tymi planami
w bazach danych Oracle, MS SQL Server i DB2
Sporzdzanie diagramw zapyta i wykorzystywanie ich do celw optymalizacji
zoonych zapyta oraz do wyznaczania najlepszych planw wykonywania
Specjalne metody optymalizacji szczeglnych przypadkw, w ktrych
standardowe postpowanie okazuje si niewystarczajce: buforowanie
wielokrotnie wydawanych zapyta, czenie i upodobnianie zapyta itp.
Treci poszczeglnych rozdziaw towarzysz wiczenia kontrolne, a cao wieczy
prezentacja zastosowania opisywanych koncepcji w (kompletnie opisanym) procesie
optymalizowania konkretnej aplikacji.

Spis treci
Przedmowa .......................................................................................................................9
Wstp ...............................................................................................................................11
Rozdzia 1. Wprowadzenie ..........................................................................................17
Po co optymalizowa zapytania SQL? ...............................................................................................18
Kto powinien zaj si optymalizacj?...............................................................................................20
Dlaczego ksika ta moe by pomocna?..........................................................................................21
Dodatek ...................................................................................................................................................23
Gotowe rozwizania..............................................................................................................................24

Rozdzia 2. Podstawowe informacje o dostpie do danych ..................................25


Buforowanie danych .............................................................................................................................26
Tabele.......................................................................................................................................................29
Indeksy ....................................................................................................................................................32
Rzadziej wykorzystywane obiekty baz danych................................................................................36
cieki dostpu do pojedynczych tabel .............................................................................................40
Wyznaczanie selektywnoci.................................................................................................................48
Zczenia .................................................................................................................................................58

Rozdzia 3. Przegldanie i interpretacja planw wykonania zapyta...............67


Analiza planu wykonania zapytania bazy danych Oracle .............................................................68
Analiza planu wykonania zapytania bazy danych DB2 .................................................................79
Analiza planu wykonania zapytania bazy danych SQL Server.....................................................92

Spis treci

Rozdzia 4. Zarzdzanie planami wykonania zapyta .......................................101


Uniwersalne techniki zarzdzania planem wykonania zapytania ..............................................101
Zarzdzanie planami wykonania zapyta w bazach danych Oracle..........................................114
Zarzdzanie planami wykonania zapyta w bazach danych DB2..............................................130
Zarzdzanie planami wykonywania zapyta w bazach danych SQL Server ...........................136

Rozdzia 5. Sporzdzanie diagramw prostych zapyta.....................................143


Po co stosowa now metod? ..........................................................................................................143
Pene diagramy zapyta .....................................................................................................................145
Interpretacja diagramw zapyta .....................................................................................................164
Uproszczone diagramy zapyta........................................................................................................166
wiczenia..............................................................................................................................................169

Rozdzia 6. Wyznaczanie najlepszych planw wykonania zapyta.................173


Efektywne plany wykonania zapyta..............................................................................................174
Standardowa heurystyczna kolejno zczania.............................................................................176
Proste przykady..................................................................................................................................177
Szczeglny przypadek ........................................................................................................................187
Skomplikowany przykad ..................................................................................................................190
Specjalne zasady postpowania dla szczeglnych przypadkw .................................................194
wiczenie ..............................................................................................................................................222

Rozdzia 7. Tworzenie diagramw i optymalizacja zoonych zapyta SQL... 225


Niestandardowe diagramy zcze ..................................................................................................226
Zapytania z podzapytaniami.............................................................................................................254
Zapytania z widokami ........................................................................................................................267
Zapytania z operacjami na zbiorach.................................................................................................277
wiczenie ..............................................................................................................................................279

Rozdzia 8. Dlaczego metoda diagramw dziaa? ................................................281


Argumenty przemawiajce za zagniedonymi ptlami..............................................................281
Wybieranie tabeli rdowej ..............................................................................................................283
Wybieranie kolejnej tabeli zczenia.................................................................................................287
Podsumowanie.....................................................................................................................................291

Rozdzia 9. Przypadki szczeglne ............................................................................293


Zczenia zewntrzne..........................................................................................................................293
Zczenie scalajce i indeksy filtrw.................................................................................................299
Brakujce indeksy ................................................................................................................................302

Spis treci

Zczenia bez filtrw ...........................................................................................................................303


Problemy bez rozwizania .................................................................................................................304

Rozdzia 10. Rozwizania dla pozornie nierozwizywalnych problemw .....307


Gdy bardzo szybko jest zbyt wolno .................................................................................................307
Zapytania zwracajce dane ze zbyt wielu wierszy ........................................................................312
Zoptymalizowane zapytanie wolno zwracajce jedynie kilka wierszy......................................324

Dodatek A Rozwizania wicze.............................................................................329


Rozwizania do rozdziau 5...............................................................................................................329
Rozwizania do rozdziau 6...............................................................................................................333
Rozwizania do rozdziau 7...............................................................................................................339

Dodatek B Peny proces..............................................................................................343


Uproszczenie zapytania do postaci diagramu ................................................................................343
Rozwizywanie diagramu zapytania ...............................................................................................347
Sprawdzanie planu wykonania.........................................................................................................349
Zmiana bazy danych ...........................................................................................................................352
Zmiana regu optymalizacji ...............................................................................................................353
Zmiana aplikacji...................................................................................................................................353
Spojrzenie na przykad z odpowiedniej perspektywy ..................................................................354

Dodatek C Sownik .....................................................................................................355


Skorowidz .....................................................................................................................367

Tworzenie diagramw
i optymalizacja
zoonych zapyta SQL
Tworzenie diagramw i optymalizacja zoonych zapyta SQL Jak dotd, nauczylimy
si optymalizowa zapytania na rzeczywistych tabelach oraz tworzy dla nich diagramy,
ktre speniaj rne wymagania odnoszce si do normalnych zapyta biznesowych:
Zapytanie przedstawione jest na jednym drzewie.
Drzewo ma jedno rdo, dokadnie jedn tabel bez zcze z jej kluczami
gwnymi. Wszystkie wzy, inne ni wze rdowy, maj pojedyncze,
skierowane ku nim poczenia ze znajdujcymi si powyej wzami
szczegowymi, ale kady wze moe by na szczycie dowolnej iloci
skierowanych ku doowi pocze.
Wszystkie zczenia maj skierowane ku doowi strzaki
(zczenia, ktre s unikalne na jednym z kocw).
Zczenia zewntrzne s niefiltrowane, skierowane ku doowi, kolejne zczenia
znajdujce si poniej s take zewntrzne.
Pytanie, na ktre zapytanie SQL udziela nam odpowiedzi jest w gruncie rzeczy
pytaniem o encj znajdujc si na samej grze (rdo) drzewa lub odnonie
agregacji tej encji.
Pozostae tabele dostarczaj jedynie referencyjnych danych, umieszczonych
w okrelonej strukturze jedynie przez wzgld na normalizacj.
Nazwaem zapytania speniajce powysze warunki zapytaniami prostymi, chocia jak
moglimy si przekona w rozdziale 6., mog one zawiera dowoln ilo zcze, a ich
optymalizacja moe by cakiem trudna, zwaszcza w rzadkich przypadkach wzw
o podobnych wspczynnikach filtrowania lub kiedy istnieje ukryte filtrowanie zcze.

226

Rozdzia 7. Tworzenie diagramw i optymalizacja zoonych zapyta SQL

Zapytania, ktre nie maj tak prostej formy bdziemy nazywa zapytaniami zoonymi.
Jak poka w tym rozdziale, niektre zoone zapytania s wynikiem bdw: w projekcie
bazy danych, aplikacji lub implementacji. Bdy tego typu powoduj, e bardzo atwo
jest utworzy nieprawidowe zapytanie. W tym rozdziale nauczymy si, jak rozpoznawa
anomalie wystpujce w diagramie zapytania, ktre mog by ostrzeeniem o istnieniu
bdu w konstrukcji zapytania. Nauczymy si rwnie, jak naprawi te funkcjonalne lub
zwizane z projektem bdy, przy czym niejednokrotnie zwikszenie wydajnoci bdzie
efektem ubocznym naszych dziaa. Poprawki te przeksztacaj zazwyczaj zapytanie do
prostej formy lub na tyle do niej zblionej, aby mona zastosowa metody przedstawione w ksice wczeniej.
Niektre zoone zapytania wykraczaj poza wszystkie formy, dla ktrych opisywaem
tworzenie diagramw, wykorzystujc podzapytania, widoki lub klauzule, takie jak UNION
i UNION ALL. Takie zoone zapytania maj zazwyczaj du funkcjonalno i s czsto
spotykane, musimy wic znale metod na stworzenie dla nich diagramu oraz na ich
optymalizacj. Cel ten osigniemy poprzez rozwinicie przedstawionych wczeniej metod adekwatnych dla prostych zapyta.

Niestandardowe diagramy zcze


Jeli zapytanie zawiera jedynie proste tabele (nie widoki), bez podzapyta, bez klauzul
operacji grupowych, takich jak UNION, zawsze mona utworzy jaki diagram zapytania
przez stosowanie metod przedstawionych w rozdziale 5. Jednake zdarza si, e diagram
ma pewne cechy, ktre nie pozwalaj na stosowanie opisanego wczeniej, zwykego
szablonu drzewa zcze. Opisz te nieprawidowoci pojedynczo i poka jak sobie
z nimi radzi.
Aby zilustrowa anomalie, przedstawi niecakowite diagramy zcze, w ktrych czci
nie majce znaczenia dla dyskusji s ukryte za szarymi obokami. Skupi to nasz uwag
na t cz, ktra odgrywa decydujc rol, pokae rwnie uniwersalno przykadu.
Jako konwencj przyjm ukrywanie nie majcych znaczenia dla dyskusji czci szkieletu pocze. Liczba szarych pocze i w ogle ich istnienie nie ma znaczenia dla
przykadu, pokazuje jedynie moliwo wykonania dodatkowych zcze w realnych
przypadkach. Sporadycznie wystpowa bd czarne poczenia z ukrytymi czciami
szkieletu zapytania. Poczenia te maj znaczenie dla dyskusji, ale ukryte czci nie.

Cykliczne grafy zcze


Jak poradzi sobie ze zczeniami, ktre nie mapuj si na proste drzewo, ale zawieraj
poczenia tworzce w pewnym miejscu szkieletu ptl? Jest kilka okolicznoci, w ktrych mona napotka tego typu diagram. W nastpnym podrozdziale omwi cztery
przypadki z rnymi rozwizaniami.

Niestandardowe diagramy zcze

227

Teoria grafw jest gazi matematyki opisujc abstrakcyjne twory zwane grafami,
ktre skadaj si z pocze i wzw, takich jak diagramy zapyta wykorzystywane w tej ksice. W teorii grafw, graf cykliczny ma poczenia w formie
zamknitej ptli. W przedstawianych dalej przykadach, a do rysunku 7.8, na
diagramach wystpuj ptle, sprawiajc, e s one diagramami cyklicznymi.

Przypadek 1. Dwie tabele nadrzdne (zczone jeden-do-jednego)


wspdziel tabel szczegow
Rysunek 7.1 ilustruje pierwszy przypadek, w ktrym pojedynczy klucz obcy czy si
z kluczami gwnymi dwch rnych tabel nadrzdnych.

Rysunek 7.1. Przypadek 1. cyklicznego diagramu zapytania

Na podstawie tego przypadku moemy wnioskowa, e SQL moe wyglda w nastpujcy sposb:
SELECT ...
FROM ... T1, ... T2, ... T3, ...
WHERE ... T1.FKey1=T2.PKey2
AND T1.FKey1=T3.PKey3
AND T2.PKey2=T3.PKey3 ...

Nazwaem klucz obcy z tabeli T1, wskazujcy na obie tabele przez FKey1, a klucze gwne
tabeli T2 i T3 odpowiednio przez PKey2 i PKey3. Poniewa wszystkie trzy zczenia
wystpuj jawnie w SQL-u, zczenie cykliczne jest oczywiste, ale naley zwrci
uwag, e dowolne z tych pocze mogoby by nieobecne. W takim przypadku przechodnio (jeli a = b i b = c to a = c) sugerowaaby istnienie tego nieobecnego warunku zczenia. To samo zapytanie moglibymy wwczas przedstawi w jednej z trzech
postaci z rysunku 7.2.
Zwrmy uwag, e w wersji A i B zapytania moemy wnioskowa o istnieniu nieobecnego poczenia z faktu, e poczenia midzy T2 a T3 maj strzaki na obu kocach, co
oznacza zczenie jeden-do-jednego. Wersja C, dla odmiany wyglda jak zwyke drzewo
zcze i mona si nie zorientowa, e ma ono cykliczne zczenia, chyba e zauwaymy, i T1 wykorzystuje ten sam klucz obcy do poczenia z T2 i T3.

228

Rozdzia 7. Tworzenie diagramw i optymalizacja zoonych zapyta SQL

Rysunek 7.2. To samo zapytanie cykliczne, w ktrym brakuje jednego z trzech przechodnich warunkw
zczenia

W przypadku wystpowania tabel jeden-do-jednego, zczenia cykliczne, takie jak na


rysunku 7.1, s czste. Nie s one problemami funkcjonalnymi, chocia ta kwestia pozostaje do rozwaenia przy napotkaniu zczenia jeden-do-jednego. Mona je nawet
postrzega jako dodatkowe moliwoci. Jeli osignlimy wze T1, dobrze jest mie
moliwo wyboru nastpnego wza, czy to T2, czy T3, poniewa kady z nich moe
mie lepszy wspczynnik filtrowania od drugiego lub moe prowadzi do dobrych filtrw lecych niej w drzewie. W przypadku dojcia w porzdku zczenia do T2 lub T3
przed T1, najbardziej uyteczne byoby zczenie jeden-do-jednego z pozostaym wzem (z T2 do T3 lub z T3 do T2). Pozwala to na uzyskanie dostpu do kadego filtra
wykorzystanego w tej drugiej tabeli, przed zczeniem z tabel T1. Bez poziomego poczenia, poczenie T2 z T3 moliwe byoby jedynie poprzez T1, przy prawdopodobnie
wikszym koszcie.
Niektre optymalizatory s wystarczajco sprytne, aby wykorzysta przechodnio do
uzupenienia brakujcego zczenia, a nawet wykorzysta dodatkow swobod w porzdku zczenia. Najbezpieczniej jest jednak jawnie uwzgldni wszystkie trzy warunki
zcze, jeli dwa spord nich wskazuj przez przechodnio na istnienie trzeciego.
Z ca pewnoci trzeba jawnie uwzgldni w SQL-u wszystkie zczenia potrzebne dla
optymalnego planu wykonania.
Istniej szczeglne przypadki, w ktrych dwie tabele zczone jeden-do-jednego, tak jak
T2 i T3, s t sam tabel! W takiej sytuacji, kady wiersz tabeli T1 czy si dwukrotnie
z tym samym wierszem tabeli T2, co jest bardzo nieefektywne. Najbardziej oczywiste
przypadki, w ktrych ta sama tabela wykorzystana jest, poprzez uycie aliasw, dwukrotnie w klauzuli FROM, s jednak mao prawdopodobne. Dzieje si tak wanie dlatego,
e s one zbyt oczywiste, aby pozosta niezauwaonymi. Jednake dwukrotne zczenie
z t sam tabel moe by bardziej subtelne i mona je pomin w przegldzie kodu.
Moe si to zdarzy, gdy synonim lub widok ukrywa prawdziw tosamo tabeli za co
najmniej jednym aliasem zapytania. Tak czy inaczej, najlepiej usun z zapytania zbyteczn
referencj do tabeli i przepisa wszystkie odniesienia kolumn oraz wszystkie zczenia
znajdujce si poniej, tak aby odnosiy si do pozostaego aliasu.

Niestandardowe diagramy zcze

229

Przypadek 2. Kada z nadrzdnych tabel szczegowych ma kopie klucza


obcego wskazujcego na klucz gwny trzeciej tabeli
Rysunek 7.3 przedstawia drugi co do wanoci przypadek zcze cyklicznych, w ktrym identyczne klucze obce tabel T1 i T2 wskazuj na ten sam klucz gwny tabeli T3.

Rysunek 7.3. Zczenie cykliczne sugerujce denormalizacj

Tym razem SQL ma nastpujc posta:


SELECT ...
FROM ... T1, ... T2, ... T3, ...
WHERE T1.FKey1=T2.PKey2
AND T1.FKey2=T3.PKey3
AND T2.FKey2=T3.PKey3 ...

W tym wyraeniu oznaczyem klucze obce wskazujce z T1 do T2 i T3 odpowiednio przez


FKey1 i FKey2. Z przechodnioci wynika, e kolumna klucza obcego T2.FKey2 ma tak
sam warto, co T1.FKey2, poniewa obie cz si z T3.PKey3. Klucze gwne tabel T2
i T3 oznaczyem odpowiednio przez PKey2 i PKey3. Najbardziej prawdopodobnym wytumaczeniem faktu, e T1 i T2 cz si z t sam tabel T3 poprzez jej klucz gwny jest
to, e klucze obce z tabel T1 i T2 s nadmiarowe. W tym scenariuszu, kolumna FKey2 tabeli szczegw T1 denormalizuje dane jej tabeli nadrzdnej. Dane te zawsze pasuj do
wartoci FKey2 w odpowiadajcym wierszu T2.
Ewentualnie wartoci FKey2 powinny pasowa, ale czasem niestety tak nie jest,
poniewa zdenormalizowane dane bardzo czsto nie s zsynchronizowane.

W rozdziale 10. opisano wszystkie za i przeciw denormalizacji w przypadkach takich jak


ten. W skrcie, jeli denormalizacja jest uzasadniona, mona przypuszcza, e dodatkowe poczenie w diagramie zapytania da dostp do lepszego planu wykonania. Jednak
bardziej prawdopodobne jest, e denormalizacja jest bdem, za ktrym id wiksze
koszty i ryzyko z ni zwizane ni spodziewane zyski. Wyeliminowanie denormalizacji
usunoby klucz obcy FKey2 z tabeli T1, a tym samym usunoby take poczenie T1
z T3, sprawiajc, e diagram zapytania staby si drzewem.

230

Rozdzia 7. Tworzenie diagramw i optymalizacja zoonych zapyta SQL

Przypadek 3. Filtr dwuwzowy (nieunikalny na obu kocach)


pomidzy wzami, ktre s ju poczone poprzez normalne zczenia
Rysunek 7.4 pokazuje trzeci przypadek zczenia cyklicznego. Tym razem mamy normalne poczenia ku doowi od T1 do T2 i T3, ale mamy take trzeci, niezwyky warunek
zczenia pomidzy T2 i T3, ktry nie wykorzystuje kluczy gwnych adnej z tabel.

Rysunek 7.4. Zczenie cykliczne z filtrem dwuwzowym


Poniewa aden klucz gwny nie jest wykorzystany przy zczeniu T2 z T3, poczenie pomidzy nimi nie ma strzaki na adnym z kocw.

SQL dla rysunku 7.4 ma posta:


SELECT ...
FROM ... T1, ... T2, ... T3, ...
WHERE ... T1.FKey1=T2.PKey2
AND T1.FKey2=T3.PKey3
AND T2.Kol2<JestJakosPorownywalneZ>T3.Kol3 ...

Jeli na przykad T1 byoby tabel Orders czc si z tabelami Customers T2


i Salespersons T3, zapytanie mogoby zwrci zamwienia, w ktrych klienci s
przypisani do innych regionw ni sprzedawcy odpowiedzialni za zamwienie.
SELECT ...
FROM Orders T1, Customers T2, Salespersons T3
WHERE T1.Customer_ID=T2.Customer_ID
AND T1.Salesperson_ID=T3.Salesperson_ID
AND T2.Region_ID!=T3.Region_ID

W tym przypadku, warunek T2.Region_ID!=T3.Region_ID jest technicznie zczeniem,


ale lepiej postrzega go jako warunek filtrowania, ktrego dziaanie wymaga wierszy
z dwch rnych tabel. Jeli zignorujemy bezstrzakowe poczenie pomidzy T2 i T3,
osigniemy T1 zanim bdziemy mogli zastosowa dwuwzowy filtr na Region_ID.
Jedynymi dozwolonymi porzdkami zcze, ktre unikaj bezporedniego, niestandardowego poczenia pomidzy T2 i T3 s:
(T1, T2, T3)
(T1, T3, T2)

Niestandardowe diagramy zcze

231

(T2, T1, T3)


(T3, T1, T2)

Dowolny porzdek, inny ni powysze cztery (taki jak (T2, T3, T1)), spowodowaby
katastrofalny nawa danych po zczeniu wiele-do-wielu z drug tabel. Byby to niemal iloczyn kartezjaski wierszy tabeli T2 i T3. We wszystkich tych bezpiecznych porzdkach
zcze tabela T1 znajduje si na pierwszym bd drugim miejscu, zanim osigniemy T2
i T3. Te porzdki zcze tworz zatem dwa zwyke zczenia wiele-do-jednego pomidzy szczegow tabel T1 a jej nadrzdnymi tabelami T2 i T3.
Rzadki filtr dwuwzowy nie ma danego dziaania w momencie osignicia pierwszej
z filtrowanych tabel, dopiero potem, po osigniciu drugiej tabeli, odrzuca cz wierszy, tak
jak to czyni zwyky filtr. Z takiej perspektywy, radzenie sobie z tym przypadkiem jest
proste zamy, e filtr nie istnieje (lub nie jest bezporednio dostpny) a do momentu zczenia z jedn z tabel, do ktrych filtr si odnosi. Jednak gdy tylko osigniemy
dowolny koniec dwuwzowego filtra, koniec przeciwny wchodzi w posiadanie lepszego
wspczynnika filtrowania i staje si bardziej atrakcyjny jako nastpny wze do zczenia.
Rysunek 7.5 pokazuje specyficzny przykad z filtrem dwuwzowym, w ktrym uamek
wierszy zwykego zczenia T1 z T2 i T3, ktre speniaj dodatkowo dwuwzowy warunek filtrowania, jest rwny 0,2. W tym przypadku wybralibymy pierwotnie porzdek
zcze niezaleny od istnienia filtru dwuwzowego, uwzgldniajc jedynie zwyke
zczenia. Jednak gdy tylko osigniemy zczenie z tabel T2 lub T3, ta druga jeszcze nie
zczona tabela otrzymuje nowy, znacznie bardziej odpowiedni wspczynnik zczenia
rwny wspczynnikowi pierwotnemu (1,0 dla T2 i 0,5 dla T3) pomnoonemu przez 0,2.

Rysunek 7.5. Filtr dwuwzowy z jawnym wspczynnikiem filtrowania

Przy optymalizacji zapytania przedstawionego na rysunku 7.5 naley postpowa zgodnie


z normaln procedur, ignorujc dwuwzowy filtr pomidzy T2 i T3, oczywicie, a do
momentu osignicia jednej z tych tabel. Tabela wejciowa to T1, po niej naley doda
tabel T4 ze wzgldu na najlepszy zwyky filtr poniej tabeli T1. T3 ma nastpny
w kolejnoci wspczynniki filtrowania rwny 0,5, tak wic wystpi ona po T4 w porzdku zczenia. Mamy teraz wybr pomidzy T2 i T5. Ale poniewa T2, ze wzgldu
na wczeniejsze osignicie T3, ma aktywowany filtr dwuwzowy, jego wspczynnik filtrowania jest rwny 0,2, i to jest on korzystniejszy ni T5. Dlatego czymy go jako nastpny
w kolejnoci. W efekcie mamy najlepszy porzdek zczenia (T1, T4, T3, T2, T5).

232

Rozdzia 7. Tworzenie diagramw i optymalizacja zoonych zapyta SQL

Zczenie z T2 w przytoczonym przykadzie jest zwykym zczeniem wykorzystujcym zagniedone ptle w indeksie na kluczu gwnym tabeli T2, wychodzc
od klucza obcego z T1. Unikajmy zagniedonych ptli w tabeli z filtrem dwuwzowym. Odnoszc si do SQL-a tu przed rysunkiem 7.5, byoby znacznie lepiej
dosign tabeli Customers, wykorzystujc ptle zagniedone przy zczeniu
T1.Customer_ID=T2.Customer_ID ni przy zczeniu dwuwzowym
T2.Region_ID!=T3.Region_ID.

Przypadek 4. Zczenie wieloczciowe z dwch kluczy obcych


jest rozoone na zoone klucze gwne dwch tabel
Na zakoczenie rozwaa na rysunku 7.6 pokazano czwarty przypadek zcze cyklicznych. Wystpuj tu dwa niestandardowe zczenia z T3. adne z nich nie wykorzystuje
caego klucza gwnego tej tabeli ani kluczy gwnych tabel na przeciwnych kocach
tych zcze. Jeli taki przypadek braku poczenia z caym kluczem gwnym na co
najmniej jednym kocu kadego zczenia jest zy, wwczas przypadek 4. jest zazwyczaj takim, w ktrym dwukrotne zo staje si dobrem!

Rysunek 7.6. Zczenie cykliczne z dwoma niestandardowymi zczeniami

W sytuacji, jak zaprezentowano na rysunku 7.6, zapytanie SQL ma posta:


SELECT ...
FROM ... T1, ... T2, ... T3, ...
WHERE ... T1.FKey1=T2.PKey2
AND T1.FKey2=T3.PKeyColumn1
AND T2.FKey3=T3.PKeyColumn2 ...

Taki SQL pojawia si zazwyczaj, kiedy tabela T3 ma dwuczciowy klucz gwny,


a dwuczciowy klucz obcy jest rozoony na dwie tabele w zalenoci tabela nadrzdnatabela szczegowa.
Konkretny przykad wyjani t kwesti. Rozwamy tabele sownikowe oznaczone Tables,
Indexes, Table_Columns i Index_Columns. Moglibymy wybra dwuczciowy klucz
gwny (Table_ID, Column_Number) tabeli Table_Columns, gdzie Column_Number
oznacza miejsce, ktre zajmuje kolumna w naturalnym porzdku kolumn tabeli 1 dla
pierwszej kolumny, 2 dla drugiej i tak dalej. Tabela Indexes miaaby klucz obcy do tabeli
Tables na kolumnie Table_ID, a tabela Index_Columns miaaby dwuczciowy klucz

Niestandardowe diagramy zcze

233

gwny (Index_ID, Column_Number). Warto Column_Number w tabeli Index_Columns


ma to samo znaczenie, co kolumna Column_Number w tabeli Table_Columns miejsce
jakie kolumna zajmuje w naturalnym porzdku kolumn tabeli (nie jej miejsce w porzdku
indeksw, ktra to warto znajduje si w Index_Position). Jeli znalibymy nazw indeksu i chcielibymy znale list nazw kolumn, ktre tworz indeks wedug porzdku
z Index_Position, moglibymy napisa zapytanie:
SELECT TC.Column_Name
FROM Indexes Ind, Index_Columns IC, Table_Columns TC
WHERE Ind.Index_Name='PRACOWNICY_X1'
AND Ind.Index_ID=IC.Index_ID
AND Ind.Table_ID=TC.Table_ID
AND IC.Column_Number=TC.Column_Number
ORDER BY IC.Index_Position ASC

W ramach powtrki, sprbujmy utworzy szkielet diagramu dla tego zapytania.

Jeli warunek na Index_Name miaby wspczynnik filtrowania 0,0002, diagram zapytania pozbawiony pozostaych wspczynnikw wygldaby jak na rysunku 7.7.

Rysunek 7.7. Konkretny przykad czwartego przypadku zcze cyklicznych

W tym przypadku, dwukrotne zo (dwa zczenia, ktre nie cz si z caym kluczem


gwnym po adnej stronie poczenia) czy si, tworzc w efekcie dobro, kiedy
rozpatrujemy zczenia z TC razem, poniewa razem cz si one z penym kluczem
gwnym tej tabeli. Moemy przetworzy diagram tego nietypowego przypadku w sposb widoczny na rysunku 7.8.

Rysunek 7.8. czenie wieloczciowych zcze z kluczy obcych rozdzielonych na dwie tabele

234

Rozdzia 7. Tworzenie diagramw i optymalizacja zoonych zapyta SQL

Jeli przestrzegamy reguy, aby czy do lub z penych kluczy gwnych, najlepszy
porzdek zczenia dla rysunku 7.7 staje si jasny. Wyjdmy z filtru na Ind i podajmy
za poczeniem grnym ku IC. Jest to tak naprawd najlepszy plan wykonania dla tego
przykadu. W przypadkach takich jak ten, naley uwzgldnia niestandardowe zczenia
prowadzce do wieloczciowych kluczy gwnych tylko do momentu, w ktrym baza
danych osignie wszystkie wzy grne niezbdne do uycia penego klucza gwnego.

Podsumowanie zcze cyklicznych


Nastpujca lista podsumowuje metody wykorzystywane przy rozwizywaniu problemw ze zczeniami cyklicznymi:
Przypadek 1. Dwie tabele nadrzdne (zczone jeden-do-jednego) wspdziel tabel szczegow
Mamy tu okazj do optymalizacji, zwikszajc stopie swobody w porzdku zczenia.
Powinnimy jednak rozway take inne rozwizania przedstawione w dalszej czci
tego rozdziau. Pozwalaj nam one dobrze radzi sobie ze zczeniami jeden-do-jednego.
Przypadek 2. Kada z nadrzdnych tabel szczegowych ma kopie klucza obcego wskazujcego
na klucz gwny trzeciej tabeli
Tutaj take mamy moliwo zwikszenia swobody w porzdku zczenia, ale ten
przypadek oznacza denormalizacj, ktra zazwyczaj nie znajduje odpowiedniego
uzasadnienia. Jeli mamy wybr, powinnimy usun denormalizacj, chyba e zysk
w tym lub innych zapytaniach potwierdza jej trafno.
W dotychczas prowadzonych rozwaaniach sugerowaem idealne rozwizania,
przy zaoeniu posiadania cakowitej kontroli nad aplikacj, projektem bazy danych oraz SQL-em. Pokazywaem take kompromisowe rozwizania, ktre maj
zastosowanie w sytuacji, gdy ma si mniejsz kontrol. Jednak czasem, gdy ma si
do czynienia z nieuzasadnion denormalizacj, w przypadku gotowego systemu,
ktrego nie posiadamy czy na ktry nie mamy nawet wpywu, jedynym wyjciem
kompromisowym jest nic nie robi.

Przypadek 3. Filtr dwuwzowy (nieunikalny na obu kocach) pomidzy wzami, ktre s ju


poczone poprzez normalne zczenia
Ten przypadek naley traktowa, jak gdyby nie wystpowa w nim aden filtr a do
momentu osignicia jednego z wzw. Wwczas w poszukiwaniu pozostaej czci
porzdku zczenia, wze w naley traktowa jako majcy lepszy wspczynnik
filtrowania.
Przypadek 4. Zczenie wieloczciowe z dwch kluczy obcych jest rozdzielone na zoone klucze
gwne dwch tabel
Ten przypadek zczenia powinien by wykorzystywany, jedynie gdy posiadamy
obie czci klucza.

Niestandardowe diagramy zcze

235

Rozczone diagramy zapyta


Rysunek 7.9 pokazuje dwa przypadki rozczonych diagramw zapytania: szkielet zapytania, w ktrym nie udao si poczy wszystkich tabel zapytania w pojedyncz,
poczon struktur. W kadym z tych przypadkw mamy w pewnym sensie do czynienia z dwoma niezalenymi zapytaniami, kade z osobnym diagramem zapytania,
ktry mona optymalizowa w oderwaniu od pozostaych diagramw.

Rysunek 7.9. Rozczone diagramy zapyta

W przypadku A przedstawiem zapytanie, ktre skada si z dwch, wygldajcych na niezalene, zapyta kade z wasnymi zczeniami. W przypadku B pokazaem praktycznie
zwyke zapytanie, ktrego jedna z tabel (tabela T2) jest odczona od drzewa zczenia
(tzn. nie jest zczona z adn inn tabel). Kady z tych dwch przypadkw mapuje si
na dwa oddzielne zapytania, ktre s wykonywane w obrbie pojedynczego zapytania.
Co si stanie, jeli poczymy dwa niezalene zapytania w jedno? Kiedy dwie tabele s
poczone w jedno zapytanie bez jakichkolwiek warunkw zczenia, baza danych
zwraca iloczyn kartezjaski kad moliw kombinacj wierszy pierwszej tabeli z wierszami tabeli drugiej. W przypadku rozczonych diagramw, naley myle o wynikach
zapytania reprezentowanego przez kady niezaleny szkielet zapytania (lub izolowany
wze) jako o wirtualnej tabeli. Z tej perspektywy wida, e baza danych zwrci wszystkie
kombinacje wierszy tych dwch niezalenych zapyta. Tak wic w wyniku otrzymamy
iloczyn kartezjaski.
Kiedy spotkamy si z iloczynem kartezjaskim, tak jak pokazano na rysunku 7.9, powinnimy zbada przyczyn jego zaistnienia. Gdy j ju poznamy, bdziemy mogli
zadecydowa, ktre z wymienionych poniej dziaa podj. Bdzie to uzalenione od
tego, z ktrym spord czterech przypadkw mamy do czynienia:
Przypadek 1. W zapytaniu brakuje zczenia, ktre czyoby rozdzielone czci
Doda brakujce zczenie.
Przypadek 2. Zapytanie skada si z dwch niezalenych zapyta, a kade z nich zwraca
wiele wierszy
Wyeliminowa iloczyn kartezjaski poprzez osobne wykonywanie oddzielnych zapyta.

236

Rozdzia 7. Tworzenie diagramw i optymalizacja zoonych zapyta SQL

Przypadek 3. Jedno z niezalenych zapyta jest zapytaniem zwracajcym jeden wiersz


Rozway rozdzielenie zapyta, aby zmniejszy przepyw danych z bazy danych,
szczeglnie jeli jedno z niezalenych zapyta zwraca wiele wierszy. Wykona najpierw zapytanie jednowierszowe.
Przypadek 4. Oba niezalene zapytania s zapytaniami jednowierszowymi
Zachowa zapytania w formie poczonej, chyba e jest to kopotliwe lub trudne
w konserwacji.
Zanim rozdzielimy rozczone zapytanie na dwa niezalene zapytania, rozwamy, czy
programista mg przez nieuwag pozostawi zapytanie bez zczenia. Na pocztku cyklu
tworzenia systemu, najczstsz przyczyn rozczonych diagramw zapyta jest to, i
programici zapominaj doda niektre warunki zczenia, ktre cz dwa rozczone
poddrzewa. W takim przypadku, powinnimy po prostu dooy brakujce zczenie,
dziki czemu pozbdziemy si rozcznych drzew. Za kadym razem, kiedy jedna z tabel w drzewie ma klucz obcy wskazujcy na klucz gwny tabeli rdowej drugiego
drzewa, niemal pewne jest, e brakujce zczenie zostao opuszczone przez przypadek.
Jeli kade niezalene zapytanie zwraca wiele wierszy, liczba kombinacji przekroczy
liczb wierszy, ktre otrzymalibymy w przypadku wykonania obu zapyta oddzielnie. Jednake zbir kombinacji z dwch tabel nie zawiera wicej informacji, ni mona
by uzyska poprzez wykonanie zapyta oddzielnie. Dlatego generowanie nadmiarowych
danych w kombinacji jest po prostu strat czasu, przynajmniej jeli zamierza si
otrzyma czyst informacj. Wobec tego lepsze moe by wykonanie tych dwch zapyta oddzielnie.
Generowanie kombinacji w iloczynie kartezjaskim rzadko bywa w jaki sposb uzasadnione, z perspektywy wygody programowania. Jednake zawsze istniej metody alternatywne,
pozwalajce unikn zbdnych danych, jeli koszt ich uzyskania jest zbyt wysoki.
Jeli rozpatrywa problem tylko pod ktem fizycznych operacji wejcia-wyjcia,
iloczyn kartezjaski nie sprawiaby adnego problemu, poniewa nadmiarowe
odczyty danych z powtrzonych zapyta byyby najprawdopodobniej w peni
buforowane ju po pierwszym odczycie. Syszaem nawet opinie, ktre broniy dugo
wykonujcych si zapyta tego typu, opierajc si o niewielk ilo fizycznych
operacji wejcia-wyjcia. Takie zapytania s dobrym sposobem na spalenie procesora i wygenerowanie ogromnej iloci logicznych operacji wejcia-wyjcia, jeli
kiedykolwiek zaszaby potrzeba przeprowadzenia jakiego testu wytrzymaoci czy innego dowiadczenia. Nie maj one jednak zastosowania w aplikacjach biznesowych.

Jeli jedno z niezalenych zapyta zwraca tylko jeden wiersz, zagwarantowane jest, e
przynajmniej iloczyn kartezjaski jest bezpieczny i e zwrcona liczba wierszy bdzie nie
wiksza ni liczba wierszy zwrconych przez wiksze z niezalenych zapyta. Jednake
istnieje wci niewielki koszt poczenia zapyta. Jest on zwizany z przesyem danych,
poniewa lista SELECT poczonego zapytania moe zwrci dane z mniejszego zapytania

Niestandardowe diagramy zcze

237

wielokrotnie, raz dla kadego wiersza zapytania wielowierszowego. Powoduje to przesy wikszej iloci zbdnych danych ni w przypadku rozdzielenia obu zapyta. Koszt
przesyu jest z drugiej strony kontrowany poprzez oszczdnoci w opnieniach wynikych z przesyu kadego pakietu zapytanie poczone oszczdza cigych odwoa
sieciowych do bazy danych, tak wic najlepszy wybr zaley od szczegw. Jeli nie rozdzielimy zapyta, optymalny plan wykonania jest prosty najpierw naley uruchomi optymalny plan wykonania dla zapytania zwracajcego pojedynczy wiersz. Nastpnie, w ptli zagniedonej, ktra wykonana bdzie tylko raz, trzeba uruchomi optymalny
plan wykonania dla zapytania wielowierszowego. Ten poczony plan wykonania ma
koszt taki sam, jak wykonanie dwch zapyta oddzielnie. Jeli plan zapytania wielowierszowego uruchomimy najpierw, plan ptli zagniedonych bdzie wymaga powtarzania dla kadego zapytania jednowierszowego tylekro razy, ile wierszy zwrcioby
zapytanie wielowierszowe.
Poczenie zapytania jednowierszowego z zapytaniem wielowierszowym jest czasem
wygodne i usprawiedliwione. Istnieje specjalny przypadek, zobrazowany na prawej
powce rysunku 7.9, w ktrym zapytanie jednowierszowe jest po prostu odczytem jedynego wiersza izolowanej tabeli T2 nie majcej adnych zcze. Iloczyn kartezjaski
z izolowan tabel jest czasem uyteczny w pobieraniu parametrw przechowywanych
w jednowierszowej tabeli parametrw, szczeglnie kiedy parametry te wystpuj jedynie
w klauzuli WHERE, a nie w licie SELECT. Kiedy zapytanie zwraca dane z tabeli parametrw, okazuje si, e tasze jest wykonanie odpowiednio poczonego zapytania ni
wykonanie dwch osobnych zapyta.
Z jeszcze rzadszym przypadkiem mamy do czynienia, gdy oba izolowane zapytania
zwracaj pojedynczy wiersz. Z punktu widzenia wydajnoci jest cakowicie uzasadnione
i bezpieczne poczenie takich dwch zapyta. Jest ono pozbawione niebezpieczestw
zwizanych z innymi przypadkami. Jednake z perspektywy programowania i konserwacji oprogramowania, czenia takich zapyta moe by mylce, a oszczdnoci s
raczej niewielkie.

Diagram zapytania z wieloma tabelami rdowymi


Rysunek 7.10 pokazuje przykad diagramu zapytania, ktry nie spenia oczekiwania
odnonie jednego rda. Przypadek ten jest spokrewniony z poprzednim (rozczone
diagramy zapyta). Tutaj, dla kadego wiersza tabeli Master speniajcego warunki zapytania, zapytanie zwrci wszystkie kombinacje odpowiednich szczegw z Root1
i Root2. Majc dane wspczynniki zcze tabeli szczegw, moemy spodziewa si
wszystkich kombinacji 5 szczegw tabeli Root1 i 30 szczegw tabeli Root2, co da
nam 150 kombinacji dla kadego wiersza tabeli Master. Te 150 wierszy kombinacji nie
zawiera wicej danych ni 5 szczegw Root1 w poczeniu z 30 szczegami Root2,
zatem szybciej jest odczyta te 5 i 30 wierszy oddzielnie, unikajc iloczynu kartezjaskiego. Podczas gdy rozczony diagram zapytania tworzy pojedynczy, duy iloczyn
kartezjaski, liczne wzy-rda tworz ca seri mniejszych iloczynw kartezjaskich,
po jednym dla kadego odpowiedniego wiersza tabeli gwnej.

238

Rozdzia 7. Tworzenie diagramw i optymalizacja zoonych zapyta SQL

Rysunek 7.10. Diagram zapytania o wielu tabelach rdowych

Istniej cztery przyczyny wystpienia diagramu zapytania o wielu rdach. Nastpujca lista pokazuje te przyczyny i opisuje odpowiadajce im rozwizania:
Przypadek 1. Brakujcy warunek
W zapytaniu brakuje warunku, ktry zamieniby jedn z tabel rdowych w tabel
gwn oraz zczenie jeden-do-wielu na jeden-do-jednego.
Rozwizanie: doda brakujcy warunek zczenia.
Przypadek 2. Iloczyn kartezjaski wiele-do-wielu
Zapytanie reprezentuje iloczyn kartezjaski wiele-do-wielu na kady wiersz tabeli
gwnej, pomidzy tabelami szczegw dzielcymi wspln tabel gwn. Przypadek
ten ma miejsce, gdy wspczynnik zczenia tabeli szczegw z pojedynczej wspdzielonej tabeli gwnej do dwch rnych tabel rdowych jest wikszy ni 1,0.
Rozwizanie: usun iloczyn kartezjaski poprzez rozdzielenie zapytania na dwa
niezalene zapytania czytajce niezalenie z tabeli rdowej.
Przypadek 3. Wspczynnik zczenia tabeli szczegw jest mniejszy ni 1,0
Jedna ze rdowych tabel szczegowych czy si ze wspdzielon tabel gwn,
przy wspczynniku tabeli szczegowej zczenia mniejszym ni 1,0.
Rozwizanie: chocia nie jest to problem wydajnociowy, naley rozway odseparowanie czci zapytania lub optymalizacj jednej z czci zapytania, tak by staa si
podzapytaniem.
Przypadek 4. Tabela jest uywana jedynie dla sprawdzenia obecnoci
Jedna ze rdowych tabel szczegw nie dostarcza adnych danych potrzebnych
w licie polecenia SELECT i jest wczona do zapytania jedynie dla sprawdzenia
obecnoci.
Rozwizanie: zamieni sprawdzenie obecnoci na podzapytanie.

Przypadek 1. Brakujcy warunek zczenia


Wystpowanie drugiego wza rdowego najczciej wskazuje na brak warunku zczenia, ktry zamieniby jeden ze rdowych wzw w wze gwny. Rysunek 7.11
pokazuje transformacj, w ktrej zczenie z tabeli Master do Root1 zostao zamienione

Niestandardowe diagramy zcze

239

Rysunek 7.11. Naprawianie zapytania z mnogimi wzami rdowymi

na zczenie jeden-do-jednego poprzez dodanie (lub rozpoznanie) dodatkowego warunku na tabeli Root1 (przemianowana na R1), co zapewnio, e baza danych znajdzie co
najmniej jeden wiersz w R1 dla kadego wiersza tabeli Master. Jest to szczeglnie prawdopodobne, jeli R1 zawiera szczegowe dane zwizane z przedziaami czasowymi (jak
np. zmieniajcy si podatek), ktre cz rekord gwny (jak encja podatku) i warunek
na dat (np. danie obecnej stawki podatkowej), tworzc zczenie jeden-do-jednego.
Niejednokrotnie warunek powodujcy, e zczenie staje si jeden-do-jednego, ju istnieje.
Wwczas powinnimy odkry kombinacj zczenia wiele-do-jednego i tego warunku,
ktra to kombinacja zmieni wspczynnik zczenia szczegw.
W przykadzie, w ktrym wspczynnik zczenia tabeli szczegw Root1 by
rwny 5, wspczynnik filtrowania dla takiego filtra byby rwny 0,2, lub inaczej 1/5.

Ewentualnie, warunek, ktry powoduje, e zczenie jest typu jeden-do-jednego moe


nie by uwzgldniony w zapytaniu, szczeglnie jeli rozwj aplikacji odbywa si w systemie testowym, w ktrym relacja jeden-do-wielu bya ukryta ze wzgldu na konkretne dane.
Poprzedni przykad dotyczcy zmieniajcych si stp podatkowych jest tu dobr
ilustracj. W systemie produkcyjnym moe si bowiem okaza, e istniej rekordy
jedynie do obecnej stopy podatku, co ukrywa w ten sposb bd nieuwzgldnienia
warunku na dat na tabeli stp.

240

Rozdzia 7. Tworzenie diagramw i optymalizacja zoonych zapyta SQL

Niezalenie od tego czy brakuje warunku tworzcego zczenie jeden-do-jednego, czy


te nie jest on rozpoznany jako poczony z tym zczeniem, powinnimy wczy ten
warunek i rozpozna go jako cz zczenia, a nie niezaleny warunek zczenia. Taki
brakujcy warunek zczenia jest szczeglnie prawdopodobny, gdy jeden z kluczy obcych
jednej z tabel rdowych wskazuje ku doowi na wspln tabel gwn i jest jednoczenie czci wieloczciowego klucza gwnego tej tabeli rdowej.

Przypadek 2. Rozdzielanie iloczynu kartezjaskiego na wiele zapyta


Rysunek 7.12 wskazuje inne rozwizanie dla problemu diagramw o wielu wzach
rdowych. To rozwizanie jest podobne do tego omwionego wczeniej, dotyczcego
jawnie wykonywanych nie poczonych zapyta, i tutaj rozdzielamy iloczyn kartezjaski i zastpujemy go przez dwa rozczne zbiory. W naszym przykadzie, zapytanie,
ktre zwrcioby 150 wierszy dla kadego wiersza tabeli Master zostao zamienione na
dwa zapytania, zwracajce w poczeniu po 35 wierszy na kady wiersz tabeli Master.
W kadym przypadku wystpienia relacji jeden-do-wielu z tabeli gwnej do dwch
rnych tabel rdowych, moemy otrzyma dokadnie te same dane, przy duo
mniejszej liczbie odczytanych wierszy, za pomoc oddzielnych zapyta, tak jak jest to
widoczne na ilustracji. Poniewa rezultat przyjmuje zmienion form, potrzeba take
zmieni logik aplikacji, ktra obsuguje t now form.

Rysunek 7.12. Rozwizywanie problemu iloczynu kartezjaskiego za pomoc oddzielnych zapyta

Przypadek 3. rdowe tabele szczegw, ktre cz si


zazwyczaj w stosunku nie wicej ni jeden-do-jednego
Rysunek 7.13 pokazuje przypadek wielokrotnych tabel rdowych, w ktrym wydajno
zapytania nie jest problemem nawet w niezmienionej postaci. Poniewa wspczynnik
zczenia tabeli szczegw z Master do Root1 jest rwny 0,5, nie pojawia si kartezjaska

Niestandardowe diagramy zcze

241

Rysunek 7.13. Iloczyn kartezjaski z niskim wspczynnikiem zczenia detali

eksplozja wierszy podczas czenia odpowiednich wierszy tabeli Root1 z Root2, dla
przecitnego rekordu tabeli Master. Mona traktowa Root1, jak gdyby by zczony ku
doowi, faworyzujc go nawet poprzez poprawienie jego wspczynnika filtrowania
przez owo 0,5 (w myl specjalnej reguy z rozdziau 6. dla wspczynnikw zcze tabel
szczegw mniejszych ni 1,0).
Chocia zapytanie to nie stanowi problemu z punktu widzenia optymalizacji, moe ono
by niepoprawne. Zczenie jeden-do-zera lub jeden-do-wielu z tabeli Master do Root1
ma zazwyczaj typ jeden-do-zera lub jeden-do-jednego, co prowadzi do dobrego zachowania iloczynu kartezjaskiego. Jednake jeli zczenie jest zawsze typu jeden-do-wielu,
trzeba wzi pod uwag, e rezultat moe by iloczynem kartezjaskim z powtrzeniami
dla danego wiersza tabeli Root2. Poniewa przypadek ten jest rzadki, mona z duym
prawdopodobiestwem powiedzie, e zapytanie byo zaprojektowane i przetestowane
tak, by zwracao rezultaty, ktre mapuj jeden-do-jednego z wierszami z Root2, a aplikacja moe nawet nie dziaa w innych rzadkich przypadkach.
Im rzadszy jest przypadek jeden-do-wielu, tym bardziej prawdopodobne jest, e
przypadek taki by zupenie zaniedbany w projektowaniu aplikacji.

Na przykad, jeli aplikacja wymieni dane w Root2 po odczytaniu ich za pomoc powyszego zapytania i bdzie prbowaa przesa zmiany z powrotem do bazy danych,
musi ona rozway, ktra kopia powtrzonych wierszy Root2 powinna by zapisana
ponownie do bazy danych. Czy aplikacja powinna ostrzec uytkownika kocowego, e
prbowaa wysa niespjne kopie? Jeli agreguje ona dane tabeli Root2 z zapytania, czy
unika dodawania danych z powtrzonych wierszy tabeli Root2?

Przypadek 4. Zamiana kontroli istnienia na jawne podzapytanie


Jedno z rozwiza funkcjonalnego problemu z rysunku 7.13 pokazane jest na rysunku 7.12
rozczenie zapytania na dwie czci. Innym, zadziwiajco czstym rozwizaniem jest
wyizolowanie gazi z Root1 w podzapytanie, zazwyczaj za pomoc warunku EXISTS.
Rozwizanie to jest szczeglnie atwe w zastosowaniu, jeli oryginalne zapytanie nie
wybierao kolumn z Root1 (lub dowolnej tabeli poczonej poniej niej poprzez ukryte,
szare poczenia na rysunku 7.13). W tym do popularnym, szczeglnym przypadku,

242

Rozdzia 7. Tworzenie diagramw i optymalizacja zoonych zapyta SQL

tak naprawd jestemy zainteresowani tylko tym, czy odpowiedni wiersz z Root1 istnieje i by moe spenia jakie warunki filtrowania. Nie interesuje nas jego zawarto czy
te liczba pasujcych wierszy (poza pierwszym). W dalszej czci rozdziau zobaczymy,
jak tworzy diagram i optymalizowa zapytania z podzapytaniami tego typu.

Zczenia bez kluczy gwnych


Poczenia bez strzaek na kocach symbolizuj zczenia, ktre nie zawieraj kluczy
gwnych. Zazwyczaj reprezentuj one niezwyke zczenia wiele-do-wielu, chocia
w niektrych przypadkach mog si zamienia w zczenia wiele-do-zera lub wiele-dojednego. W przypadku gdy nigdy nie maj one postaci wiele-do-wielu, unikalny warunek na jednym z kocw jest po prostu nierozpoznany, wic trzeba doda strzak na
tym unikalnym kocu. Jeli chocia czasami s one typu wiele-do-wielu, wwczas
spotykamy si z tymi samymi problemami (i tymi samymi rozwizaniami), ktre s charakterystyczne dla diagramw zapyta o wielu wzach rdowych. Rysunek 7.14
przedstawia zczenie wiele-do-wielu pomidzy T1 a T2, gdzie wspczynnik zczenia
detali na kadym kocu jest wikszy ni 1,0. (Wspczynniki zczenia tabel gwnych
istniej jedynie na unikalnych kocach zczenia, tych ze strzakami, wic to zczenie
ma dwa wspczynniki zczenia detali).

Rysunek 7.14. Zczenie wiele-do-wielu

Okazuje si, e taki przypadek jest znacznie czciej spotykany ni poprzednie przykady
niestandardowych diagramw zcze. Chocia wspdzieli on te same przyczyny problemw i te same rozwizania, co problem z wieloma wzami rdowymi, znaczna
wikszo zcze wiele-do-wielu wystpuje ze wzgldu na brak jakiego warunku
zczenia. Zacz naley od sprawdzenia, czy warunki filtrowania, ktre istniej ju
w zapytaniu powinny by traktowane jako cz zczenia, poniewa dopeniaj one
specyfikacji penego klucza gwnego na jednym z kocw zczenia. Przykad 5.2
z rozdziau 5. mg by potencjalnie takim przypadkiem, z brakujcym warunkiem
OT.Code_Type='STATUS_ZAMOWIENIA' niezbdnym, aby zczenie z OT stao si unikalne. Gdybymy traktowali ten warunek jedynie jako warunek filtrowania na aliasie OT,
zczenie z OT wygldaoby jak wiele-do-wielu. Nawet jeli nie znalelibymy brakujcej
czci zczenia pord warunkw filtrowania tego zapytania, powinnimy podejrzewa, e zostaa ona opuszczona przez pomyk.
Ten przypadek brakujcych warunkw zczenia jest szczeglnie czsty, kiedy projekt
bazy danych pozwala na wiele typw encji lub partycji w obrbie tabeli, a programista
zapomnia w zapytaniu uwzgldni warunek na typ lub partycj. Wczeniejszy przykad
tabeli Code_Translation ma rne typy encji translacji dla kadego Code_Type i nie

Niestandardowe diagramy zcze

243

uwzgldnienie warunku na Code_Type spowodowaoby, e zczenie z Code_Translation


byoby typu wiele-do-wielu. Czsto zdarza si, e problem tego typu nie jest do wczenie
zauwaony w fazie testw. Dzieje si tak dlatego, e nawet jeli projekt bazy danych pozwala na wiele typw partycji, rodowisko testowe moe mie dane tylko jednego typu.
Na ten stan rzeczy projektanci bardzo czsto si godz. Nawet jeli w prawdziwych
danych istnieje wiele typw partycji, inna bardziej wybircza cz klucza moe sama
powodowa unikalno. Jest to jednoczenie szczliwy i nieszczliwy zbieg okolicznoci
z jednej strony nie pozwala, aby brakujcy warunek zczenia sprawi natychmiastowe problemy, z drugiej powoduje, e problem jest znacznie trudniejszy do znalezienia
i naprawienia, oraz daje faszywe wraenie, e aplikacja nie zawiera bdw. Odnalezienie
i wstawienie brakujcego warunku zczenia moe zwikszy wydajno tylko nieznacznie poprzez uczynienie zczenia bardziej selektywnym, ale moe take mie
ogromn warto, jeli naprawi niebezpieczny w skutkach, niewidoczny bd.
Poprzez bezporedni analogi z diagramem zapytania o wielu wzach rdowych,
rozwizania problemu zczenia wiele-do-wielu mapuje si na podobne rozwizania
diagramu wielu rde.

Zczenia jeden-do-jednego
Jest taki dowcip o czowieku, ktry skary si, e musi codziennie chodzi do szkoy 5 mil
pod gr w obie strony. W pewnym sensie, zczenia jeden-do-jednego zamieniaj ten obraz na sytuacj przeciwn ze wzgldu na heurystyczne reguy wybierania nastpnej
tabeli zczenia, zczenia jeden-do-jednego s w obie strony z grki! Jako takie, tego typu
zczenia nie powoduj adnych problemw z optymalizacj i s najmniej kopotliwymi
elementami diagramw zapytania. Jednake wskazuj one czasami na pewne sprzyjajce
okolicznoci do poprawienia projektu bazy danych, jeli jestemy na etapie rozwoju
aplikacji, w ktrym projekt bazy danych nie jest jeszcze zamroony. Uytecznie jest take mie standardowe sposoby na reprezentacj zcze jeden-do-jednego na diagramie.
Opisz wic sposoby przedstawiania takich przypadkw.

Zczenie jeden-do-jednego z tabel zawierajc podzbir danych


Rysunek 7.15 pokazuje typowe zczenie jeden-do-jednego osadzone w wikszym zapytaniu. Podczas gdy zczenie wiele-do-wielu posiadao wspczynniki zczenia szczegw
na obu kocach, zczenie jeden-do-jedengo posiada wspczynniki zczenia jedynie
z tabel nadrzdn. Wspczynnik ten pokazuje nam, e zczenie pomidzy T1 a T2 jest
rzeczywicie typu jeden-do-zera lub jeden-do-jednego zczenie zero-do-jednego zdarza si w 30% wierszy tabeli T1.

Rysunek 7.15. Typowe zczenie jeden-do-jednego

244

Rozdzia 7. Tworzenie diagramw i optymalizacja zoonych zapyta SQL

Poniewa jest to zczenie wewntrzne, przypadki jeden-do-zera pomidzy T1 a T2 tworz ukryty warunek zczenia, ktry powinien by obsuony tak, jak opisano to pod
koniec rozdziau 6. Naley take zwrci uwag, e moe to by ukryty przypadek zczenia cyklicznego, co czsto si zdarza, gdy tabela gwna czy si jeden-do-jednego
z inn tabel. Jeli tabela szczegw znajduje si powyej T1, jak wskazuje na to szare
poczenie i jeli ta tabela szczegw czy si z T1 przez ten sam klucz unikalny, ktry
zosta uyty przy zczeniu z T2, wwczas przez przechodnio tworzy si zczenie
prowadzce od tabeli szczegw do tabeli T2. Rysunek 7.16 pokazuje to implikowane
zczenie poprzez poczenie zaznaczne szarym kolorem. O tym, jak radzi sobie z takimi
przypadkami napisano we wczeniejszej czci tego rozdziau poruszajcej zagadnienie
zcze cyklicznych.

Rysunek 7.16. Zczenie implikowane tworzce zczenie cykliczne

Niezalenie od istnienia zczenia cyklicznego, moe istnie okazja do poprawienia projektu


bazy danych. Przypadek z rysunku 7.16 sugeruje istnienie zbioru encji, ktre mapuj si
jeden-do-jednego z T1 oraz podzbioru tych samych encji, ktre mapuj si jeden-dojednego z T2, gdzie T2 jest zbudowane z kluczy gwnych T1 i kolumn majcych zastosowanie jedynie dla tego podzbioru. W tym przypadku nie ma istotnych powodw, aby
konieczne byy dwie tabele wystarczy po prostu doda kolumn do T1 i pozostawi j
pust dla wszystkich elementw wikszego zbioru, ktre nie nalez do zbioru mniejszego! Sporadycznie zdarzaj si sytuacje, w ktrych ze wzgldu na wygod, mona
pozostawi w projekcie dwie tabele. Z perspektywy optymalizacji, poczenie tych
dwch tabel jest niemal zawsze pomocne, tak wic naley si choby nad nim zastanowi, jeli tylko mamy wpyw na projekt bazy danych.

Zczenia cile typu jeden-do-jednego


Rysunek 7.17 pokazuje szczeglnie wany przypadek na poczenie dwch tabel w jedn.
Wspczynnik zczenia z tabel gwn jest tu dokadnie rwny 1,0, a relacja pomidzy
tabelami jest cile typu jeden-do-jednego. W zwizku z tym, obie tabele mapuj si na
ten sam zbir encji, a zczenie jest niepotrzebnym wydatkiem w porwnaniu z wykorzystaniem tabeli poczonej.
Biorc pod uwag wydajno, jedynym powodem rozdzielenia tych tabel mogaby by
sytuacja, w ktrej zapytanie niemal zawsze potrzebowaoby danych tylko z jednej spord nich i bardzo rzadko wymagaoby wykonania zczenia. Najczciej zdarza si, e

Niestandardowe diagramy zcze

245

Rysunek 7.17. Zczenie dokadnie jeden-do-jednego

jedna z tabel zawiera dane potrzebne sporadycznie, w porwnaniu z drug tabel.


W tym przypadku zwaszcza gdy rzadko wykorzystywane dane zajmuj duo miejsca na kady wiersz, a wierszy jest wiele moe si okaza, e wiksza zwarto czciej przeszukiwanej tabeli, w wyniku ktrej jest ona lepiej buforowana, uzasadni koszt
rzadko potrzebnego zczenia. Nawet z funkcjonalnego punktu widzenia lub perspektywy
tworzenia oprogramowania jest cakiem prawdopodobne, e koszt kodowania jednoczesnego dodawania i usuwania wierszy z obu tabel (a czasem i aktualizowania) jest
wysoki. Dlatego atwiejsze moe si okaza utrzymanie pojedynczej, poczonej tabeli.
Zazwyczaj pojawiajce si zczenia dokadnie typu jeden-do-jednego s rezultatem jakiej
dodanej funkcjonalnoci, ktra wymaga nowych kolumn w ju istniejcych encjach,
a ograniczenia w projektowaniu lub po prostu czyja wizja nie pozwoliy zmieni oryginalnej tabeli. Jeli to tylko moliwe, lepiej jest rozwiza problem przez usunicie tego
typu ogranicze.

Zczenie jeden-do-jednego ze znacznie mniejszym podzbiorem


Inny przypadek zosta pokazany na rysunku 7.18. Jest to zczenie jeden-do-zera lub jedendo-jednego, ktre niemal zawsze jest typu jeden-do-zera. W takim przypadku argumenty za rozdzieleniem tabel s bardzo mocne. May zbir encji reprezentowany przez
T2 moe mie zupenie inne wymogi optymalizacyjne ni nadzbir reprezentowany
przez T1. Najprawdopodobniej tabela T1 jest zazwyczaj przeszukiwana bez zczenia
z T2. Wwczas bardzo istotny jest fakt, e nie zawiera ona niepotrzebnych kolumn z T2,
a indeksy na niej zaoone maj zastosowanie przy zapytaniach do czsto uywanych
danych. Ukryty warunek zczenia, reprezentowany przez may wspczynnik zczenia
z tabel gwn po stronie T2, jest bardzo dobry. W rzeczywistoci jest on na tyle dobry,
e mona zdecydowa si na wyjcie od penego przeszukania tabeli T2 i ponownie
znale najlepsz ciek prowadzc do pozostaych danych. Trudno byoby powtrzy
taki plan wykonania bez tworzenia, zbdnych gdzie indziej, indeksw, gdybymy mieli
poczy te dwie tabele w jedn.

Rysunek 7.18. Zczenie jeden-do-zera lub jeden-do-jednego pomidzy tabelami o bardzo duej rnicy
rozmiarw

246

Rozdzia 7. Tworzenie diagramw i optymalizacja zoonych zapyta SQL

W tym przypadku najwaniejsze jest, aby wzi pod uwag ukryty warunek zczenia
z tabeli T1 do T2, niezalenie od tego, czy wychodzimy ze strony zapytania, po ktrej znajduje si T2, czy te osigniemy j jak najwczeniej, aby uzyska dostp do ukrytego filtru.

Zczenie jeden-do-jednego z ukrytymi filtrami zczenia po obu stronach


Rysunek 7.19 pokazuje wyjtkowy przykad zczenia [zero lub jeden]-do-[zero lub jeden],
w ktrym filtr ma zastosowanie w obu kierunkach. Jeli zczenia jeden-do-jednego s
skierowane w d w obu kierunkach, wwczas zczenia [zero lub jeden]-do-[zero lub jeden]
opadaj bardzo stromo. Jednake jeli tylko dane nie s uszkodzone (w jednej tabeli brakuje danych), taki przypadek wskazuje na istnienie trzeciej tabeli lub na to, e powinna
istnie, zawierajc nadzbir tych dwch zachodzcych na siebie zbiorw. Jeli znajdziemy lub utworzymy tak tabel, te same argumenty, ktre przytoczono wczeniej maj
zastosowanie w czeniu jej z jedn lub obiema tabelami zawierajcymi podzbir danych.

Rysunek 7.19. Zczenie [zero lub jeden]-do-[zero lub jeden]

Konwencje pokazywania zcze jeden-do-jednego


Bardzo pomocne jest ustalenie konwencji odnonie pokazywania diagramw zapyta.
Pomagaj one prezentowa wane informacje w uniwersalny sposb. Poczenia z pojedynczymi strzakami zawsze wskazuj ku doowi. Rysunek 7.20 pokazuje dwie moliwoci,
ktre dobrze funkcjonuj w zczeniach jeden-do-jednego lecych poniej rdowej
tabeli szczegw. Pierwsza moliwo wskazuje na poczenie dwustrzakowe, gdzie
aden z wzw nie ley powyej drugiego. Druga uywa standardowego przepywu ku
doowi ze rdowej tabeli szczegw. Obie metody oka si dobre, jeli tylko bdziemy
pamita, e oba kierunki zczenia jeden-do-jednego s w istocie skierowane ku doowi.

Rysunek 7.20. Tworzenie diagramu dla zcze jeden-do-jednego lecych pod rdow tabel szczegw

Niestandardowe diagramy zcze

247

W razie gdy obie zczone tabele znajduj si poniej rda, naley pamita o tym, e
jeli tabele zczone jeden-do-jednego wspdziel klucz gwny, wwczas poczenie
od gry do T1 moe przez przechodnio rwnie dobrze prowadzi do T2, chyba e
prowadzi do jakiego innego klucza unikalnego wystpujcego w T1, a nieistniejcego
w T2. Tworzy si tu implikowane zczenie cykliczne przedstawione na rysunku 7.2 B.
Rysunek 7.21 przedstawia inne moliwe diagramy dla zcze jeden-do-jednego tabel,
ktre mona zakwalifikowa jako gwne tabele szczegw (nie maj zcze od gry),
jeli chocia jeden z kierunkw zczenia jeden-do-jednego ma wspczynnik zczenia
z tabel nadrzdn mniejszy ni 1,0. Ponownie mona podkreli zczenie jeden-dojednego poprzez wykorzystanie poziomego ukadu lub te podkreli, ktra tabela jest
wiksza (i ktry kierunek zczenia jest bardziej stromy) poprzez umieszczenie wyej
wza z wikszym wspczynnikiem zczenia z tabel nadrzdn. Wze z wikszym
wspczynnikiem zczenia z tabel nadrzdn reprezentuje tabel zawierajc wicej
wierszy w tym [zero lub jeden]-do-[zero lub jeden] zczeniu.

Rysunek 7.21. Rne moliwe diagramy dla zczenia [zero lub jeden]-do-[zero lub jeden] gwnych tabeli
szczegw

Rysunek 7.22 pokazuje przypadek podobny do tego z rysunku 7.21, ale z wzami bdcymi
dokadnie w relacji jeden-do-jednego (tabel, ktre zawsze si cz). Ponownie moemy
wzmocni rwno obu kierunkw zczenia poprzez uoenie wzw w poziomie.
Ewentualnie, moemy wybra kierunek, ktry pozwala na stworzenie lepiej zbalansowanego drzewa, tj. takiego, ktre lepiej mieci si na stronie, umieszczajc wzy z bardziej
rozbudowanymi gaziami wyej. To, ktre rozwizanie wybierzemy, ma mniejsze znaczenie, jeli tylko pamitamy, e oba kierunki s w zasadzie skierowane ku doowi, niezalenie od tego jak s przedstawione na diagramie.

Rysunek 7.22. Rne moliwoci przedstawienia diagramu dla gwnych tabel szczegw zczonych
dokadnie jeden-do-jednego

248

Rozdzia 7. Tworzenie diagramw i optymalizacja zoonych zapyta SQL

Zczenia zewntrzne
Niemal zawsze sensem i celem zczenia zewntrznego jest zapobieenie utracie podanych danych z tabeli, z ktrej wychodzi zczenie. Nieprawidowe zczenia zewntrzne,
ktre opisz w nastpnych podrozdziaach, oglnie rzecz biorc, pokazuj pewne sprzecznoci z podanymi powyej przyczynami istnienia zcze zewntrznych.

Filtrowane zczenia zewntrzne


Przyjrzyjmy si rysunkowi 7.23, na ktrym zobrazowano zczenie zewntrzne z tabel
zawierajc warunek filtrowania. W przypadku gdy tabela T1 ma wiersz nie znajdujcy
odpowiednika w tabeli T2, baza danych przypisuje w rezultacie warto null do kadej
kolumny T2. Dlatego za wyjtkiem T2.JakaKolumna IS NULL praktycznie kady
warunek filtrowania na T2 wyczyby wynikowy wiersz pochodzcy z zewntrznej
czci zczenia zewntrznego.

Rysunek 7.23. Zczenie zewntrzne z filtrowanym wzem

Nawet warunki takie, jak T2.Unpaid_Flag != 'T' lub NOT T2.Unpaid_Flag = 'Y',
ktre powinny by prawdziwe, w zewntrznym przypadku nie s.
W przypadku warunkw w klauzuli WHERE, baza danych interpretuje wartoci
null w mao intuicyjny sposb. Jeli patrzymy na null jako na reprezentacj
wartoci niewiadoma w odniesieniu do kolumny tabeli, a nie w bardziej standardowym znaczeniu nie ma zastosowania, moemy zacz rozumie jak
baza danych traktuje wartoci null w klauzuli WHERE. Za wyjtkiem pytania
konkretnie o to, czy kolumna ma warto null, niemal kade pytanie jakie mona
zada, zwrci rezultat nieznany, co w istocie jest prawdziw wartoci wikszoci
warunkw z wartociami null. W razie odrzucenia wierszy zapytania, baza danych
traktuje prawdziw warto nieznany jak FALSE, nie przyjmujc wierszy z nieznanymi prawdziwymi wartociami w klauzuli WHERE. I o ile NOT FALSE =
TRUE, okazuje si, e NOT "nieznane" = "nieznane"!

Poniewa wikszo filtrw na tabeli zewntrznej odrzuca zewntrzn cz zczenia


zewntrznego i poniewa gwnym celem zczenia zewntrznego jest zachowanie tej czci, trzeba szczeglnie uwaa na kady filtr na tabeli zewntrznej. Jeden z poniszych
scenariuszy ma zazwyczaj zastosowanie i dobrze jest powici chwil, aby ustali ktry:

Niestandardowe diagramy zcze

249

Filtr jest jednym z rzadko wystpujcych filtrw, jak na przykad JakaKolumna IS


NULL, ktry moe zwrci warto TRUE dla wartoci null wystpujcych w czci
zewntrznej, a sam filtr jest funkcjonalnie poprawny.
Programista nie mia zamiaru pozby si czci zewntrznej,
wic warunek filtrowania musi zosta usunity.
Warunek filtrowania mia w zamierzeniach odrzuci cz zewntrzn, a zczenie
mogoby by rwnie dobrze wewntrzne. W takim przypadku nie ma funkcjonalnych
rnic pomidzy zapytaniem ze zczeniem wyraonym w formie zewntrznej
czy formie wewntrznej. Jednak poprzez jawne zaznaczenie go jako zczenia
wewntrznego, baza danych ma wiksz swobod w tworzeniu planu wykonania
i zczenie to moe by wykonane w obie strony. Jeli najlepszy filtr znajduje si
po tej samej stronie zczenia co poprzednio zczona zewntrznie tabela, dodatkowy
stopie swobody moe udostpni lepszy plan wykonania. Niemniej zamiana
zczenia na wewntrzne moe spowodowa, e optymalizator popeni bd, ktrego
mgby unikn w przypadku zczenia zewntrznego. Zczenia zewntrzne s
jedn z metod na wymuszenie porzdku zczenia, jeli tylko wiadomie tego chcemy,
nawet gdy nie potrzebujemy uchroni zewntrznej czci zczenia.

Warunki zczenia zewntrznego na pojedynczej tabeli


W starej notacji bazy danych Oracle, warunek filtrowania czynimy czci zczenia przez dodanie (+). Na przykad, dwuczciowe zczenie zewntrzne z tabel
Code_Translations, uyt we wczeniejszych przykadach, mogoby wyglda
nastpujco:
WHERE ...
AND O.Order_Type=OType_Trans.Code (+)
AND OTypeTrans.Type(+)='TYP_ZAMOWIENIA'

Wedug nowszej notacji ANSI, ktra jest jedyn dozwolon w DB2, warunek filtrowania przenosi si z klauzuli FROM i staje si jawnym warunkiem zczenia:
FROM ... Orders O ...
LEFT OUTER JOIN Code_Translations OTypeTrans
ON O.Order_Type_Code=OTypeTrans.Code
AND OTypeTrans.Code_Type='TYP_ZAMOWIENIA'

W oryginalnej notacji zczenia zewntrznego, pochodzcej z bazy danych SQL Server,


baza danych po prostu zakada, e warunek filtrowania jest czci zczenia:
WHERE ...
AND O.Order_Type_Code*=OTypeTrans.Code
AND OTypeTrans.Type='TYP_ZAMOWIENIA'

Zauwamy, e opisany problem przestaje istnie dla zcze zewntrznych starego


SQL Servera. Baza danych automatycznie uczynia filtr czci zapytania. Zwrmy take uwag, e w rzadkich przypadkach, w ktrych warunek filtrowania jest naprawd
filtrem, musimy bd stosowa now notacj zcze zewntrznych, aby otrzyma podane rezultaty, bd te zamieni zczenie w rwnowane podzapytanie NOT EXISTS,
tak jak to zaraz opisz.

250

Rozdzia 7. Tworzenie diagramw i optymalizacja zoonych zapyta SQL

Warunek filtrowania by zamierzony, ale powinien by czci zczenia!


Dziki uczynieniu warunku filtrowania czci zczenia, nakazujemy bazie
danych co nastpuje: Dla kadego wiersza tabeli szczegw dostarcz
odpowiadajcy mu wiersz z tabeli, do ktrej pasuje filtr, jeli w ogle taki istnieje.
W przeciwnym wypadku pocz z pseudowierszem o wszystkich wartociach null.
Rozwamy dogbniej pierwszy scenariusz. Spjrzmy na zapytanie:
SELECT ...
FROM Employees E
LEFT OUTER JOIN Departments D
ON E.Department_ID=D.Department_ID
WHERE E.Manager_ID IS NULL

O co tak naprawd zapytanie pyta baz danych? Semantycznie jest to danie o dwa, raczej
rne, zbiory wierszy zbir wszystkich pracownikw, ktrzy nie maj adnych oddziaw i zbir wszystkich pracownikw, ktrych menaderowie nie maj departamentw.
Moliwe jest, e aplikacja rzeczywicie potrzebuje dwch takich niezalenych zbiorw
jednoczenie, aczkolwiek wydaje si bardziej prawdopodobnym, e programista nie zauway, e tak proste zapytanie zwraca tak zoone rezultaty, i wcale nie potrzebowa
jednego z tych zbiorw.
Rozwamy nieco inny przykad:
SELECT ... FROM Employees E
LEFT OUTER JOIN Departments D
ON E.Department_ID=D.Department_ID
WHERE D.Department_ID IS NULL

Na pierwszy rzut oka zapytanie to moe si wydawa dziwne, poniewa klucz gwny
(Department_ID) tabeli Department nie moe by rwny null. Pomimo tego, taki klucz
wartoci null nie mgby nigdy zczy si z adn inn tabel zczeniem takim, jak
zaprezentowane (poniewa warunek NULL = NULL zwraca warto nieznany). Jednake, poniewa jest to zczenie zewntrzne, istnieje sensowna interpretacja tego zapytania:
Znajd pracownikw, ktrzy nie maj przypisanych departamentw. W zewntrznej
czci tego zewntrznego zapytania, kada kolumna tabeli Departments, wczajc
nawet obligatoryjne rne od null kolumny, jest zamieniana na null. Dlatego warunek D.Department_ID IS NULL jest prawdziwy jedynie w zewntrznym przypadku. Istnieje
jednak znacznie popularniejszy i atwiejszy do odczytania sposb wyraenia tego zapytania:
SELECT ...
FROM Employees E
WHERE NOT EXISTS (SELECT *
FROM Departments D
WHERE E.Department_ID=D.Department_ID)

Chocia forma NOT EXISTS w tego typu zapytaniu jest bardziej naturalna, atwiejsza do
odczytania i zrozumienia, forma pierwsza (najlepiej jeli jest otoczona przez odpowiednie komentarze) ma swoje miejsce w optymalizacji SQL. Przewaga wyraenia NOT
EXISTS jako zczenia zewntrznego, po ktrym wystpuje wyraenie Klucz_Gwny IS
NULL, polega na tym, e daje ono wiksz kontrol w momencie wystpienia zczenia

Niestandardowe diagramy zcze

251

w planie wykonania oraz kiedy selektywno warunku zostanie uwzgldniona. Zazwyczaj


warunki NOT EXISTS s wykonywane po wszystkich zwykych zczeniach, w kadym
razie dzieje si tak w bazie danych Oracle. To przykad, w ktrym filtr (nie bdcy czci zczenia zewntrznego) na zczonej zewntrznie tabeli jest umieszczony celowo
i poprawnie.
W notacji zgodnej ze star wersj SQL Servera, kombinacja zczenia zewntrznego
i warunku IS NULL nie dziaaa. Przepisanie przykadu w notacji zgodnej z SQL
Serverem mogoby wyglda w taki sposb:
SELECT ...
FROM Employees E, Departments D
WHERE E.Department_ID*=D.Department_ID
AND D.Department_ID IS NULL

Jednake rezultat nie bdzie taki, jakiego bymy sobie yczyli! Przypomnijmy, e
SQL Server interpretuje wszystkie warunki filtrowania na tabeli zczonej zewntrznie jako cz zczenia i bdzie prbowa utworzy poczenie z tabel
Departments, ktra ma wartoci null klucza gwnego (wartoci null w kolumnie D.Department_ID). Nawet jeli takie wiersze istniej z naruszeniem poprawnego
projektu bazy danych, nigdy nie zcz si poprawnie z tablic Employees, poniewa warunek rwnoci nie moe by prawdziwy dla wartoci null klucza.
Zamiast tego zapytanie nie przefiltruje adnych wierszy, zwracajc wszystkich
pracownikw z wszystkimi zczeniami wpadajcymi w przypadek zewntrzny.

Zczenia zewntrzne prowadzce do zcze wewntrznych


Rozwamy rysunek 7.24, w ktrym zczenie zewntrzne prowadzi do zczenia wewntrznego.

Rysunek 7.24. Zczenie zewntrzne prowadzce do zczenia wewntrznego

Powysze zczenie w starej wersji bazy danych Oracle miaoby nastpujcy zapis:
SELECT ...
FROM Table1 T1, Table3 T2, Table3 T3
WHERE T1.FKey2=T2.PKey2(+)
AND T2.FKey3=T3.PKey3

252

Rozdzia 7. Tworzenie diagramw i optymalizacja zoonych zapyta SQL

W zewntrznym przypadku pierwszego zczenia, baza danych wygeneruje pseudowiersz


tabeli T2, wypeniony samymi wartociami null dla wszystkich kolumn, wczajc w to
warto T2.FKey3. Jednake klucz obcy o wartoci null nigdy nie zczy si z inn tabel, tak wic wiersze reprezentujce przypadek zewntrzny bd odrzucone podczas
prby zczenia z T3. Dlatego wynik zczenia zewntrznego prowadzcego do zczenia
wewntrznego jest dokadnie taki sam, jak rezultat jaki otrzymalibymy, gdyby oba
zczenia byy wewntrzne. Jego otrzymanie jest bardziej kosztowne, poniewa baza
danych odrzuca wiersze, ktre nie poczyy si w dalszej czci planu wykonania. Taka
sytuacja zawsze wiadczy o bdzie. Jeli zamiarem jest utrzymanie zewntrznego przypadku, naley wymieni zczenie zewntrzne prowadzce do zczenia wewntrznego
przez zczenie zewntrzne prowadzce do innego zczenia zewntrznego. W przeciwnym
razie naley uy zczenia wewntrznego prowadzcego do zczenia wewntrznego.

Zczenie zewntrzne wskazujce na tabele szczegw


Przeanalizujmy rysunek 7.25, w ktrym strzaka porednia pokazuje zczenie zewntrzne
wskazujce na tabel szczegw.

Rysunek 7.25. Zczenie zewntrzne wskazujce na tabel szczegw

Gdyby wykorzysta now notacj ANSI, zapytanie mogoby wyglda nastpujco:


SELECT ...
FROM Departments D
LEFT OUTER JOIN Employees E
ON D.Department_ID=E.Department_ID

Zapis w starej wersji bazy danych Oracle przedstawiaby si w ten sposb:


SELECT ...
FROM Departments D, Employees E
WHERE D.Department_ID=E.Department_ID(+)

za w starej wersji SQL Servera, w taki:


SELECT ...
FROM Departments D, Employees E
WHERE D.Department_ID*=P.Department_ID

O co pyta kade z tych zapyta? Istot pytania mona by sformuowa w mniej wicej taki
sposb: Podaj mi informacje dotyczce wszystkich pracownikw, ktrzy maj departamenty (przypadek wewntrzny) wraz z danymi ich departamentw, a take informacje

Niestandardowe diagramy zcze

253

dotyczce departamentw, ktre nie posiadaj pracownikw (przypadek zewntrzny).


W przypadku wewntrznym, rezultat mapuje kady wiersz na encj detali (pracownik
przynalecy do departamentu), podczas gdy w przypadku zewntrznym, rezultat mapuje kady wiersz na encj rdow (departament, ktry nie przynaley do adnego
pracownika). Jest mao prawdopodobne, eby taki dziwny splot encji by uyteczny jako
rezultat jednego zapytania, std zapytania takie jak te, ze zczeniami zewntrznymi do
tabeli szczegw, rzadko s poprawne. Najbardziej popularny przypadek takiego bdu
to zczenie z tabel szczegw, ktre zazwyczaj nie zwrci adnego lub jeden szczeg
na wiersz rdowy i rzadko jest to zczenie wiele-do-jednego z tabel rdow. Programici czasem nie zauwaaj implikacji zwizanych z rzadkimi przypadkami wieledo-jednego, a mog si one nie ujawni w czasie testowania.

Zczenia zewntrzne z tabelami szczegw posiadajcymi filtry


Rysunek 7.26 pokazuje zczenie zewntrzne z tabel szczegw, ktra dodatkowo
ma warunek filtrowania. I znowu podwjne zo daje w wyniku dobro. Zczenie zewntrzne z tabel szczegw, ktra posiada dodatkowo filtr moe przysporzy wszystkich problemw opisanych w poprzednich dwch podrozdziaach. Czasem filtr znosi
efekt problematycznego zczenia zewntrznego, zamieniajc je funkcjonalnie w zczenie wewntrzne. W takich przypadkach trzeba unika usunicia filtra, chyba e uczynimy
jednoczenie zczenie zewntrzne wewntrznym.

Rysunek 7.26. Zczenie zewntrzne do filtrowanej tabeli szczegw

Najbardziej interesujcym przypadkiem, widocznym na rysunku 7.26, jest sytuacja, w ktrej


istnienie filtru ma sens jedynie w kontekcie zczenia zewntrznego. Wwczas warunek
filtrowania na T1 jest prawdziwy jedynie w przypadku zewntrznym, na przykad
T1.FKey_ID IS NULL. (T1.FKey_ID jest kluczem obcym wskazujcym na T2.PKey_ID
na diagramie zczenia). Podobnie jak w poprzednim przykadzie z warunkiem wartoklucza-czcego IS NULL (klucz gwny we wczeniejszym przypadku), przypadek ten
jest rwnowany podzapytaniu NOT EXISTS. To alternatywne wyraenie dla warunku
NOT EXISTS oferuje czasami uyteczny poziom dodatkowej kontroli w momencie, kiedy
baza danych wykona zczenie i odrzuci wiersze, ktre nie speniaj warunku. Poniewa
wszystkie zczone wewntrznie wiersze s odrzucone przez warunek IS NULL, pozbywamy si standardowego problemu zwizanego ze zczeniem zewntrznym z tabel
szczegw zmieszania ze sob rnych encji pochodzcych z wewntrznej i zewntrznej czci zczenia. I w taki oto sposb dwukrotne zo daje w efekcie dobro!

254

Rozdzia 7. Tworzenie diagramw i optymalizacja zoonych zapyta SQL

Zapytania z podzapytaniami
Niemal wszystkie prawdziwe zapytania z podzapytaniami nakadaj specjalny rodzaj
warunku na wiersze w zewntrznym, gwnym zapytaniu musz pasowa albo te
nie do odpowiednich wierszy powizanego zapytania. Na przykad, jeli potrzebujemy
danych odnonie departamentw, ktre maj pracownikw, zapytanie mogoby wyglda nastpujco:
SELECT ...
FROM Departments D
WHERE EXISTS (SELECT NULL
FROM Employees E
WHERE E.Department_ID=D.Department_ID)

Ewentualnie moglibymy zapyta o departamenty, ktre nie posiadaj pracownikw:


SELECT ... FROM Departments D
WHERE NOT EXISTS (SELECT NULL
FROM Employees E
WHERE E.Department_ID=D.Department_ID)

Zczenie E.Department_ID=D.Department_ID w kadym z tych zapyta jest zczeniem skorelowanym, ktre dopasowuje do siebie tabele zapytania zewntrznego i podzapytania. Zapytanie EXISTS ma alternatywn, rwnowan posta:
SELECT ...
FROM Departments D
WHERE D.Department_ID IN (SELECT E.Department_ID FROM Employees E)

Poniewa obie formy s funkcjonalnie rwnowane i poniewa diagram nie powinien


sugerowa jednego rozwizania, jest on dla obu form taki sam. Dopiero po jego utworzeniu naley wybra odpowiedni form w zalenoci od tego, ktra z nich najlepiej
rozwizuje problem wydajnoci i w najlepszy sposb przedstawia oczekiwan ciek
dostpu do danych.

Tworzenie diagramw zapyta z podzapytaniami


Ignorujc zczenie pomidzy zapytaniem zewntrznym a podzapytaniem, mona
utworzy niezalene diagramy zapyta dla kadego z nich osobno. Pozostaje jedynie
pytanie, jak przedstawi poczenie tych dwch diagramw, tak by utworzyy jeden. Na
podstawie formy EXISTS poprzedniego zapytania jasno wida, e zapytanie zewntrzne
czy si z podzapytaniem poprzez zczenie skorelowane. Takie zczenie ma szczegln waciwo: dla kadego wiersza zapytania zewntrznego, ju po pierwszym razie,
kiedy baza danych odnajdzie pasujce do siebie (wedug zczenia) wiersze, zaprzestaje
dalszych poszukiwa, uwaajc warunek EXISTS za speniony i podaje wiersz zapytania
zewntrznego do nastpnego kroku planu wykonania. Jeli znajdzie pasujce wiersze dla
podzapytania powizanego przez NOT EXISTS, zatrzymuje si, ze wzgldu na niespenienie tego warunku, a nastpnie odrzuca odpowiedni wiersz zapytania zewntrznego.

Zapytania z podzapytaniami

255

Takie zachowania sugeruj, e diagram zapytania powinien odpowiada na nastpujce


cztery pytania odnonie zcze skorelowanych, ktre nie maj zastosowania w przypadku zwykych zcze:
Czy zczenie jest zwyke? (Nie, zczenie jest skorelowane z podzapytaniem.)
Ktra strona zczenia jest podzapytaniem, a ktra zapytaniem zewntrznym?
Przez ktr form zapytania da si wyrazi, EXISTS czy NOT EXISTS?
Jak wczenie w planie wykonania podzapytanie powinno by wykonane?
Pracujc z podzapytaniami i ustalajc odpowiedzi na te pytania, trzeba pamita, e tak
samo jak dla zwykych zapyta, musimy pokaza, ktry koniec jest tabel gwn i jak
due s wspczynniki zcze.

Tworzenie diagramw dla podzapyta EXISTS


Rysunek 7.27 pokazuje moj konwencj tworzenia diagramw z podzapytaniami typu
EXISTS (ktre mog by wyraone przez rwnowane podzapytanie IN). Rysunek oparty
jest o wczeniejsze podzapytanie typu EXISTS:
SELECT ... FROM Departments D
WHERE NOT EXISTS (SELECT NULL
FROM Employees E
WHERE E.Department_ID=D.Department_ID)

Rysunek 7.27. Proste zapytanie z podzapytaniem

Dla zcze skorelowanych (znanych jako zczenia typu semi-join, jeli odnosz si do
podzapyta typu EXISTS) z tabeli Departments do Employees, diagram rozpoczyna si
z takimi samymi statystykami zczenia, jak pokazano na rysunku 5.1.
Jak kade inne zczenie, zczenie typu semi-join, ktre czy zapytanie wewntrzne
z zewntrznym jest przedstawione w postaci strzaki na jednym z kocw poczenia,
wskazujcej na klucz gwny. Podobnie na kadym kocu znajduj si wspczynniki
zczenia, ktre reprezentuj te same waciwoci, ktre zczenie to miaoby w zwykym
zapytaniu. Uywam strzaki poredniej, aby wskaza przejcie od wza zewntrznego
zapytania skorelowanego do wza podzapytania. Umieciem E obok strzaki poredniej,
aby pokaza, e jest to zczenie typu semi-join dla elementu EXISTS lub IN podzapytania.

256

Rozdzia 7. Tworzenie diagramw i optymalizacja zoonych zapyta SQL

W tym przypadku, tak jak w wielu przypadkach podzapyta, cz diagramu z podzapytaniem jest pojedynczym wzem reprezentujcym podzapytanie bez jego wasnych
zcze. Rzadziej, jednak podobnie jak w tym przykadzie, zapytanie zewntrzne jest
pojedynczym wzem, reprezentujcym to zapytanie bez zcze wasnych. Skadnia jest
zasadniczo nieograniczona, z moliwoci wystpienia wielu podzapyta zczonych
z zapytaniem zewntrznym lub te podzapyta ze zoon wewntrzn struktur zcze lub nawet podzapyta wskazujcych na gbiej zagniedone w nich samych
podzapytania.
Zczenie typu semi-join wymaga take do dwch liczb, aby pokaza waciwoci
podzapytania, dziki czemu mona wybra najlepszy plan. Rysunek 7.27 pokazuje obie
te wartoci, ktre czasem s niezbdne do wybrania optymalnego planu radzenia sobie
z podzapytaniem.
Pierwsza warto, tu obok E (rwna 20 na rysunku 7.27) jest wspczynnikiem korelacji.
Wspczynnik korelacji jest wspczynnikiem I/E. E jest szacunkowym lub zmierzonym
czasem wykonania najlepszego planu prowadzcego z zapytania zewntrznego do podzapytania (podajc za logik zapytania EXISTS). I jest szacunkowym lub zmierzonym
czasem wykonania najlepszego planu prowadzcego z zapytania wewntrznego do
zapytania zewntrznego (podajc za logik zapytania typu IN). Moemy zawsze wyznaczy ten wspczynnik bezporednio poprzez zmierzenie czasu wykonania obu form,
co zazwyczaj jest do atw czynnoci, chyba e mamy do czynienia z du liczb
poczonych podzapyta. W dalszej czci ksizki opisz kilka regu pomocnych
w oszacowaniu wartoci I/E mniej lub bardziej celnie, ale nawet przybliona estymacja
jest wystarczajca do wyboru planu, kiedy jak ma to czsto miejsce warto jest
bd znacznie mniejsza, bd znacznie wiksza ni 1,0. Kiedy wspczynnik korelacji
jest wikszy ni 1,0, naley wybra podzapytanie skorelowane z warunkiem EXISTS
oraz plan, ktry wychodzi od zapytania zewntrznego do podzapytania.
Nastpn now wartoci jest skorygowany wspczynnik filtrowania podzapytania (rwny
0,8 na rysunku 7.27) zaraz obok wspczynnika zczenia detali. Jest to szacunkowa
warto, ktra jest pomocna w wyborze najlepszego miejsca w porzdku zczenia do
sprawdzenia warunku podzapytania. Ma ona jedynie zastosowanie do zapyta, ktre
zaczynaj si od zapytania zewntrznego, tak wic naley j wykluczy z kadego zczenia typu semi-join (ze wspczynnikiem korelacji mniejszym ni 1,0), ktre moe by
zamienione na rdowe zapytanie w planie wykonania.
Jeli mamy wicej ni jedno zczenie typu semi-join ze wspczynnikiem korelacji
mniejszym ni 1,0, powinnimy wyj od podzapytania o najmniejszym wspczynniku korelacji, ale wci bd nam potrzebne skorygowane wspczynniki filtrowania
pozostaych podzapyta.

Zanim wyjani, jak obliczy wspczynnik korelacji i skorygowany wspczynnik korelacji podzapytania, zastanwmy si, kiedy bdziemy ich potrzebowa. Rysunek 7.28
pokazuje cz diagramu zapytania dla podzapytania typu EXISTS ze rdow tabel
szczegw na kocu zczenia typu semi-join odpowiadajcemu kluczowi gwnemu.

Zapytania z podzapytaniami

257

Rysunek 7.28. Zczenie semi-join z kluczem gwnym

Zczenie semi-join na rysunku nie rni si funkcjonalnie od zwykego zczenia, poniewa zapytanie nigdy nie znajdzie wicej ni jednego pasujcego wiersza z tabeli M dla
dowolnego wiersza zapytania zewntrznego.
Zakadam tutaj, e cae poddrzewo poniej M ma form normaln (ze wszystkimi poczeniami wskazujcymi ku doowi na klucze gwne), tak e cae podzapytanie mapuje
si jeden-do-jednego z wierszami ze rdowej tabeli szczegw M tego poddrzewa.

Poniewa zczenie typu semi-join nie rni si funkcjonalnie od zwykego zczenia,


moemy uzyska dodatkowy stopie swobody w planie wykonania poprzez jawne wyeliminowania warunku EXISTS oraz wczenie podzapytania do zapytania zewntrznego.
Rozwamy nastpujce zapytanie:
SELECT <Kolumny jedynie z zapytania zewntrznego>
FROM Order_Details OD, Products P, Shipments S,
Addresses A, Code_Translations CT
WHERE OD.Product_ID = P.Product_ID
AND P.Unit_Cost > 100
AND OD.Shipment_ID = S.Shipment_ID
AND S.Address_ID = A.Address_ID(+)
AND OD.Status_Code = CT.Code
AND CT.Code_Type = 'Dokladny_Status_Zamowienia'
AND S.Shipment_Date > :now - 1
AND EXISTS (SELECT null
FROM Orders O, Customers C, Code_Translations OT,
Customer_Types CT
WHERE C.Customer_Type_ID = CT.Customer_Type_ID
AND CT.Text = 'Rzd'
AND OD.Order_ID = O.Order_ID
AND O.Customer_ID = C.Customer_ID
AND O.Status_Code = OT.Code
AND O.Completed_Flag = 'N'
AND OT.Code_Type = 'STAN_ZAMOWIENIA'
AND OT.Text!= 'Odwolane')
ORDER BY <Kolumny jedynie z zapytania zewntrznego>

Uywajc nowej notacji zcze typu semi-join moemy to zapytanie przedstawi na


diagramie, tak jak pokazano je na rysunku 7.29

258

Rozdzia 7. Tworzenie diagramw i optymalizacja zoonych zapyta SQL

Rysunek 7.29. Zoony przykad zczenia semi-join skorelowanego z kluczem gwnym rdowej tabeli
szczegw podzapytania

Jeli po prostu przepiszemy to zapytanie, przenoszc zczenia tabel i wszystkie warunki


z podzapytania do zapytania zewntrznego otrzymamy zapytanie, ktre ma t sam
funkcjonalno, poniewa zczenie typu semi-join jest skierowane ku kluczowi gwnemu, a podzapytanie jest zczone jeden-do-jednego ze swoj rdow tabel szczegw:
SELECT <Kolumny jedynie z oryginalnego zapytania zewntrznego>
FROM Order_Details OD, Products P, Shipments S,
Addresses A, Code_Translations ODT,
Orders O, Customers C, Code_Translations OT, Customer_Types CT
WHERE OD.Product_ID = P.Product_ID
AND P.Unit_Cost > 100
AND OD.Shipment_ID = S.Shipment_ID
AND S.Address_ID = A.Address_ID(+)
AND OD.Status_Code = ODT.Code
AND ODT.Code_Type = 'Dokladny_Status_Zamowienia'
AND S.Shipment_Date > :now - 1
AND C.Customer_Type_ID = CT.Customer_Type_ID
AND CT.Text = 'Rzd'
AND OD.Order_ID = O.Order_ID
AND O.Customer_ID = C.Customer_ID
AND O.Status_Code = OT.Code
AND O.Completed_Flag = 'N'
AND OT.Code_Type = 'STAN_ZAMOWIENIA'
AND OT.Text!= 'Odwolane'
ORDER BY <Kolumny jedynie z oryginalnego zapytania zewntrznego>

Aby transformacja z jednej formy w drug staa si oczywista, zrobiem odpowiednie wcicia
w kodzie. Diagram zapytania jest niemal identyczny, jak mona zobaczy na rysunku 7.30.
Ta nowa forma ma duy stopie dodatkowej swobody, pozwalajc na przykad na plan,
ktry czy rednio filtrowany wze P tu po zczeniu z wysoce filtrowanym wzem O,
ale przed zczeniem z niemal nieprzefiltrowanym wzem OT. W oryginalnej formie baza
danych byaby zmuszona do wykonania caego podzapytania, zanim mogaby rozway
zczenia z wzami zapytania zewntrznego. Poniewa w przypadkach takich jak ten

Zapytania z podzapytaniami

259

Rysunek 7.30. To samo zapytanie zmienione przez wczenie podzapytania

wczanie podzapyta w zapytania zewntrzne moe tylko pomc i poniewa takie


wczenie tworzy diagram, ktry umiemy ju optymalizowa, opr si na zaoeniu
obowizujcym w pozostaej czci podrozdziau, e ten typ podzapytania bdziemy
zawsze wczali w zapytanie zewntrzne. Opisz jedynie, jak tworzy diagramy i optymalizowa inne przypadki.
W teorii, ten sam trik moe by zaadoptowany do wczania podzapyta typu EXISTS,
w ktrych zczenie typu semi-join jest take skierowane do koca zwizanego z tabel
szczegw, ale wykonanie go jest trudniejsze i z mniejszym prawdopodobiestwem
przyniesie jak popraw wydajnoci. Przeanalizujmy wczeniejsze zapytanie odnonie
departamentw z warunkiem EXISTS na Employees:
SELECT ...
FROM Departments D
WHERE EXISTS (SELECT NULL
FROM Employees E
WHERE E.Department_ID=D.Department_ID)

A oto na jakie problemy natrafimy przy prbie zastosowania powyej przedstawionego


triku:
Oryginalne zapytanie zwraca co najwyej jeden wiersz dla kadego wiersza tabeli
nadrzdnej i kadego departamentu. Aby uzyska te same rezultaty z zapytania
po transformacji, ze zwykym zczeniem z tabel szczegw (Employees),
musielibymy wymieni licie SELECT unikalny klucz tabeli nadrzdnej
oraz wykona operacj DISTINCT na wierszach wynikowych.
Poczynienie tych krokw usuwa duplikaty, ktre pojawiaj si, gdy jeden wiersz
tabeli nadrzdnej posiada wiele odpowiadajcych mu wierszy tabeli szczegw.
Jeli wiersz nadrzdny ma wiele pasujcych wierszy tabeli szczegw, czsto
bardziej kosztown operacj jest znalezienie ich wszystkich ni wstrzymanie
zczenia semi-join, tu po znalezieniu pierwszej pasujcej pary.

260

Rozdzia 7. Tworzenie diagramw i optymalizacja zoonych zapyta SQL

Dlatego jeli zczenie semi-join jest skierowane ku grze, nie powinno si zamienia
zcze tego typu na zwyke zczenia, za wyjtkiem sytuacji, gdy wspczynnik zczenia szczegw dla zczenia semi-join jest bliski 1,0 lub nawet nieco mniejszy.
Aby dokoczy tworzenie diagramu podzapytania typu EXISTS, musimy mie kilka regu pozwalajcych nam oszacowa wspczynnik korelacji oraz skorygowany wspczynnik filtrowania podzapytania. W oszacowaniu wspczynnika korelacji moe nam
pomc opisana poniej procedura.
1. Dla zczenia typu semi-join, niech D bdzie wspczynnikiem zczenia
szczegw, M wspczynnikiem zczenia tabeli nadrzdnej. Niech S bdzie
najlepszym (najmniejszym) wspczynnikiem filtrowania spord wszystkich
wzw podzapytania oraz niech R bdzie najlepszym (najmniejszym)
wspczynnikiem filtrowania wszystkich wzw zapytania zewntrznego.
2. Jeli DS < MR to wspczynnik korelacji bdzie rwny (DS)/(MR).
3. Natomiast jeli S > R, wspczynnik korelacji bdzie rwny S/R.
4. W przeciwnym wypadku, niech E bdzie zmierzonym czasem wykonania
najlepszego planu, ktry wiedzie od zapytania zewntrznego do podzapytania
(podajc za logik dziaania EXISTS). Niech I bdzie zmierzonym czasem
wykonania najlepszego planu prowadzcego z zapytania wewntrznego
do zewntrznego (w zgodzie z logik IN). Wwczas wspczynnik korelacji bdzie
rwny I/E. Jeli krok 2. lub 3. pozwoli nam znale przybliony wspczynnik
korelacji, moemy cakiem bezpiecznie okreli, w ktrym kierunku poprowadzi
podzapytanie bez mierzenia czasw wykonania.
Szacunkowa warto uzyskana w kroku 2. i 3. moe nie by tak celna, jak bezporednie zmierzenie czasu wykonania. Jednak szacowanie jest wystarczajce, jeli
tylko dokonywane jest ostronie, tak aby unikn wartoci prowadzcych do
niewaciwego wyboru rda zapytania zewntrznego lub podzapytania. Reguy
przedstawione w kroku 2. oraz 3. s zaprojektowane specjalnie dla przypadkw,
w ktrych takie ostrone, zachowawcze szacowania s wykonalne.

Jeli w kroku 2. lub 3. nie uda si uzyska estymacji, wartoci, ktra bdzie
najbezpieczniejsza i najatwiejsza do uzyskania jest po prostu warto zmierzona.
W takim przypadku, ktry wystpuje do rzadko, znalezienie dobrej wartoci
na podstawie oblicze byoby na tyle skomplikowane, e nie jest warte wysiku.
W momencie znalezienia wspczynnika korelacji musimy sprawdzi, czy potrzebujemy
skorygowanego wspczynnika filtrowania podzapytania i w takim przypadku sprbowa
go ustali:
1. Jeli wspczynnik korelacji jest mniejszy ni 1,0 oraz mniejszy ni wszystkie
pozostae wspczynniki korelacji (w wypadku wielu podzapyta) musimy si
zatrzyma. Wwczas nie potrzebujemy wspczynnika filtrowania podzapytania,
poniewa jest on pomocny jedynie w przypadku, gdy ustalamy, kiedy wyjdziemy
ze zczenia zewntrznego, co nie ma w tej sytuacji zastosowania.

Zapytania z podzapytaniami

261

2. Jeli podzapytanie jest zapytaniem na jednej tabeli bez warunkw filtrowania,


jedynie ze skorelowanym warunkiem zczenia, musimy zmierzy q (liczba wierszy
zapytania zewntrznego z usunitym warunkiem podzapytania) i t (liczba wierszy
penego zapytania, wczajc w to podzapytanie). Wwczas skorygowany
wspczynnik filtrowania podzapytania bdzie rwny t/q. W tym przypadku,
warunek EXISTS jest szczeglnie atwy do sprawdzenia baza danych szuka
w indeksie zczenia pierwszego dopasowania.
3. W przeciwnym przypadku, dla zczenia typu semi-join, niech D bdzie
wspczynnikiem zczenia tabeli szczegowej, a s wspczynnikiem filtrowania
skorelowanego wza (wza przyczonego do zczenia semi-join)
na szczegowym kocu podzapytania.
4. Jeli D 1, skorygowany wspczynnik filtrowania podzapytania bdzie rwny sD.
5. W przeciwnym przypadku, jeli sD < 1, skorygowany wspczynnik filtrowania
podzapytania bdzie rwny (D1+(sD))/D.
6. W przeciwnym przypadku, niech skorygowany wspczynnik filtrowania
podzapytania bdzie rwny 0,99. Nawet najsabszy warunek filtrowania EXISTS
zapobiegnie rozmnoeniu wierszy i oferuje wiksz si filtrowania na jednostk
ni zczenie dolne bez adnych filtrw. Ta ostatnia regua obsuguje wszystkie
pozostae przypadki tego typu. Lepsze to ni nic (zreszt niewiele lepsze).
Tak jak pozostae reguy zawarte w tej ksice, reguy obliczania wspczynnika
korelacji oraz skorygowanego wspczynnika filtrowania podzapytania s reguami
heurystycznymi. Poniewa dokadne wartoci s rzadko potrzebne, aby wybra
dobry plan wykonania, ta starannie zaprojektowana, wydajna heurystyka daje
dobre rozwizanie w co najmniej 90% i praktycznie nigdy nie prowadzi do nieoptymalnego wyboru. Podobnie jak w innych czciach tej ksiki, idealna kalkulacja
zoonego zapytania jest poza zasigiem manualnych metod optymalizacji.

Sprawdmy, czy powysze reguy s zrozumiae w wystarczajcym stopniu, aby ustali


wspczynnik korelacji oraz skorygowany wspczynnik filtrowania podzapytania oraz
uzupeni rysunek 7.31, na ktrym brakuje tych dwch liczb.

Rysunek 7.31. Zoone zapytanie z brakujcymi wartociami dla zczenia semi-join

262

Rozdzia 7. Tworzenie diagramw i optymalizacja zoonych zapyta SQL

Wyniki naszych dziaa moemy porwna z nastpujcym rozwizaniem problemu:


1. Niech D = 2 i M = 1 (brak wartoci na diagramie oznacza 1). Niech S = 0,015
(najlepszy wspczynnik filtrowania z podzapytania naley do wza S3,
ktry znajduje si dwa poziomy poniej rdowej tabeli szczegw podzapytania
tabeli D). Nastpnie ustalmy R = 0,01, ktre jest najlepszym filtrem
na przestrzeni wszystkich wzw drzewa poniej rdowej tabeli szczegw
zapytania zewntrznego M, z ni sam wcznie.
2. Poniewa DS = 0,03 oraz MR = 0,01, DS > MR, przechodzimy do kroku 3.
3. Poniewa S > R, wspczynnik korelacji jest rwny S/R, czyli 1,5.
Aby znale skorygowany wspczynnik filtrowania podzapytania, wykonajmy nastpujce
czynnoci:
1. Zauwaamy, e wspczynnik korelacji jest wikszy ni 1, wic przechodzimy
do kroku 2.
2. Zauwaamy, e podzapytanie zoone jest z wielu tabel i filtrw,
tote przechodzimy do punktu 3.
3. Znajdujemy D = 2 oraz wspczynnik filtrowania na wle D s = 0,1.
4. Zauwaamy, e D > 1, wic przechodzimy do kroku 5.
5. Obliczamy sD = 0,2, co jest wartoci mniejsz ni 1, a wic szacujemy
skorygowany wspczynnik filtrowania podzapytania przez (D 1+(sD))/D =
(21+(0,12))/2 = 0,6.
W jednym z nastpnych podrozdziaw, dotyczcym optymalizacji podzapyta EXISTS,
poka optymalizacj caego diagramu z rysunku 7.32.

Tworzenie diagramw dla podzapyta NOT EXISTS


Warunek podzapytania, ktry mona wyrazi przez NOT EXISTS lub te NOT IN s pod
jednym wzgldem prostsze ni podzapytania typu EXISTS nie mona wyj z podzapytania ku zapytaniu zewntrznemu. Eliminuje to potrzeb znajdowania wspczynnika
korelacji. Litera E, symbolizujca podzapytanie typu EXISTS, jest zamieniona przez N,
oznaczajce warunek podzapytania typu NOT EXISTS, a wspczynnik korelacji jest
znany jako zczenie typu anti-join, poniewa poszukuje ono przypadku, w ktrym zczenie z wierszami podzapytania nie znajdzie adnych elementw pasujcych.
Okazuje si, e niemal zawsze lepiej jest wyraa zapytania typu NOT EXISTS, warunkiem
NOT EXISTS ni warunkiem NOT IN. Rozwamy nastpujcy szablon podzapytania NOT IN:
SELECT ...
FROM ... Outer_Anti_Joined_Table_Order Outer
WHERE ...
AND Outer.Some_Key NOT IN (SELECT Inner.Some_Key
FROM ... Subquery_Anti_Joined_Table Inner WHERE
<Warunki_I_Zlaczenia_Jedynie_Na_Tabelach_Podzapytania>)
...

Zapytania z podzapytaniami

263

Moemy i powinnimy wyrazi to zapytanie w rwnowanej formie NOT EXISTS:


SELECT ...
FROM ... Outer_Anti_Joined_Table_Order Outer
WHERE ...
AND Outer.Some_Key IS NOT NULL
AND NOT EXISTS (SELECT null
FROM ... Subquery_Anti_Joined_Table Inner WHERE
<Warunki_I_Zlaczenia_Jedynie_Na_Tabelach_Podzapytania>)
AND Outer.Some_Key = Inner.Some_Key)

Aby zamieni zapytanie NOT IN na NOT EXISTS bez zmian funkcjonalnoci, musimy
doda warunek NOT NULL na kluczu zczenia skorelowanego w tabeli zewntrznej. Dzieje si tak, poniewa warunek NOT IN jest rwnowany serii warunkw
rny-od poczonych za pomoc OR, ale wedug bazy danych warunek NULL!=
<JakasWartosc> nie jest prawdziwy, a wic forma NOT IN odrzuca wszystkie
wiersze zapytania zewntrznego dziki kluczowi skorelowanemu o wartoci null.
Ten fakt nie jest powszechnie znany, wic moliwe jest, e prawdziw intencj
twrcy takiego zapytania byo wczenie w rezultat zapytania tych wierszy, ktre
forma NOT IN odrzuca. Po zamianie form mamy dobr okazj, aby wyszuka i naprawi tego typu bdy.

Oba warunki podzapytania, typu EXISTS i NOT EXISTS, zaprzestaj poszukiwa pasujcych wierszy tu po znalezieniu pierwszego dopasowania, jeli tyko takie istnieje.
Warunki podzapyta typu NOT EXISTS s potencjalnie bardziej pomocne we wczesnych
fazach planu wykonania, poniewa kiedy odpowiednie wiersze znalezione s wczenie,
zapytanie odrzucajc je sprawia, e pniejsze kroki planu wykonania odbywaj si
szybciej. W przypadku warunku EXISTS, baza danych musi sprawdzi kad moliwo
pasujcych do siebie wierszy, po czym wszystkie je odrzuca, co jest duo kosztowniejsz
operacj, gdy istnieje wiele szczegw na wiersz nadrzdny, zczone przez zczenie
semi-join. Zapamitajmy nastpujce reguy, ktre porwnuj warunki EXISTS i NOT
EXISTS wskazujce na tabele detali z nadrzdnej tabeli zapytania zewntrznego:
Nieselektywny warunek EXISTS nie jest kosztowny przy testowaniu
(poniewa atwo znajduje dopasowanie, zazwyczaj na pierwszym wierszu
zczonym przez semi-join), ale odrzuca niewiele wierszy z zapytania
zewntrznego. Im wicej wierszy zwrcioby izolowane podzapytanie,
tym mniej kosztowny i selektywny jest warunek EXISTS. Warunek EXISTS,
ktry cechowaby si du selektywnoci, byby take kosztowny w sprawdzaniu,
gdy musi on odrzuci dopasowanie na kadym wierszu szczegw.
Selektywny warunek NOT EXISTS nie jest kosztowny przy sprawdzaniu
(poniewa atwo znajduje dopasowania, zazwyczaj ju na pierwszym wierszu
zczonym przez semi-join) i odrzuca wiele wierszy z zapytania zewntrznego.
Im wicej wierszy zwrcioby izolowane podzapytanie tym mniej kosztowny
i bardziej selektywny jest warunek EXISTS. Z drugiej strony, mao selektywne
warunki NOT EXISTS s kosztowne w sprawdzaniu, gdy musz potwierdzi
brak dopasowania dla kadego wiersza szczegw.

264

Rozdzia 7. Tworzenie diagramw i optymalizacja zoonych zapyta SQL

Poniewa konwersja warunkw podzapytania typu NOT EXISTS na rwnowane proste


zapytanie nie zawierajce podzapyta, jest trudna i mao wynagradzajca, czsto uywa
si podzapyta NOT EXISTS na obu kocach zczenia anti-join na kocu tabeli nadrzdnej i tabeli szczegw. Rzadko istnieje potrzeba poszukiwania innych sposobw
wyraenia warunku NOT EXISTS.
Poniewa selektywne warunki NOT EXISTS nie s kosztowne przy sprawdzaniu, okazuje si,
e oszacowanie skorygowanego wspczynnika filtrowania podzapytania jest cakiem atwe:
1. Naley zmierzy q (liczba wierszy zapytania zewntrznego z usunitym
warunkiem podzapytania typu NOT EXISTS) i t (liczba wierszy penego zapytania,
wczajc w to podzapytanie). Niech C bdzie liczb tabel w klauzuli FROM
podzapytania (zazwyczaj dla warunkw NOT EXISTS jest to jedna tabela).
2. Ustalmy skorygowany wspczynnik filtrowania podzapytania na (C1+(t/q))/C.

Optymalizacja zapyta zawierajcych podzapytania


Podobnie jak w przypadku prostych zapyta, optymalizacja zapyta zoonych z podzapytaniami jest cakiem prosta, jeli tylko dysponujemy odpowiednim diagramem zapytania.
Poniej przedstawiono niezbdne kroki postpowania dla optymalizacji zoonych zapyta z podzapytaniami, ktre pozwalaj utworzy kompletny diagram zapytania.
1. Naley zamieni kady warunek NOT IN na rwnowany warunek NOT EXISTS,
wedug wczeniejszego szablonu.
2. Jeeli zczenie skorelowane jest typu EXISTS, a podzapytanie znajduje si
na nadrzdnym kocu tego zczenia (strzaka porednia jest skierowana ku doowi),
trzeba zamieni zapytanie zoone na proste, tak jak pokazano to wczeniej
oraz zoptymalizowa je, uywajc zwykych regu dla prostych zapyta.
3. W przeciwnym przypadku, jeli zczenie skorelowane jest typu EXISTS,
naley znale najniszy wspczynnik korelacji spord wszystkich zapyta
typu EXISTS (jeli tylko istnieje wicej ni jeden). Jeli ten najmniejszy
wspczynnik korelacji jest mniejszy ni 1,0, musimy zamieni ten warunek
podzapytania na rwnowany warunek IN i wyrazi pozostae warunki
podzapyta typu EXISTS poprzez jawne wykorzystanie warunku EXISTS.
Nastpnie musimy zoptymalizowa nieskorelowane podzapytanie typu IN,
tak jakby byo ono samodzielnym zapytaniem jest to punkt pocztkowy planu
wykonania caego zapytania. Po zakoczeniu wykonywania podzapytania
nieskorelowanego, baza danych przeprowadzi operacj sortowania, aby odrzuci
z listy wygenerowanej przez podzapytanie, zduplikowane klucze skorelowania.
Nastpnym krokiem w zczeniu, po ukoczeniu pierwszego podzapytania,
jest skorelowany klucz w zapytaniu zewntrznym, wykorzystujc do tego indeks
na kluczu tego zczenia. Od tego momentu zapytanie zewntrzne naley
traktowa jak gdyby rdowe podzapytanie nie istniao i jakby pierwszym
wzem bya rdowa tabela zapytania zewntrznego.

Zapytania z podzapytaniami

265

4. Jeli wszystkie wspczynniki korelacji s wiksze lub rwne 1,0 lub jeli warunki
podzapytania s jedynie typu NOT EXISTS, tabel rdow wybieramy z zapytania
zewntrznego, tak jakby zapytanie to nie miao adnych warunkw podzapytania,
zgodnie ze zwykymi reguami odnoszcymi si do prostych zapyta.
5. W momencie osignicia wzw zapytania zewntrznego, ktre zawiera
zczenia semi-join lub anti-join z jeszcze niewykonanymi podzapytaniami,
cae podzapytanie naley traktowa, jakby byo ono pojedynczym, podczonym
od dou wzem (nawet jeli zczenie skorelowane jest w rzeczywistoci grne).
Przy wyborze momentu wykonania pozostaych podzapyta powinno si przyj,
e ten wirtualny wze ma wspczynnik filtrowania rwny skorygowanemu
wspczynnikowi filtrowania podzapytania.
Poniewa podzapytania skorelowane zatrzymuj si na pierwszym pasujcym wierszu
jeli takowy istnieje zapobiegaj ryzyku rozmnoenia wierszy, charakterystycznego dla normalnych zcze grnych, i mog zmniejszy liczb wierszy bdcych
w obiegu. Jednak poniewa czsto zachodzi konieczno sprawdzenia wielu
wierszy, aby uzyska taki efekt filtrowania, prawdziwa warto skorygowanego
wspczynnika filtrowania podzapytania czyni ten wirtualny wze rwnowany
wzowi niemal nieprzefiltrowanemu (jeli rozpatruje si wspczynnik zysku
do kosztu).

6. Tu po umieszczeniu zczenia skorelowanego w porzdku zczenia w oparciu


o krok 5., natychmiast naley wykona pozosta cz tego skorelowanego
podzapytania, optymalizujc plan wykonania podzapytania z wzem
skorelowanym jako wzem rdowym. Po zakoczeniu podzapytania wracamy
do zapytania zewntrznego i kontynuujemy optymalizacj pozostaej czci
porzdku zczenia.
Jako przykad, rozwamy rysunek 7.32, ktry jest po prostu uzupenionym rysunkiem
7.31, z wypenionymi wartociami wspczynnika korelacji oraz skorygowanego wspczynnika filtrowania podzapytania.

Rysunek 7.32. Przykadowy problem optymalizacji zoonego zapytania z podzapytaniem

266

Rozdzia 7. Tworzenie diagramw i optymalizacja zoonych zapyta SQL

Poniewa zczenie skorelowane jest typu EXISTS, krok 1. nie ma tu zastosowania. Podobnie, poniewa strzaka porednia zczenia semi-join jest skierowana ku grze, krok 2.
take nie ma tu racji bytu. Najniszy (jedyny) wspczynnik korelacji jest rwny 1,5
(tu obok E), tak wic i krok 3. nie mona tu zrealizowa. Przechodzc do kroku 4.,
znajdujemy, e najlepszym wzem rdowym zapytania zewntrznego jest M. W kroku
5. wybieramy pomidzy zczeniami dolnymi z A1 i A2, ze wspczynnikami filtrowania
rwnymi odpowiednio 0,2 i 0,7, a zczeniem dolnym z wirtualnym wzem reprezentujcym cae podzapytanie, o wirtualnym wspczynniku filtrowania rwnym 0,6.
A1 jest najlepszym spord tych trzech kandydatw, poniewa ma najodpowiedniejszy
wspczynnik filtrowania, a wic czymy si z nim w nastpnej kolejnoci. Poniewa nie
osigniemy adnego wza idc ku doowi od A1, nastpnym kandydatem do zczenia jest
podzapytanie (wykorzystujc krok 5.), a wic wykonujemy zczenie semi-join z wzem D.
Stosujc si do kroku 6. procedury (gdy rozpoczlimy podzapytanie), musimy dalej
poda t ciek, wychodzc od D jako od wza rdowego. Wykorzystujc w obrbie tego podzapytania reguy dla prostych zapyta, czymy si z S1, S3, S2 i S4, w tym
porzdku. Wracamy do zapytania zewntrznego, stosujc reguy dla prostych zapyta
i znajdujemy pozostay porzdek zczenia A2, B1, B2. Zatem cay, optymalny plan
zczenia, uwzgldniajc zczenia semi-join, ma posta (M, A1, D, S1, S3, S2, S4,
A2, B1, B2).

Czy trzeba si przejmowa podzapytaniami?


Reguy odnoszce si do podzapyta s tak skomplikowane, e a zniechcajce do
ich stosowania, dlatego chciabym si przyzna do czego, co by moe polepszy samopoczucie Czytelnika. Na przestrzeni 10 lat zoptymalizowaem zapytania SQL zawierajce
podzapytania bez koniecznoci stosowania takich formalnych regu, podajc wycznie za intuicj i generaln regu wyboru pomidzy wyjciem z podzapytania lub
z zapytania zewntrznego, ktra to regua opiera si na wyborze najbardziej selektywnego warunku. Zazwyczaj nie przejmuj si zbytnio momentem wykonania podzapyta,
za wyjtkiem przypadkw gdy powinny one by rdem caego zapytania, poniewa
taka kontrola jest zazwyczaj bardzo utrudniona a zysk okazuje si niewielki, w porwnaniu z sytuacj, gdy wybr pozostawimy automatycznemu optymalizatorowi.
Czasami (rzadziej jednak ni mogoby si wydawa) udaje mi si rozpozna przypadki
lece na pograniczu, dla ktrych wyprbowanie rnych alternatyw ma sens.
To samo podejcie moe zadziaa i u Czytelnika. Jeli jednak nie mamy zaufania
do swojej intuicji lub chcemy mie dla niej jakie oparcie, te formalne reguy oka si
przydatne. Reguy zawarte w tym rozdziale, ktre stworzyem specjalnie na potrzeby
tej ksiki, s efektywne w penym zakresie rzeczywistych zapyta oraz zapewniaj
sensowny kompromis pomidzy matematyczn perfekcj a uytecznoci. Jedynie
pena kalkulacja moe rozwiza pen zoono problemu w sposb idealny, bez
wykorzystania metody prb i bdw. Jednak powysze reguy daj co w rodzaju
automatycznej intuicji, ktra, jeli tylko si chce, jest rwnie dobra, co ta stosowana
przeze mnie.

Zapytania z widokami

267

Zapytania z widokami
Widok moe spowodowa, e dowolnie skomplikowane zapytanie bdzie wygldao jak
prosta tabela, z punktu widzenia osoby piszcej zapytanie wykorzystujce ten widok.
Kiedy wiele zapyta wspdzieli jak cz planu wykonania SQL, wspdzielone widoki
wielokrotnego uytku mog by bardzo silnym mechanizmem redukujcym zoono
kodu aplikacji. Niestety, ukrywanie pewnych dziaa przed okiem programisty nie
zmniejsza skomplikowania krokw niezbdnych do osignicia rzeczywistych danych.
Z drugiej strony, ukrywanie zoonoci przed programist najprawdopodobniej nie
zwikszy trudnoci problemu, ktry optymalizator, czy to automat, czy te czowiek,
musi pokona, aby znale szybki plan wykonania. W dyskusji tej odnosi si bd do
dwch zapyta wanych dla problemu optymalizacji. S to zatem:
Zapytania tworzce widoki
Zapytania, ktre stanowi podstaw dla widokw (zapytania uywane do tworzenia widokw za pomoc CREATE VIEW <NazwaWidoku> AS <ZapytanieDefiniujaceWidok>).
Zapytania wykorzystujce widoki
S to zapytania, ktre naley optymalizowa i ktre s wykonywane przez baz danych. Odwouj si one do widokw w klauzuli FROM (na przykad SELECT ... FROM
Widok1 V1, Widok2 V2, ... WHERE ...).
Czsto jestem proszony o optymalizacj lub oszacowanie wydajnoci zapytania
definiujcego widok bez listy zapyta z niego korzystajcych. Nierzadko te prosi
si mnie o optymalizacj zapyta wykorzystujcych widoki bez wiedzy odnonie
zapyta tworzcych widoki. adna z prb nie jest moliwa do spenienia adne zapytanie definiujce widok, ktre jest bardziej skomplikowane ni SELECT
<ListaProstychKolumn> FROM <PojedynczaTabela>, nie zadziaa dobrze
w kadym moliwym zapytaniu wykorzystujcym ten widok. Podobnie, adne
zapytanie wykorzystujce jaki widok nie zadziaa poprawnie, jeli zapytanie tworzce widok koliduje z wydajn drog do osignicia potrzebnych danych.
Dla danego widoku musimy zna i zoptymalizowa kade zapytanie wykorzystujce
ten widok, abymy mogli powiedzie, e zapytanie je definiujce jest w tym kontekcie cakowicie poprawne. Analogicznie, musimy zna zapytanie definiujce
kady uyty widok, abymy mogli stwierdzi, czy zapytanie wykorzystujce te
widoki jest poprawne.

Kiedy optymalizujemy SQL, widoki zwikszaj zazwyczaj zoono na jeden z trzech


sposobw:
W celu utworzenia optymalnego diagramu zcze, zachodzi potrzeba zamiany
zapytania wykorzystujcego widok na zapytanie rwnowane, wykorzystujce
rzeczywiste tabele.

268

Rozdzia 7. Tworzenie diagramw i optymalizacja zoonych zapyta SQL

Zapytania do widokw czsto zawieraj w szkielecie zapytania zbdne wzy.


Kady widok niesie ze sob cae zapytanie, ktre je definiuje, wraz z caym
poddrzewem zoonym z wszystkich definiujcych widok wzw i zcze.
Uycie widoku oznacza uycie caego poddrzewa. Jednake programista
wykorzystujcy ten widok moe potrzebowa tylko kilku kolumn widoku
i moe omin jak liczb wzw i zcze w zapytaniu definiujcym widok,
jeli napisze rwnowane zapytanie do zwykych tabel. Kiedy aplikacja potrzebuje
wszystkich wzw widoku, wci zachodzi prawdopodobiestwo, e zapytanie
wykorzystujce widok dotyka te wzy w mao efektywny sposb, czc si z tymi
samymi wierszami tych samych, lecych u podstawy widoku, tabel w wielu
ukrytych kontekstach. Przykad bdzie przedstawiony w czci Nadmiarowe
operacje odczytu w zapytaniach wykorzystujcych widoki.
Czasami zapytania wykorzystujce widoki nie mog by w prosty sposb
wyraone poprzez rwnowane zapytania do zwykych tabel. Zazwyczaj takie
przypadki, w ktrych zapytania do widokw zwracaj inne rezultaty
ni zapytania do tabel, s sporadyczne. Jednake rezultaty poprawne w takich
przypadkach nie s uzyskiwane z zapyta do widokw! Kiedy zapytanie
do widokw nie pozwala si dobrze rozoy na proste, rwnowane zapytanie
do tabel, wydajno takiego zapytania jest zazwyczaj niska, a te sporadyczne
przypadki, ktre definiuj funkcjonalno specyficzn dla poszczeglnych
widokw, s zazwyczaj bdne. Tak czy inaczej, aby poprawi wydajno
za pomoc niemal rwnowanego prostego zapytania do tabel, wymagane
s zwykle drobne zmiany w funkcjonalnoci i trzeba by szczeglnie ostronym,
aby nie wprowadzi jakiego nowego bdu. (Pomimo tego, e poprawia si wicej
bdw ni si ich tworzy, ich ilo i tak wzrasta!) Odpowiedni przykad bdzie
przedstawiony w podrozdziale Zczenia zewntrzne z widokami.

Tworzenie diagramw dla zapyta


wykorzystujcych widoki
Tworzenie diagramw dla zapyta wykorzystujcych widoki jest relatywnie proste, chocia
czasem mczce. Poniej przedstawiono instrukcj postpowania w takich wypadkach.
1. Utworzy diagram kadego zapytania definiujcego widok, tak jakby byo
ono zapytaniem samodzielnym. Kady diagram, ktry definiuje widok powinien
by zwyczajny, tzn. powinien mie jedn rdow tabel szczegw, a zczenia
powinny by typu wiele-do-jednego i powinny by skierowane ku doowi,
od wza gwnego. Jeli zapytanie definiujce widok nie mapuje si na szkielet
normalnego zapytania, zapytania wykorzystujce ten widok bd
najprawdopodobniej miay nisk wydajno i bd zwracay bdne rezultaty.
Klucz gwny rdowej tabeli szczegw dla zapytania definiujcego widok
naley traktowa jak wirtualny klucz gwny caego widoku.
2. Utworzy diagram zapytania wykorzystujcego widok, tak jakby kady widok
by zwyk tabel. Zczenie z widokiem powinno mie strzak na kocu
przy widoku (widok powinien si znajdowa na niszym kocu poczenia)

Zapytania z widokami

269

tylko wtedy, gdy czy si z wirtualnym kluczem gwnym widoku. Symbolicznie


mona pokaza warunki filtrowania widoku w zapytaniu wykorzystujcym widoki
jako liter F, nie zaprztajc sobie gowy dokadnym wyznaczaniem wspczynnikw
filtrowania. Warto narysowa przerywan lini kko wok kadego widoku.
3. Rozszerzy diagram zapytania wykorzystujcego widoki z kroku 2. procedury,
zastpujc kady wze reprezentujcy widok przez cay diagram zapytania
definiujcego widok z kroku 1., wraz z przerywan lini dokoa tego diagramu.
Kade zczenie od gry bdzie zczone z poddrzewem definiujcym widok
w rdowym wle szczegw. Zczenia wychodzce ku doowi od widokw
mog si czy z dowolnym wzem widoku, w zalenoci od tego, ktra spord
tabel z zapytania definiujcego widok ma klucz obcy zczenia (w licie SELECT
definiujcej widok). Dowolny warunek filtrowania na widoku staje si warunkiem
filtrowania na odpowiadajcym wle zapytania definiujcego widok, w zalenoci
od tego, ktr kolumn wza warunek filtrowania uwzgldnia. Dla kadego z tych
warunkw znajdujemy wspczynnik filtrowania w standardowy sposb,
tj. rozwijajc symbol F na wynikowym diagramie zapytania. Ewentualnie mona
poczy wspczynnik filtrowania zapytania definiujcego widok oraz zapytania
go wykorzystujcego, jeli te dwa zapytania posiadaj dwa rne filtry
na tym samym wle.
Reguy te mog si wydawa abstrakcyjne i skomplikowane, ale przykad powinien sprawi, e cay proces stanie si janiejszy. Rozwamy nastpujce dwie definicje widokw:
CREATE VIEW Shipment_V AS
SELECT 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 Shipment_ZIP,
S.Shipment_Date, S.Shipment_ID
FROM Shipments S, Addresses A
WHERE S.Address_ID = A.Address_ID
CREATE VIEW Recent_Orders_V AS
SELECT 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_Name,
C.Address_ID Customer_Address_ID, OT.Text Order_Status
FROM Orders O, Customers C, Code_Translations OT
WHERE O.Customer_ID = C.Customer_ID
AND O.Status_Code = OT.Code
AND OT.Code_Type = 'STATUS_ZAMOWIENIA'
AND O.Order_Date > SYSDATE - 366

W pierwszym kroku postpowania musimy utworzy diagramy tych definiujcych


widoki zapyta, tak jak pokazano to na rysunku 7.33. Te diagramy zapyta zostay
utworzone w oparciu o reguy opisane w rozdziale 5. przy uyciu tych samych wspczynnikw filtrowania i tych samych statystyk zczenia, co dla odpowiedniego przykadu z rysunku 5.5.

270

Rozdzia 7. Tworzenie diagramw i optymalizacja zoonych zapyta SQL

Rysunek 7.33. Diagramy zapyta dla przykadowych zapyta definiujcych widoki

Zapytanie wykorzystujce utworzone widoki moe mie zatem posta:


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_Address_Line1,
SV.Shipment_Street_Address_Line2, SV.Shipment_City_Name,
SV.Shipment_State, SV.Shipment_ZIP, OD.Deferred_Ship_Date,
OD.Item_Count, ODT.Text, P.Prod_Description, SV.Shipment_Date
FROM Recents_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
AND OV.Customer_ID = C.Customer_ID
AND OD.Product_ID = P.Product_ID(+)
AND OD.Shipment_ID = SV.Shipment_ID(+)
AND OD.Status_Code = ODT.Code
AND ODT.Code_Type = 'DOKLADNY_STATUS_ZAMOWIENIA'
ORDER BY OV.Customer_ID, OV.Order_ID Desc, OD.Shipment_ID,
OD.Order_Details_ID

Przechodzc do kroku 2. procedury, tworzymy pocztkowy diagram zapytania, traktujc widoki jak zwyke tabele, w taki sposb, jak na rysunku 7.34.

Rysunek 7.34. Nierozwinity diagram zapytania wykorzystujcego widok

Zamiemy kady wze odpowiadajcy widokowi na rysunku 7.34 przez diagramy


zapyta definiujcych te widoki z rysunku 7.33 oraz otoczmy kade zapytanie definiujce
widok przerywan lini, tak aby pokaza granice widoku. Uwzgldnijmy zapytania definiujce widoki w pozostaej czci caego diagramu, podczajc je do odpowiednich
wzw-tabel, w zalenoci od tego, ktra tablica w zapytaniu tworzcym widok zawiera klucz czcy. Normalnie, kade zczenie z widokiem, przychodzce z gry, bdzie

Zapytania z widokami

271

zakotwiczone w rdowej tabeli szczegw zapytania definiujcego ten widok. Jednake


wzy tabel nadrzdnych, ktre poczone s w widokiem od dou (na przykad wze C na
rysunku 7.34) mog si czy z dowolnym wzem szkieletu definiujcego widok, w zalenoci od tego, ktra tabela zawiera klucz obcy wskazujcy na wze nadrzdny. Dodajmy
liczbowe wspczynniki filtrowania do kadego wza szkieletu zapytania, niezalenie
od tego czy nale do zapytania definiujcego czy te wykorzystujcego widok. Na rysunku 7.35 wspczynnik filtrowania rwny 0,3 tu obok wza O pochodzi z filtra wystpujcego w zapytaniu definiujcym widok, podczas gdy wspczynnik 0,0002 tu obok wza C
pochodzi z warunku (na imi i nazwisko klienta) zapytania korzystajcego z widoku.

Rysunek 7.35. Rozwinity diagram zapytania wykorzystujcego widok

Graficzny rezultat naszego przykadu powinien wyglda jak na rysunku 7.35, na ktrym
dodaem gwiazdk do umieszczonego najbardziej na lewo wza C, aby podkreli rnic
pomidzy dwoma tak samo oznaczonymi wzami. Ponownie statystyki dla filtra na wle
klienta zapoyczyem z przykadu pokazanego wczeniej na rysunku 5.5, uzyskujc w ten
sposb wspczynnik 0,0002 tu obok C w najbardziej na prawo wysunitym szkielecie.
Te czynnoci pozwalaj nam ukoczy diagram, ktrego utworzenie jest niezbdne, aby
kontynuowa optymalizacj zapytania wykorzystujcego widok, tak bymy mogli zadecydowa, czy do otrzymania optymalnego planu konieczne s zmiany w zapytaniu
definiujcym widok, czy te w zapytaniu wykorzystujcym widok.

Optymalizacja zapyta z widokami


Przewanie optymalny plan wykonania dla zapytania wykorzystujcego widoki jest
dokadnie tym samym planem, ktry uzyskalibymy, gdyby wystpoway w nim tylko
zwyke tabele. Jednake istniej cztery utrudnienia, z ktrymi by moe bdziemy musieli si zmierzy:
Niektre zczenia ze zoonymi widokami s trudne do wyraenia w postaci
prostych zcze do prostych tabel. W szczeglnoci s to zczenia zewntrzne
z widokami, ktre same maj zczenia w zapytaniu je definiujcym. Problem ten
dotyka take naszego przypadku, a jego wyjanienie bdzie mona znale si
w podrozdziale Zczenia zewntrzne z widokami.

272

Rozdzia 7. Tworzenie diagramw i optymalizacja zoonych zapyta SQL

Niektre widoki odnosz si do dokadnie tych samych wierszy, tej samej tabeli,
co jaka inna tabela w zapytaniu wykorzystujcym te widoki, czego rezultatem
jest wykonywanie zbytecznej pracy przez baz danych (efekt, ktry powinnimy
usun). Taki przypadek wystpuje na diagramie 7.35 dla wzw C* oraz C.
Problemem tym zajmiemy si rwnie dalszym fragmencie tej publikacji.
Zalet widokw, z perspektywy tworzenia oprogramowania jest to, e ukrywaj
zoono problemu, ale niestety dokadnie ta zaleta sprawia, e tworzenie
nadmiarowych zcze jest bardzo atwe. Przy wykorzystaniu jedynie zwykych
tabel sytuacja taka byaby atwa do zauwaenia i wymagaaby duo wicej pracy,
gdybymy chcieli j ponowi.
Wzy znajdujce si w obrbie zapytania definiujcego widok oraz zczenia
do nich prowadzce s czsto zbyteczne w uzyskiwaniu rezultatw zapytania,
ktre wykorzystuje ten widok.
Uywanie widokw ogranicza nasz kontrol nad planem wykonania.
Jeli zmienimy zapytanie definiujce widok, tak aby poprawi plan wykonania
zapytania wykorzystujcego ten widok, moemy przez przypadek obniy
wydajno innych zapyta go wykorzystujcych. Zawsze moemy utworzy
nowy widok do uycia tylko w obrbie jednego zapytania, ale powoduje
to zaprzepaszczenie korzyci pyncych z moliwoci wspdzielenia widokw.
Oglnie rzecz biorc wskazwki SQL oraz inne zmiany w zapytaniu
wykorzystujcym widoki nie wpywaj na sposb w jaki baza danych uzyskuje
dostp do tabel tego zapytania. Czasem, aby otrzyma wydajny plan wykonania,
niezbdne jest usunicie widokw.

Zczenia zewntrzne z widokami


Powracajc do wczeniejszego przykadu, zastanwmy si, co tak naprawd znaczy zczenie zewntrzne z widokiem Shipment_V, ktry jest z kolei zczeniem wewntrznym
pomidzy tabelami Shipments i Addresses. Poniewa baza danych musi zachowywa
si tak, jak gdyby widok by rzeczywist tabel o dokadnie takich wierszach jakie ma
widok, zczenie znajduje wewntrzny przypadek tych Shipment_ID, ktre istniej w tabeli
Shipments i wskazuj na dostawy o wartociach Address_ID pasujcych do tabeli
Addresses. Jeli baza danych nie bdzie moga znale zczenia z tabelami Shipments
i Addresses, zczenie z widokiem stanie si cakowicie zczeniem zewntrznym (z oboma tabelami), nawet jeli pierwotne zczenie z tabel Shipments nie zakoczyo si
sukcesem. W poszukiwaniu planu zagniedonych ptli, baza danych nie moe wiedzie, czy zczenie zewntrzne znajdzie przypadek wewntrzny a do momentu poczenia si z powodzeniem do obu tabel w zapytaniu definiujcym widok.
Niestety, przypadek ten jest zbyt skomplikowany, aby mg by obsuony automatycznie, dlatego te baza danych moe po prostu zaprzesta poszukiwania planu zagniedonych ptli. Co wicej, baza danych powinna uwzgldni, e niezalenie od tego jak
bardzo skomplikowana jest leca u podstaw logika, nie moe popeni bdu w takich
zoonych przypadkach jak ten, jeli pobierze kady wiersz z zapytania definiujcego

Zapytania z widokami

273

widok i bdzie traktowa rezultat jakby pochodzi z rzeczywistej tabeli. Dla zcze
zewntrznych z widokami, baza danych wykorzystuje zazwyczaj do poczenia z t
tymczasow tabel zczenie sortujco-scalajce lub mieszajce. Takie dziaanie jest zazwyczaj bezpieczne, gdy chodzi o funkcjonalno, ale dla wydajnoci jest nierzadko
katastrofalna w skutkach, chyba e zapytanie definiujce widok jest szybkie jako zapytanie samodzielne.
Jako generaln regu dla utrzymania wydajnoci warto przyj, i naley unika
zcze zewntrznych z kadym widokiem, ktry jest bardziej skomplikowany
ni proste SELECT <ListaProstychKolumn> FROM <PojedynczaTabela>.

Podobne problemy wystpuj w przypadku wszystkich zcze z widokami, ktre zawieraj UNION lub GROUP BY w zapytaniu definiujcym widok. Chocia trzeba przyzna,
i zczenia wychodzce od takich widokw zazwyczaj dziaaj dobrze, pod warunkiem,
e zawieraj tabel, ktr wybralibymy jako rdow tabel zapytania.
Przeanalizujmy ponownie zapytanie wykorzystujce widoki z poprzedniego podrozdziau.
Jeli wczymy zapytanie definiujce widok Shipment_V do zapytania wykorzystujcego
widok w celu rozwizania problemw wydajnociowych zwizanych ze zczeniem zewntrznym, moemy spodziewa si nastpujcych rezultatw:
SELECT OV.Customer_Main_Phone, C.Honorific, OV.Customer_First_Name,
OV.Customer_Main_Phone, C.Suffix, OV.Customer_Address_ID,
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 Shipment_ZIP, OD.Deferred_Ship_Date, OD.Item_Count,
ODT.Text, P.Prod_Description, S.Shipment_Date
FROM Recent_Orders_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_ID
AND OV.Customer_ID = C.Customer_ID
AND 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.Code
AND ODT.Code_Type = 'DOKLADNY_STATUS_ZAMOWIENIA'
ORDER BY OV.Customer_ID, OD.Order_ID Desc, S.Shipment_ID, OD.Order_Detail_ID

Niestety, wynik tego zapytania nie jest dokadnie taki, jak zapytania pocztkowego, ze
wzgldu na szczeglne cechy zcze zewntrznych z widokami. W szczeglnoci zapytanie
oryginalne zwraca Shipment_Date o wartoci null za kadym razem, gdy zczenie caego widoku (wczajc w to zczenie z tabel Addresses) z tabel Order_Details nie
powiedzie si. Dlatego za kadym razem, gdy dostawa nie ma poprawnego, niepustego
Address_ID, oryginalne zapytanie zwrci dla Shipment_Date warto null pomimo tego, e zczenie z Shipments jest poprawne.

274

Rozdzia 7. Tworzenie diagramw i optymalizacja zoonych zapyta SQL

Z du pewnoci mona powiedzie, e to dziwne zachowanie nie byo intencj programisty i nie jest funkcjonalnie niezbdne, dlatego powysza forma najprawdopodobniej
zadziaa poprawnie, a nawet lepiej ni orygina w tym szczeglnym przypadku. Jednak jakakolwiek zmiana funkcjonalnoci dla poprawienia wydajnoci jest dziaaniem
niebezpiecznym. Dlatego przed dokonaniem zmiany, takiej jak przed chwil opisanej,
ktra wcza zapytanie definiujce widok w gwne zapytanie SQL, naley si upewni,
czy nowe zachowanie w takich kracowych przypadkach jest poprawne oraz ostrzec programistw informujc ich, e zmiana moe spowodowa, i testy zwrc inne rezultaty.
W mao prawdopodobnym przypadku, gdy oryginalne zachowanie jest naprawd potrzebne lub gdy nie chcemy zagbia si w analiz poprawnoci pierwotnego zachowania
przypadkach kracowych, mona idealnie emulowa oryginaln funkcjonalno zapytania w nastpujcy sposb:
SELECT OV.Customer_Main_Phone, C.Honorific, OV.Customer_First_Name,
OV.Customer_Main_Phone, C.Suffix, OV.Customer_Address_ID,
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 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_Date
FROM Recent_Orders_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_ID
AND OV.Customer_ID = C.Customer_ID
AND 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.Code
AND ODT.Code_Type = 'DOKLADNY_STATUS_ZAMOWIENIA'
ORDER BY OV.Customer_ID, OD.Order_ID Desc,
DECODE(A.Address_ID, NULL, TO_NUMBER(NULL), S.Shipment_ID),
OD.Order_Detail_ID

Powysze zapytanie zawiera dwie zmiany, ktre powoduj e zwrcone rezultaty s


takie, jak gdyby zczenie z Shipments tworzyo przypadek zewntrzny, niezalenie od
tego, czy zczenie z tabel Addresses tworzyo przypadek zewntrzny. Bez widoku, zapytanie bdzie traktowao zczenie z tabel Shipments niezalenie od zczenia z tabel
Addresses. Jednake wyraenie DECODE na obu kocach listy SELECT oraz rodkowa
cz listy ORDER BY sprawiaj, e wewntrzny przypadek pierwszego zczenia emuluje
przypadek zewntrzny (produkujc NULL w miejsce Shipment_Date i Shipment_ID) za
kadym razem, kiedy zczenie z Addresses znajdzie przypadek zewntrzny.
Czasami bdzie wystpowaa jaka funkcjonalna potrzeba zastosowania widoku zamiast
zwykych tabel. Najczstszym powodem jest obejcie ogranicze automatycznie wygenerowanego SQL-a. Moe si okaza, e dla wypenienia zadanej funkcjonalnoci niezbdne s bardziej zoone konstrukcje SQL, ktrych generator moe nie obsugiwa.
Popularnym rozwizaniem jest ukrycie tej zoonoci w rcznie napisanym zapytaniu

Zapytania z widokami

275

tworzcym widok i pozwolenie generatorowi na traktowanie tego widoku jak zwykej


tabeli, zatajajc przed nim t zoono. W takich przypadkach moliwe jest, e nie uda si
pozby widokw, tak jak sugerowaem to we wczeniejszych rozwizaniach. Alternatywnym wyjciem z tej sytuacji jest rozszerzenie zastosowania widokw, ukrywajc wiksz
cz SQL w ich definicji. Poniewa poprzedni problem by zwizany ze zczeniem zewntrznym z widokiem, moglibymy go rozwiza poprzez wcignicie zczenia zewntrznego do zapytania definiujcego widok. W takim przypadku zamienilibymy uycie
Shipment_V na Order_Details_V, wykorzystujc nastpujce zapytanie definiujce widok:
CREATE VIEW Order_Details_V AS
SELECT 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 Shipment_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 OD
WHERE OD.Shipment_ID = S.Shipment_ID(+)
AND S.Address_ID = A.Address_ID(+)

Zapytanie wykorzystujce ten widok przybiera tak posta:


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.Deferred_Ship_Date,
ODV.Item_Count, ODT.Text, P.Prod_Description, ODV.Shipment_Date
FROM Recent_Orders_V OV, Order_Details_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_ID
AND OV.Customer_ID = C.Customer_ID
AND ODV.Product_ID = P.Product_ID(+)
AND ODV.Status_Code = ODT.Code
AND ODT.Code_Type = 'DOKLADNY_STATUS_ZAMOWIENIA'
ORDER BY OV.Customer_ID, OV.Order_ID Desc, ODV.Shipment_ID,
ODV.Order_Detail_ID

Nadmiarowe operacje odczytu w zapytaniach wykorzystujcych widoki


Przejdmy teraz do przypadku zczenia z wzami C* oraz C, z rysunku 7.35. Wzy
te reprezentuj t sam tabel, z identycznymi skadniami zczenia, wic kady plan
wykonania, ktry korzysta z nich obu odczytuje te same wiersze dwukrotnie i prawdopodobnie korzysta z tych samych indeksw take dwukrotnie. Drugi zbyteczny odczyt
nie jest najprawdopodobniej zwizany z fizycznymi operacjami wejcia-wyjcia, poniewa odczyt pierwszy, ktry mia miejsce milisekundy wczeniej, powinien bezpiecznie
umieci tabel lub blok indeksu na pocztku wspdzielonego bufora pamici podrcznej.
Jeli plan wykonania jest wysoce filtrowany zanim osignie drugi, zbyteczny wze, nadmiarowo logicznych operacji wejcia-wyjcia moe nie mie znaczenia, jednak dla

276

Rozdzia 7. Tworzenie diagramw i optymalizacja zoonych zapyta SQL

duych zapyta lub zapyta, ktre odfiltrowuj wikszo wierszy dopiero po osigniciu
drugiego wza, dodatkowy koszt takich logicznych operacji wejcia-wyjcia moe mie
znaczenie.
Jeli programista oryginalnie pisa zapytanie do prostych tabel, ten rodzaj bdu raczej
si nie pojawi musiaby zej z waciwej sobie cieki, aby uwzgldni nadmiarowe
zczenie, a ta redundancja byaby oczywista przy przegldzie kodu. Jednak przy wykorzystaniu widokw, tego typu bdy s atwe do popenienia i dobrze ukryte.
Jak pozby si nadmiarowego zczenia z tabel Customers? Mamy trzy moliwoci:
Moemy doda nowe kolumny do listy SELECT zapytania definiujcego widok
i w zapytaniu wykorzystujcym ten widok bdziemy ich uywa zamiast kolumn
odnoszcych si do zbytecznej tabeli. Takie rozwizanie jest bezpieczne dla innych
zapyta wykorzystujcych ten sam widok, poniewa nie zmienia ono diagramu
zapytania definiujcego widok.
Wyeliminujemy zbyteczne zczenie z zapytania definiujcego widok i w zapytaniu
wykorzystujcym widok bdziemy uywa jedynie kolumn z prostych tabel.
Jednak w razie gdy istniej inne zapytania wykorzystujce ten sam widok,
mog si one odnosi do usunitych kolumn.
Nie bdziemy wykorzystywa widoku w zapytaniu, ktre go wykorzystywao,
zamieniajc go przez rwnowane, nienadmiarowe zczenia z prostymi tabelami.

Niepotrzebne wzy i zczenia


Rozwamy zczenie z wzem OT w ostatnim zapytaniu wykorzystujcym widok. Oryginalne zapytanie definiujce widok uwzgldnia to zczenie w celu uzyskania statusu
zamwienia, ale zapytanie wykorzystujce widok nawet nie odnosi si do niego, wic
mona sobie zada pytanie o konieczno tego wza. Jeli nawet nie zauwaylimy takiego
nieuywanego wza, moglibymy go wykry, jeli zwrcilibymy uwag na odwoanie
do indeksu klucza gwnego tej tabeli, ale bez odczytw samej tabeli. Takie odczyty
wycznie indeksw klucza gwnego wskazuj zazwyczaj na niepotrzebne zczenie.
Usunicie niepotrzebnych zcze w bezpieczny sposb nie jest atwe, gdy maj one czasami pewne funkcjonalne efekty uboczne. Poniewa to zczenie jest zczeniem wewntrznym, jest bardzo moliwe, nawet przy braku filtra na tym wle, e samo zczenie odrzuci
wiersze, ktrych zapytanie nie powinno zwrci. Rezultatem moe by usunicie wierszy,
dla ktrych Order.Status_Code IS NULL lub dla ktrych Status_Code wskazuje na niewaciwe wartoci kodw nie majcych odpowiednikw w tabeli Code_Translations. Ta
ostatnia moliwo jest mao prawdopodobna lub powinna by usunita przez naprawienie spjnoci odwoa. Trzeba zauway, e wartoci null kluczy obcych s czste
i jeli kolumna moe mie warto null, powinnimy rozway jawne dodanie warunku
Status_Code IS NOT NULL przed usuniciem zczenia, aby zasymulowa ukryty efekt
filtrowania zczenia wewntrznego. Bardziej prawdopodobne jest, e programista uywajcy tego widoku nie pomyla nawet o niejawnej funkcji filtrowania widoku i ukryty

Zapytania z operacjami na zbiorach

277

filtr by cakowicie niepodany i niezgodny z intencj. Dlatego przed podjciem decyzji o symulowaniu pierwotnego dziaania poprzez zapytanie oparte jedynie o tabele
i eliminujce niepotrzebne zczenie, naley sprawdzi, czy to pierwotne dziaanie
byo w ogle poprawne. Jeli zamiana spowoduje nawet drobn zmian zachowania
zapytania, nawet na lepsze, naley ostrzec testerw, e testy regresyjne mog w takich
kracowych przypadkach przynie inne rezultaty.

Zapytania z operacjami na zbiorach


Niekiedy zachodzi potrzeba optymalizacji wieloczciowego zapytania, ktre uywa operatorw, takich jak UNION, UNION ALL, INTERSECT i EXCEPT, aby poczy rezultaty dwch
lub wikszej liczby prostych zapyta. Rozszerzenie metody optymalizacji poprzez
tworzenie diagramw SQL na takie wieloczciowe zapytania jest zazwyczaj proste naley stworzy diagramy i optymalizowa kad cz osobno, tak jakby bya samodzielnym
zapytaniem. Kiedy czci te wykonuj si szybko, poczenie rezultatw za pomoc
operatorw zbiorw zazwyczaj dziaa dobrze.
Sowo kluczowe EXCEPT jest wyspecyfikowane przez standard ANSI SQL dla operatorw zbiorowych jako operacja wyszukania rnic pomidzy zbiorami. DB2
i SQL Server podaj za standardem poprzez wspieranie EXCEPT. Jednak Oracle
wykorzystuje dla tej samej operacji sowo MINUS, najprawdopodobniej dlatego, e
wspiera on t operacj jeszcze zanim pojawia si ona w standardzie.

Niektre z tych operatorw zbiorw zasuguj na chwil uwagi. Operator UNION nie tylko
czy czci wyniku, ale musi je take posortowa i odrzuci duplikaty. Ta ostatnia
czynno jest czsto niezbdna, szczeglnie jeli projekt uwzgldnia podzia na czci
gwnie, aby odrzuci powtrzenia. W bazie danych Oracle operator UNION moe by
zamieniony przez UNION ALL, jeli stwierdzimy, e powtrzenia nie s moliwe lub nie
powinny by usunite. W bazach danych nie wspierajcych UNION ALL mona przeskoczy eliminujce dziaanie przez zastpienie pojedynczego zapytania UNION dwoma lub
wiksz liczb prostych zapyta i czc rezultaty w warstwie aplikacji zamiast w bazie
danych.
Operacja INTERSECT moe zazwyczaj by z powodzeniem zamieniona przez podzapytanie
typu EXISTS poszukujcego pasujcego wiersza, ktry byby wynikiem dziaania drugiej
czci zapytania z INTERSECT. Na przykad, jeli mielibymy dwie tabele odnoszce si
do pracownikw, moglibymy poszuka rekordw pracownika wspdzielonego w nastpujcy sposb:
SELECT Employee_ID FROM Employees1
INTERSECT
SELECT Employee_ID FROM Employees2

278

Rozdzia 7. Tworzenie diagramw i optymalizacja zoonych zapyta SQL

Zawsze moglibymy zamieni zapytanie INTERSECT przez:


SELECT DISTINCT Employee_ID
FROM Employees E1
WHERE EXISTS (SELECT null
FROM Employees2 E2
WHERE E1.Employee_ID=E2.Employee_ID)

Uywajc metod zaprezentowanych w rozdziale Zapytania z widokami mona okreli,


czy podzapytanie EXISTS powinno by wyraone w formie EXISTS lub IN, czy te zamienione na proste zczenie. Zauwamy, e warunki zczenia skorelowanego staj si cakiem
liczne, jeli lista SELECT zawiera wiele elementw. Wemy take pod uwag, e INTERSECT
dopasuje listy kolumn z wartociami null, podczas gdy zczenie skorelowane nie, chyba
e uyjemy warunku zczenia specjalnie do tego przeznaczonego. Przykadowo gdy
nieujemny klucz gwny Manager_ID moe mie warto null (ale Employee_ID nie)
rwnowana posta zapytania w wersji Oracle:
SELECT Employee_ID, Manager_ID FROM Employees1
INTERSECT
SELECT Employee_ID, Manager_ID FROM Employees2

jest nastpujca:
SELECT DISTINCT Employee_ID, Manager_ID
FROM Employees1 E1
WHERE EXISTS (SELECT null
FROM Employees E2
WHERE E1.Employee_ID=E2.Employee_ID
AND NVL(E1.Manager_ID,-1)=NVL(E2.Manager_ID,-1))

Wyraenie NVL(...,-1) w drugim warunku zczenia skorelowanego zamienia wartoci


null na kolumnie null-owej, tak aby zczyy si one poprzez dopasowanie null z null.
Operacja EXCEPT (lub MINUS) moe zazwyczaj by zamieniona z zyskiem na podzapytanie
NOT EXISTS. Gdybymy poszukiwali rekordw pracownikw w pierwszej tabeli, pod
warunkiem, e nie istniay w tabeli drugiej, moglibymy uy poniszego zapytania:
SELECT Employee_ID, Manager_ID FROM Employees1
MINUS
SELECT Employee_ID, Manager_ID FROM Employees2

Zawsze moglibymy te zastpi t posta nastpujc:


SELECT DISTINCT Employee_ID
FROM Employees1 E1
WHERE NOT EXISTS (SELECT null
FROM Employees2 E2
WHERE E1.Employee_ID=E2.Employee_ID)

Rozwizalibymy wwczas to zapytanie wykorzystujc metody opisane we wczeniejszym rozdziale Zapytania z podzapytaniami.

wiczenie

279

wiczenie
Poniszy przykad przedstawiajcy nierealistycznie skomplikowane zapytanie przygotowano tak, aby Czytelnik mg sprawdzi, czy dobrze zrozumia zasady optymalizacji
zapyta z podzapytaniami. Rysunek 7.36 obrazuje zapytanie bardziej skomplikowane
i trudniejsze ni mona by spotka po roku intensywnej pracy nad optymalizacj SQL.
Osoba, ktra poradzi sobie z tym zadaniem, poradzi sobie take z atwoci z dowolnym
scenariuszem, ktre przyniesie ycie.

Rysunek 7.36. Zoony problem z wieloma podzapytaniami


Jeli kto nie zdoa rozwiza tego zadania za pierwszym razem, powinien powrci do tego wiczenia po nabyciu wikszej praktyki.

Na diagramie naley uzupeni brakujce wspczynniki dla zcze skorelowanych.


Zamy e t = 5 (liczba wierszy caego zapytania, uwzgldniajc podzapytanie NOT
EXISTS) oraz q = 50 (liczba wierszy zapytania z usunitym warunkiem NOT EXISTS).
Nastpnie trzeba znale najlepszy porzdek zczenia biorc pod uwag wszystkie
tabele podzapyta oraz zapyta zewntrznych.