You are on page 1of 46
Aspekty fizyczne baz danych
Aspekty fizyczne baz danych
Niepoprawny projekt bazy danych • Zły projekt logiczny bazy danych prowadzi do kiepskiej wydajnościowo bazy
Niepoprawny projekt bazy danych
• Zły projekt logiczny bazy danych prowadzi do kiepskiej
wydajnościowo bazy danych.
• Przy tworzeniu bazy danych od podstaw, warto
poświęcić więcej czasu na dobry projekt logiczny. Jest to
warunek konieczny do dobrej bazy danych z punktu
wydajnościowego.
• Wszelkie poprawki w schemacie logicznym bazy danych
dopiero podczas implementacji są trudne do
przeprowadzenia.
• Straty na wydajności wynikające z nieoptymalnego
projektu bazy danych są ciężkie do nadrobienia nawet
przy zastosowaniu drogich rozwiązań sprzętowych.
Plan wykładu • Wykonywanie zapytań • Indeksowanie • Partycjonowanie • Zalecenia dla twórców bazy danych
Plan wykładu
• Wykonywanie zapytań
• Indeksowanie
• Partycjonowanie
• Zalecenia dla twórców bazy danych (zbiór
dobrych praktyk)
Wykonywanie zapytań • Kompilacja zapytania • Wykonywanie zapytania
Wykonywanie zapytań
• Kompilacja zapytania
• Wykonywanie zapytania
Plan wykonania zapytania • Dla każdej „paczki” instrukcji tworzony jest osobny plan wykonania zapytania •
Plan wykonania zapytania
• Dla każdej „paczki” instrukcji tworzony jest
osobny plan wykonania zapytania
• Etapy utworzenia planu zapytania:
– Parsowanie – sprawdzenie czy zapytanie jest
poprawne syntaktycznie;
– Bindowanie – sprawdzanie semantyczne (np. czy
obiekty, do których odwołują się zapytania znajdują
się rzeczywiście w bazie danych)
– Optymalizacja – znalezienie najlepszego planu
wykonania zapytania, czyli takiego, który wykona
zapytanie najszybciej.
• Plany wykonania zapytań są zapisywanie w
pamięci cache i mogą być powtórnie używane.
Zapytanie SELECT C.CustomerID, COUNT(O.OrderID) AS NumOrders FROM dbo.Customers AS C LEFT OUTER JOIN dbo.Orders AS
Zapytanie
SELECT C.CustomerID, COUNT(O.OrderID) AS NumOrders
FROM dbo.Customers AS C LEFT OUTER JOIN dbo.Orders AS O
ON C.CustomerID = O.CustomerID
WHERE C.City = 'London'
GROUP BY C.CustomerID
HAVING COUNT(O.OrderID) > 5
ORDER BY NumOrders;
Plan zapytania
Plan zapytania
Drzewa • Drzewo składa się z węzłów • Każdy węzeł oprócz korzenia ma jednego przodka
Drzewa
• Drzewo składa się z węzłów
• Każdy węzeł oprócz korzenia ma jednego
przodka i może mieć różną liczbę
potomków
• Korzeń nie ma przodka
• Węzeł, który nie ma potomków jest
liściem
• Poziom węzła jest zawsze większy o 1 niż
poziom jego przodka, poziom korzenia = 0
Czym jest B+ drzewo • Cechy charakterystyczne B+ drzewa • Jest drzewem zbalansowanym: – Każda
Czym jest B+ drzewo
• Cechy charakterystyczne B+ drzewa
• Jest drzewem zbalansowanym:
– Każda ścieżka z korzenia do liści ma tę samą
długość
– Każdy wierzchołek posiada od n/2 do n dzieci,
gdzie n jest ustalone dla każdego drzewa
(reguła 50%)
– Wskaźniki do danych znajdują się tylko na
liściach
B+ drzewo – przykład (n=4)
B+ drzewo – przykład (n=4)
Przeszukiwanie B+ drzewa • Przeszukiwanie B+ drzewa polega na porównywaniu wartości klucza w drzewie. Przykład:
Przeszukiwanie B+ drzewa
• Przeszukiwanie B+ drzewa polega na
porównywaniu wartości klucza w
drzewie.
Przykład: znajdź wartość 45 i 15 w
poniższym drzewie.
Przeszukiwanie • Rezultat: 1. Wartości 45 nie ma w drzewie. 2. Dla wartości 15 zwrócona
Przeszukiwanie
• Rezultat:
1. Wartości 45 nie ma w drzewie.
2. Dla wartości 15 zwrócona zostanie
pozycja wskaźnika.
Wstawianie • Jeśli wstawianie do B+ drzewa spowoduje, że drzewo nie będzie zbalansowane, wówczas następuje
Wstawianie
• Jeśli wstawianie do B+ drzewa spowoduje, że
drzewo nie będzie zbalansowane, wówczas
następuje przebudowa drzewa.
• Przykład #1 : wstawianie 28 do drzewa.
25
28 30
Zachowana jest
reguła 50%
Wstawianie • Rezultat:
Wstawianie
• Rezultat:
Wstawianie • Przykład #2: wstawianie 70 do drzewa
Wstawianie
• Przykład #2: wstawianie 70 do drzewa
Wstawianie • Reorganizacja drzewa 50 55 60 65 70 Naruszenie reguły 50%, 50 55 60
Wstawianie
• Reorganizacja drzewa
50
55
60
65
70
Naruszenie
reguły
50%,
50
55
60
65
70
reorganiza
cja drzewa
Wstawianie • Rezultat: wybieranie środkowego klucza 60, i umieszczenie go w wierzchołku indeksu pomiędzy 50
Wstawianie
• Rezultat: wybieranie środkowego klucza
60, i umieszczenie go w wierzchołku
indeksu pomiędzy 50 i 75.
Wstawianie • Przykład #3: dodawanie wartości klucza 95 do drzewa. 75 80 85 90 95
Wstawianie
• Przykład #3: dodawanie wartości klucza
95 do drzewa.
75
80
85
90
95
Naruszenie
reguły 50%,
podzielenie
liścia
75 80
85 90
95
25
50
60
75
85
Wstawianie • Rezultat: wstawienie wartości klucza 60 do węzła indeksowego i reorganizacja drzewa.
Wstawianie
• Rezultat: wstawienie wartości klucza 60 do
węzła indeksowego i reorganizacja
drzewa.
Algorytm wstawiania w B+ drzewie Strona Strona Akcja danych indeksu pełna pełna Nie Nie Wstaw
Algorytm wstawiania w B+ drzewie
Strona
Strona
Akcja
danych
indeksu
pełna
pełna
Nie
Nie
Wstaw rekord w porządku rosnącym do odpowiedniego liścia
Tak
Nie
1. Podziel stronę danych .
2. Umieść środkowy klucz danych do strony indeksowej w porządku rosnącym
3. Lewa strona liścia zawiera rekordy o kluczu mniejszym niż klucz środkowy.
4. Prawa strona liścia zawiera rekordy o kluczu mniejszym lub równym niż klucz
środkowy.
Tak
Tak
1. Podziel stronę danych.
2. Lewa strona liścia zawiera rekordy o kluczu mniejszym niż klucz środkowy.
3. Prawa strona liścia zawiera rekordy o kluczu mniejszym lub równym niż klucz
środkowy.
4. Podziel stronę indeksu.
5. Klucz środkowy zapisywany jest do strony wyższego poziomu.
6. Klucze mniejsze od środkowego klucza zapisywane są
do lewego liścia, większe lub równe do prawego.
7. Jeśli następny poziom jest pełny, następuje kolejny podział.
Usuwanie • Zasady podobne do wstawiania, B+ drzewo musi być przebudowane przy załamaniu reguły 50%.
Usuwanie
• Zasady podobne do wstawiania, B+ drzewo musi być
przebudowane przy załamaniu reguły 50%.
• Przykład #1: usunięcie 70 z drzewa
To jest OK.
60
65
Usuwanie – Rezultat:
Usuwanie
– Rezultat:
Usuwanie Przykład #2: usunięcie 25 z drzewa, przy czym 25 pojawia się na stronie indeksu.
Usuwanie
Przykład #2: usunięcie 25 z drzewa, przy
czym 25 pojawia się na stronie indeksu.
Ale…
28 30
To jest
OK.
Usuwanie • Rezultat: zastąpienie przez 28 na stronie indeksu. Dod. 28
Usuwanie
• Rezultat: zastąpienie przez 28 na stronie
indeksu.
Dod. 28
Usuwanie • Przykład #3: usuwanie 60 z drzewa 65 Złamanie 50 55 65 reguły 50%
Usuwanie
• Przykład #3: usuwanie 60 z drzewa
65
Złamanie
50
55 65
reguły 50%
Usuwanie • Rezultat: usuniecie 60 ze strony indeksowej i reorganizacja grafu.
Usuwanie
• Rezultat: usuniecie 60 ze strony
indeksowej i reorganizacja grafu.
Algorytm usuwania dla B+ drzewa Strona danych poniżej współczynnika wypełnienia Strona indeksu poniżej
Algorytm usuwania dla B+ drzewa
Strona danych
poniżej
współczynnika
wypełnienia
Strona indeksu
poniżej
współczynnika
wypełnienia
Akcja
Nie
Nie
Usuń rekord ze strony danych. Jeśli klucz
pojawia się w stronie indeksu, zamień go przez
następny klucz.
Tak
Nie
Przenieś dane ze strony, z których usunięto
dane do strony sąsiedniej. Zmień stronę indeksu
tak, aby odzwierciedlić zmianę w liściach.
Tak
Tak
Przenieś dane ze strony, z których
usunięto dane do strony sąsiedniej.
Zmień stronę indeksu tak, aby
odzwierciedlić zmianę w liściach.
Przenieś dane indeksowe do strony
sąsiedniej. Dostosuj stronę indeksową
poziom wyżej do powyższych zmian.
Algorytm powinien być kontynuowany do
momentu, gdy strona indeksu będzie poniżej
współczynnika wypełnienia
Rodzaje indeksów na przykładzie SQL Server • Indeks klastrowy: – może być jeden w tabeli;
Rodzaje indeksów na przykładzie
SQL Server
• Indeks klastrowy:
– może być jeden w tabeli;
– dane znajdują się w liściach;
– utworzenie klucza głównego na kolumnę w tabeli powoduje
dodanie indeksu klastrowego na tę kolumnę;
create clustered index nazwa_indeksu on tabela (kolumna1,…)
• Indeks nieklastrowy:
– może być więcej niż jeden w tabeli;
– w liściach nie ma danych tylko są wskaźniki do danych;
create nonclustered index nazwa_indeksu on tabela (kolumna1,…)
Indeks klastrowy
Indeks klastrowy
Indeks nieklastrowy
Indeks nieklastrowy
Indeks klastrowy i nieklastrowy
Indeks klastrowy i nieklastrowy
Kiedy stosować indeksy? • Przyspieszają dostęp do bazy danych. • Powinny być projektowane ostrożnie •
Kiedy stosować indeksy?
• Przyspieszają dostęp do bazy danych.
• Powinny być projektowane ostrożnie
• Zajmują miejsce na dysku, a więc nie
powinno być ich więcej niż potrzeba
• Przy zmianie danych w bazie (insert,
update, delete) indeksy są
przebudowywane, to zajmuje czas
Kiedy stosować indeksy? • Gdy tabela jest często zmieniana, należy nie używać zbyt wielu indeksów
Kiedy stosować indeksy?
• Gdy tabela jest często zmieniana, należy nie używać zbyt wielu
indeksów na niej oraz indeksów na wielu kolumnach
• Gdy tabela jest rzadko modyfikowana, można zakładać dużo
indeksów na niej
• Małe tabele należy indeksować rozsądnie, gdyż nawigacja po
indeksie może być dłuższa niż skanowanie tabeli
• Lepiej implementować indeks na kolumnie o wartościach
unikalnych. Im mniej powtarzających się wartości, tym lepsza
wydajność indeksu.
• Przy indeksach złożonych należy brać pod uwagę kolejność. Na
pierwszym miejscu powinny być takie kolumny, które najczęściej są
używane w klauzuli WHERE.
Indeksy a zapytania • Częstość zmian w bazie ma wpływ na wydajność indeksów • Lepiej
Indeksy a zapytania
• Częstość zmian w bazie ma wpływ na
wydajność indeksów
• Lepiej modyfikować dużą paczkę danych na raz
niż robić kilka zapytań. W pierwszym przypadku
indeksy będą reorganizowane tylko raz.
• Należy używać indeksów nieklastrowych na
kolumnach, które będą brały udział w
instrukcjach złączenia.
• Należy używać indeksów nieklastrowych w
przypadku, gdy będzie często wykonywana
instrukcja WHERE na tych kolumnach.
Dlaczego baza powinna być znormalizowana? • Redukuje ilość danych w bazie. Zwiększa się więc wydajność
Dlaczego baza powinna być
znormalizowana?
• Redukuje ilość danych w bazie. Zwiększa się więc wydajność bazy.
• Redukuje ilość wartości NULL w bazie danych. Używanie wartości
NULL znacznie obniża wydajność bazy danych, szczególnie w
klauzulach WHERE.
• Redukuje liczbę kolumn w bazie co sprawia, że więcej wierszy
mieści się na jednej stronie, co z kolei zwiększa wydajność serwera.
• Redukuje ilość kodu SQL, który musiałby być napisany w przypadku
bazy nieznormalizowanej.
• Im bardziej znormalizowana baza, tym więcej tabel i więcej
indeksów klastrowych, które zwiększają wydajność.
• Brak redundancji powoduje, że nie ma potrzeby obsługi anomalii
bazy danych:
– dodawania, modyfikacji takich samych danych w kilku miejscach
– usuwania tych samych danych z kilku tabel
Transakcje • Transakcje powinny być krótkie. Im krótsza transakcja tym krótsze są blokady na danych.
Transakcje
• Transakcje powinny być krótkie. Im krótsza
transakcja tym krótsze są blokady na danych. To
z kolei zwiększa wydajność.
• Nie należy używać transakcji do odczytywania
danych.
• Tam gdzie to możliwe powinien być niski poziom
transakcji.
• Transakcje nie powinny być otwarte podczas
oczekiwania na reakcję użytkownika.
• Transakcje powinny być rozpoczynane i
kończone jawnie.
Transakcje - przykład • Przykład: Tworzenie nowej faktury • Scenariusz #1: 1) Rozpoczęcie transakcji 2)
Transakcje - przykład
• Przykład: Tworzenie nowej faktury
• Scenariusz #1:
1) Rozpoczęcie transakcji
2) Dodanie faktury
3) Dodanie elementów faktury
4) Zatwierdzenie faktury
5) Zatwierdzenie transakcji
• Scenariusz #2:
1) Dodanie faktury
2) Dodanie elementów faktury
3) Rozpoczęcie transakcji
4) Zatwierdzenie faktury
5) Zakończenie transakcji
• Scenariusz #2: krócej są dane blokowane podczas transakcji.
• Scenariusz #1: Wewnątrz transakcji należy czekać na reakcję użytkownika.
Dlaczego warto używać procedur składowanych? • Redukcja ruchu sieci. Jeśli aplikacja kliencka wysyła kod SQL
Dlaczego warto używać procedur
składowanych?
• Redukcja ruchu sieci. Jeśli aplikacja kliencka
wysyła kod SQL do serwera, to wysyła nazwę
procedury składowanej, a nie pojedyncze
instrukcje SQL.
• Plan wykonania zapytania procedury
składowanej pozostaje w pamięci cache i może
być ponownie użyty
• Kod w procedurze składowanej można zmienić
nie zmieniając kodu aplikacji.
Poprawienie wydajności operacji Join • Operację JOIN przyspieszają indeksy, które są na atrybutach złączenia.
Poprawienie wydajności operacji
Join
• Operację JOIN przyspieszają indeksy,
które są na atrybutach złączenia.
• Wydajność jest większa, gdy atrybuty
złączeń są numeryczne.
• Jeśli jedna z tabel jest mała, wówczas jest
ona pobierana do pamięci cache, co
zwiększa wydajność operacji Nested
Loop.
Partycjonowanie • Partycjonowanie jest fizycznym podziałem danych pomiędzy różne pliki bazy danych •
Partycjonowanie
• Partycjonowanie jest fizycznym podziałem
danych pomiędzy różne pliki bazy danych
• Partycjonować można tabele i indeksy
bazy danych
• Użytkownik bazy danych nie jest
świadomy tego, czy struktura jest
podzielona czy też nie jest.
• Partycjonowanie nie ma wpływu na
zapytania SQL.
Korzyści z partycjonowania • Podniesienie skalowalności i zarządzania tabelami o dużych rozmiarach (rzędu
Korzyści z partycjonowania
• Podniesienie skalowalności i zarządzania tabelami o
dużych rozmiarach (rzędu kilkuset megabajtów)
• Lepszy dostęp do danych
• Możliwość wykorzystania wieloprocesorowych serwerów
(każdy procesor może wówczas obsługiwać różne
partycje)
• Przykład:
Dana jest tabela sprzedaż posiadająca rekordy dotyczące sprzedaży z
wielu miesięcy. Zakładamy, że dzielimy tabelę po miesiącu. Na ostatnim
miesiącu są wykonywane częste modyfikacje, a z poprzednich tylko odczyt.
• Modyfikacje z ostatniego miesiąca nie maja więc wpływu
na wydajność z miesięcy poprzednich.
Konfigurowanie partycjonowania – tworzenie bazy danych CREATE DATABASE [Data Partition DB] ON PRIMARY
Konfigurowanie partycjonowania –
tworzenie bazy danych
CREATE DATABASE [Data Partition DB]
ON PRIMARY
(NAME='Data Partition DB Primary FG',
FILENAME=
'C:\Data\Primary\Data Partition DB Primary FG.mdf',
SIZE=5,
MAXSIZE=500,
FILEGROWTH=1 ),
FILEGROUP [Data Partition DB FG1]
(NAME = 'Data Partition DB FG1',
FILENAME =
'C:\Data\FG1\Data Partition DB FG1.ndf',
SIZE = 5MB,
MAXSIZE=500,
FILEGROWTH=1 ),
FILEGROUP [Data Partition DB FG2]
(NAME = 'Data Partition DB FG2',
FILENAME =
'C:\Data\FG2\Data Partition DB FG2.ndf',
SIZE = 5MB,
MAXSIZE=500,
FILEGROWTH=1 ),
FILEGROUP [Data Partition DB FG3]
(NAME = 'Data Partition DB FG3',
FILENAME =
'C:\Data\FG3\Data Partition DB FG3.ndf',
SIZE = 5MB,
MAXSIZE=500,
FILEGROWTH=1 )
Konfigurowanie partycjonowania Tworzenie funkcji partycji: CREATE PARTITION FUNCTION [Data Partition Range](int) AS
Konfigurowanie partycjonowania
Tworzenie funkcji partycji:
CREATE PARTITION FUNCTION [Data Partition Range](int)
AS RANGE LEFT FOR VALUES (100000)
Tworzenie schematu partycji:
CREATE PARTITION SCHEME [Data Partition Scheme]
AS PARTITION [Data Partition Range]
TO ([Data Partition DB FG1], [Data Partition DB FG2]);
Tworzenie tabeli na partycji:
CREATE TABLE MyTable
(ID INT NOT NULL,
Date DATETIME,
Cost money)
ON [Data Partition Scheme] (ID);
Dodawanie danych declare @count int set @count =1 while @count <=100 begin insert into MyTable
Dodawanie danych
declare @count int
set @count =1
while @count <=100
begin
insert into MyTable select @count,getdate(),100.00
set @count=@count+1
end
set @count =100002
while @count <=100202
begin
insert into MyTable select @count,getdate(),200.00
set @count=@count+1
end
Odczyt danych Partycjonowanie nie ma wpływu na polecenia SQL: select * from MyTable Odczyt danych
Odczyt danych
Partycjonowanie nie ma wpływu na
polecenia SQL:
select * from MyTable
Odczyt danych z uwzględnieniem partycji:
select $partition.[Data Partition Range](t.ID), * from
MyTable as t
Dziękuję
Dziękuję