W bazie danych są następujące tabele:
Zamowienie (
nr VARCHAR(10) PRIMARY KEY,
klient VARCHAR(20)
)
Pozycja(
zam VARCHAR(10) REFERENCES Zamowienie,
nr VARCHAR(3),
towar VARCHAR(20),
ilosc NUMBER(8),
CONSTRAINT pk PRIMARY KEY (zam, id)
)
W takiej bazie danych ma zostać wykonane następujące zapytanie:
SELECT z.klient, p.towar
FROM Zamowienie z, Pozycja p
WHERE z.nr = p.zam AND ilosc > ALL (SELECT ilosc FROM Pozycja p1
WHERE p1.zam = p.zam AND p1.towar <> p.towar);
Przyjmijmy, że w pamięci operacyjnej mieści się 100 bloków, tabela Zamowienie
ma 50.000 wierszy i zajmuje 1.000 bloków, a tabela Pozycja
ma 1.000.000 wierszy i zajmuje 10.000 bloków. Zaproponuj jak najlepszy plan wykonania tego zapytania i oszacuj sumaryczną liczbę bloków przeczytanych i zapisanych na dysku. Można założyć istnienie dowolnych struktur pomocniczych.
Klastrujemy tabelę Pozycja
po parze (zam, ilosc)
i tworzymy indeks, który wskazuje na końce zamówień i trzyma w sobie informację (zam, towar)
, gdzie towar
odpowiada dokładnie poszukiwanym nazwom towarów dla każdego zamówienia. Ten indeks obejmie około bloków, bo tyle jest różnych zamówień. Zamowienie
klastrujemy po nr
. Teraz możemy liniowo zjoinować informacje z indeksu z odpowiednim zamowieniem i dodać nazwę klienta. Koszt to przeczytanie całego najniższego rzędu indeksu i całej tabeli Zamowienie
plus wypisanie wyniku, czyli . Można spokojnie założyć, że to od do bloków.
Rozwiązanie bardziej na palcach:
Zakładamy indeks sklastrowany na Zamowienie.nr
oraz Pozycja.zam
. W ten sposób możemy ładować Pozycje
razem z Zamowieniami
w rosnacej kolejnosci id
, a w pomocniczym bloku pamięci trzymać największą do tej pory znalezioną ilosc
oraz towar
. Korzystamy jedynie z tego, że dane są posortowane i czytamy obie tabele raz, więc kosztuje nas to .