SGBD Practice 1
SGBD Practice
1
What will we study?
• Beeing about something that is practical, mostly nothing theoretical.
• We will have 3 main topics:
- Optimizing an querry by indexing;
- Transactions (some topic remaind from DB);
- NoSQL – a short introduction.
• In laboratory: PL/SQL (Procedural Language / Structured Query Language)
2
3
Achieving Optimum Performance for Executing SQL Queries in Online Transaction Processing and in Data Warehouses (Lucrare dizertaţie - Lazăr L.)
http://use-the-index-luke.com/
4
Sintactical & Semantical
• We can consider that a querry is a proposition in english that tells the DB server what he has to do:
… what if the answer comes back after 15 seconds?
SELECT fname
FROM students
WHERE lname = „Jackson'
5
At the base of an application error are two human errors*
• Most of the time, the programmer that writes the querry doesn’t care how will be executed.
• He usually strongly believes that the SGBD beehaviour is slow…
• Solution ? Simple: stop using Oracle, start using somethin else (MySQL, PostgreSQL or SQL Server (because we heard that it will work faster than oracle).
*One of them is to blame the computer. 6
Actually…
• The only thing that programmers should know about databases is how to index the data.
• The most important information is how the application will access the data.
• The journey of the data is not known by anybody except the programmer !
7
…ToC… (about indexing)
• How indexes look like
• WHERE-clause
• Performance and scalability
• JOIN
• Clustering
• Sorting and grouping data
• Partial Results
• INSERT, UPDATE, DELETE8
Index anatomy
• “An index makes the query fast” - how fast?
------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 9 | 5 (0)| 00:00:01 |
|* 1 | TABLE ACCESS FULL| STUDENTS | 1 | 9 | 5 (0)| 00:00:01 |
------------------------------------------------------------------------------
PLAN_TABLE_OUTPUT
-------------------------
1 - filter(“LNAME"=„Jackson')
9
Index anatomy
• “An index makes the query fast” (5x ?)
-----------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
-----------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 9 | 1 (0)| 00:00:01 |
|* 1 | INDEX RANGE SCAN| STD_LNAME| 1 | 9 | 1 (0)| 00:00:01 |
-----------------------------------------------------------------------------
PLAN_TABLE_OUTPUT
--------------------------------
1 - access(“LANME"=„Jackson')
10
Index anatomy
• An index is a structure* that is not the actual table. It can be created by using create index.
select index_name from user_indexes;
• It needs it’s own space on HDD and points to the records in the actual table. Beeing an index (mostly like the ToC of a book, it will have a certain degree of redundancy – some of them even have 100% redundancy: SQL Server or MySQL + InnoDB are using Index-Organized Tables [IOT]).
* We will give some details, most of them you know from the DB course previous semester.
11
Index Anatomy
• Looking for information into an index is the same as searching for a number in a phonebook.
• The index in a DB has to be fastly reorganized because there are more operations in a DB (than in a phonebook):
[insert / update / delete]
• It has to be maintained without moving big quantities of data.
12
Accessing data in a “sorted” file
• Suppose that we have 1.000.000 data having the same space on HDD *e.g. …FoxPro+.
• Binary Search => log2(1.000.000) =20 reads
• A HDD having 7200RPM makes a complete rotation in 60/7200” = 0.008333..” = 8.33ms
• For a Seagate ST3500320NS, track-to-track seek time = 0.8ms
https://en.wikipedia.org/wiki/B-tree13
Accessing data in a “sorted” file
• Searching (0.8ms) and readin (8.33ms) might get up to 10ms – this is for 1 read. But we needed 20 (to completely search the file).
• 20 readings = 200ms = 0.2”
• Might not look that much and, probably, because some data are in the same HDD area they will be accessed without moving the header to some other location. Suppose that we have 0.15”
https://en.wikipedia.org/wiki/B-tree14
Accessing data in a “sorted” file
• What we would have searched for 10 values ? The needed time would be 1.5 seconds.
• What about 100 values ? 15 seconds ?!?!
• What if the data are not even sorted…
15
How do I get smaller times?
log2(1.000.000)
We need to change this
16
Index anatopy
• How does it work ? Based on a searching tree
Based on a doubly linked list
• The tree required for accessing data is a B+-trees (a version of B-tree with data on leafs).
• The list is used to access next data (after the first one is found based on the tree).
17
For a long time it was unclear what the "B" in the name represented. Candidates discussedin public where "Boeing", "Bayer", "Balanced", "Bushy" and others. In 2013, the B-Tree had just turned 40, Ed McCreight revealed in an interview, that they intentionally never published an answer to this question. They were thinking about many of these options themselves at the time and decided to just leave it an open question. http://sqlity.net/en/2445/b-plus-tree/
18
To easily talk about indexes…
• We will discard one of the pointers in each node of the tree – each pointer has the highest value in the next node (we actually ignored one of the pointers) !
• The leafs contain also duplicates (even though in realty there are buckets of values) !
• In reality many DB use a doubly lionked list – in order to be able to search in both ways.
19
Index Anatomy
20
In reality here is a bucket of
27s.
Index Anatomy
• Because the values in the leafs are not uniformly distributed, we need to access a certain value by the means of the B-tree.
21
Index Anatomy
22
Index Anatomy
The next node will have the highest value equal to the value of the pointer.
23
Index Anatomy
24
Index Anatomy
• A B+ tree is a balanced tree !
• A B+ tree is not a binary tree !
• Oince is created, the DB maintains the index balanced (insert/delete/update)
• B+ tree-ul helps the DB gets fast to a leaf;
• How fast ? [first power of indexing]
25
How is the B+ tree balanced?
• This topic was discussed in the DB course.
• Basic ideea is that when the node is full and we want to add another value, it will split in two (brothers) nodes adding a value to his parent.
• The balancing is done up to the point where the father node has enough space for keeping one more value. If this is impossible, the root will be splitted and the B+ tree will increase the level.
26
Index Anatomy
• There is a fake rumor that in time the index will not be as effective as in the beginning. This is totally fake because the B+tree will always balance.
27
Index Anatomy
• What makes the index work slow ?
• Accessing the bucket !28
Index Anatomy
• Why would the DB work slow when using indexes ?
• After finding the rowID, the data has to be taken from the table.
• 3 sptes:
Traversing B+ tree[time: O(log(n))]Searching the wanted leaf [O(n)]Accessing the table [HDD speed dependant]
29
Index Anatomy
• It is a mistake to believe that the B+ tree is not balanced anymore.
• The developer can ask the DB how the query will be executed.
30
Index Anatomy
• 3 types of operations:
INDEX UNIQUE SCAN
INDEX RANGE SCAN
TABLE ACCESS BY INDEX ROWID
• The highest cost: INDEX RANGE SCAN.
• If there are more than 1 row: TABLE ACCESS –might start to be a problem (especially when the row are not in the same track of the HDD).
31
Exectuin Plan
• If we want to ask Oracle how he will execute a querryu: EXPLAIN PLAN FOR
• To obtain a representation of the answer as a table, we execute the following command:
SELECT* FROM TABLE(dbms_xplan.display);
32
33
34
35
WHERE clause
36
WHERE clause
• WHERE defines the selection criterion: it tells the DB what data are asked in order to not have the entire table returned (that would take time). That is why it has the most power of influencing the time data are returned.
• WHERE is the one that is actually using the indexes in order to get a faster result.
37
WHERE clause
CREATE TABLE studentd (
id INT PRIMARY KEY,
lname VARCHAR2(15) NOT NULL,
fname VARCHAR2(30) NOT NULL,
dob DATE,
email VARCHAR2(40), … (LAB)
);
…we add 1025 students.
It will automatically
create an index
38
WHERE clauseSELECT lname, fname
FROM students
WHERE id = 300
Is it better with range scan ? Can we get a range scan when using a primary index and equality in the where clause ?
39
WHERE clauseSELECT lname, fname
FROM students
WHERE id BETWEEN 200 AND 210
40
Composing indexes
• Sometime we want our index to contain two columns:
CREATE UNIQUE INDEX idx_grades ON
grades(id_student, id_course);
• Instead of a single value, each node will have a combination of the two. The same goes for the doubly linked list. When searching finds the student with the certain ID, the index will start accessing the data using the id_course.
41
42
Looking up 300,2 (for example)
43
Composing indexes
• When the combination of the two fields that are used in the creation of the index are unique, we can create the index using:CREATE UNIQUE INDEX ….
• What if we want now to search by only one of the fields ? Two cases
Case 1: Looking by id_student
Case 2: Looking by id_course
44
id_student
45
id_course
46
Composing indexes
• Consider that the index is created on a phonebook and we try to access everybody having a certain first last name (e.g. Jackson). Is it possible to search on the first field of the index ?
• Consider that the index is created on a phonebook and we try to access everybody having a certain first name (e.g. Michael). Is it possible to search on the second field of the index ?
47
Composing indexes
Look at how much the consumption of the CPU has increased ?
And this is only a small case scenario.
48
49
Search all the rows containing grades for the student with ID=300.
Search all the rows with grades from the course with ID-1.
Composing indexes
• We can easily see that the value 1 for id_curs is randomly distributed in the index. That is why is not efficient to search using this index.
• How do we do it better ?
• We have an index built upon the same columns (in a different order though).
DROP INDEX idx_grades;
CREATE UNIQUE INDEX idx_grades
ON grades(id_coursw, id_student);
50
51
Composing indexes
• The most important when creating composed indexes is to know what data we can access using that index.
• If we want to index 3 fields, that index can be used by querries of 1st field, querries on the 1st
+ 2nd fields or querries upon all three fields. NO OTHER COMBINATION WILL BE ABLE TO USE THE QUERRY.
• However, you can use 2+1 or 2+3+1 (he knows his that and operation is commutative).
52
WHERE clause
• When it’s possible a single index is better to use then 2 different indexes (balancing 1 tree is easier then balancing 2 trees).
• To make a composed index efficient, we also have to know how the data is accessed – this is usually known only by the programmer.
53
Slow indexes
• Changing an index can affect the entire application (e.g. now none of the querriesusing id_student will be able to use the index).
54
• What if we build 2 different indexes, each on a field. Can they both be used ? If now, which one will be ?
55
56
Slow indexes
• The Query Optimizer
Cost based optimizers (CBO)
Rule-based optimizers (RBO)
57
Statistics
• CBO uses some statistics about DB (e.g. about: columns, tables, indexes). For example, for a table he can hold statistics regarding:
- Highes and smallest value,
- The number of distinct data in a column,
- Number of fields NULL,
- Data distribution (histogram),
- How many rows and blocks it uses.
58
Statistics
• CBO uses some statistics about DB (e.g. about: columns, tables, indexes). For example, for a index he can hold statistics regarding:
- how deep the B+ tree is,
- number of leafs,
- number of distinct values in the index,
- “clustering” factor (data of apropiate of same values are in the same location on HDD).
• Using indexes is not always the best ideea.59
Indecsi bazati pe functii
60
Functii
• Sa presupunem ca dorim sa facem o cautaredupa last_name.
61
Functii• Evident, aceasta cautare va fi mai rapida daca:
CREATE INDEX emp_name ON employees (last_name);
62
Functii• Ce se intampla daca vreau ignorecase?
• Pentru o astfel de cautare, desi avem un index construit peste coloana cu last_name, acesta va fi ignorat [de ce ? – exemplu]
[poate utilizarea unui alt collation ?!]*
• Pentru ca BD nu cunoaste rezultatul apeluluiunei functii a-priori, functia va trebui apelatapentru fiecare linie in parte.
*SQL Server sau MySQL nu fac distinctie intre cases cand sorteazainformatiile in indecsi.
63
FunctiiSELECT * FROM employees
WHERE UPPER(last_name) = UPPER('winand');
Isi da seama ca e mai eficient sa evaluezefunctia pentru valoarea constanta si sa nu faca
acest lucru pentru fiecare rand in parte. 64
Functii• Cum vede BD interogarea ?SELECT * FROM employees
WHERE BLACKBOX(...) = 'WINAND';
• Se observa totusi ca partea dreapta a expresieieste evaluata o singura data. In fapt filtrul a fost facut pentru
UPPER(“last_name”)=„WINAND‟
65
Functii• Indexul va fi reconstruit pesteUPPER(last_name)
drop index emp_name;
CREATE INDEX emp_up_name
ON employees (UPPER(last_name));
66
Functii - function-based index (FBI)SELECT * FROM employees
WHERE UPPER(last_name) = UPPER('winand');
67
Functii• In loc sa puna direct valoarea campului in
index, un FBI stocheaza valoarea returnata de functie.
• Din acest motiv functia trebuie sa returnezemereu aceeasi valoare: nu sunt permise decatfunctii deterministe.
• A nu se construi FBI cu functii ce returneazavalori aleatoare sau pentru cele care utilizeazadata sistemului pentru a calcula ceva. [days untill xmas]
68
Functii• Nu exista cuvinte rezervate sau optimizari
pentru FBI (altele decat cele deja explicate).
• Uneori instrumentele pentru Object relation mapping (ORM tools) injecteaza din prima o functie de conversie a tipului literelor (upper / lower). De ex. Hibernate converteste totul in lower.
• Puteti construi proceduri stocate deterministeca sa fie folosite in FBI. getAge ?!?!
69
Functii – nu indexati TOT• De ce ? (nu are sens sa fac un index pt. lower)
(daca tot aveti peste upper). De fapt, daca existao functie bijectiva de la felul in care sunt indexatedatele la felul in care vreti sa interogati baza de date, mai bine refaceti interogarea – cu sigurantaeste posibil !).
• Incercati sa unificati caile de acces ce ar putea fiutilizate pentru mai multe interogari.
• E mai bine sa puneti indecsii peste dateleoriginale decat daca aplicati functii peste acestea.
70
Parametri dinamici
71
Parametri dinamici (bind parameters, bind variables)
• Sunt metode alternative de a trimiteinformatii catre baza de date.
• In locul scrierii informatiilor direct in interogare, se folosesc constructii de tipul ? si:name (sau @name) iar datele adevarate sunttransmise din apelul API
• E “ok” sa punem valorile direct in interogaredar abordarea parametrilor dinamici are uneleavantaje:
72
Parametri dinamici (bind parameters, bind variables)
• Avantajele folosirii parametrilor dinamici:
Securitate [impiedica SQL injection]
Performanta [obliga QO sa foloseasca acelasi plan de executie]
73
Parametri dinamici (bind parameters, bind variables)
• Securitate: impiedica SQL injection*statement = "SELECT * FROM users
WHERE name ='" + userName + "';“
Daca userName e modificat in ' or '1'='1
Daca userName e modificat in: a';DROPTABLE users; SELECT * FROM
userinfo WHERE 't' = 't
* http://en.wikipedia.org/wiki/SQL_injection 74
75
76
Parametri dinamici (bind parameters, bind variables)
• Avantajele folosirii parametrilor dinamici:Securitate
Performanta
• Performanta: Baze de date (Oracle, SQL Server) pot salva (in cache) executii ale planurilor pe care le-au considera eficiente darDOAR daca interogarile sunt EXACT la fel. Trimitand valori diferite (nedinamic), suntformulate interogari diferite.
77
Si, reamintesc….
78
Parametri dinamici (bind parameters, bind variables)
• Utilizand parametri dinamici, cele doua vor fiprocesate dupa acelasi plan. E mai bine ?
• Neavand efectiv valorile, se va executa planulcare este considerat mai eficient daca valoriledate pentru subsidiary_id ar fidistribuite uniform. [atentie, nu valorile din tabela ci cele din interogare !]
79
Parametri dinamici (bind parameters, bind variables)
• Query optimizer este ca un compilator:
- daca ii sunt trecute valori ca si constante,
se foloseste de ele in acest mod;
- daca valorile sunt dinamice, le vede ca
variabile neinitializate si le foloseste ca
atare.
• Atunci de ce ar functiona mai bine cand nu sunt stiute valorile dinainte ?
80
Parametri dinamici (bind parameters, bind variables)
• Atunci cand este trimisa valoarea, The query optimizer va construi mai multe planuri, vastabili care este cel mai bun dupa care il vaexecuta. In timpul asta, s-ar putea ca un plan (prestabilit), desi mai putin eficient, sa fiexecutat deja interogarea.
• Utilizarea parametrilor fixati e ca si cum aicompila programul de fiecare data.
81
Parametri dinamici (bind parameters, bind variables)
• Cine “bindeaza” variabilele poate face eficienta interogarea (programatorul): se vorfolosi parametri dinamici pentru toatevariabilele MAI PUTIN pentru cele pentru care se doreste sa influenteze planului de executie.
• In all reality, there are only a few cases in which the actual values affect the execution plan. You should therefore use bind parameters if in doubt—just to prevent SQL injections.
82
Parametri dinamici (bind parameters, bind variables) – exemplu Java:
Fara bind parameters:
int subsidiary_id = 20;
Statement command =
connection.createStatement(
"select first_name, last_name" +
" from employees" +
" where subsidiary_id = " +
subsidiary_id );
83
Parametri dinamici (bind parameters, bind variables) – exemplu Java:
Cu bind parameters:
int subsidiary_id = 20;
PreparedStatement command =
connection.prepareStatement(
"select first_name, last_name" +
" from employees" +
" where subsidiary_id = ?" );
command.setInt(1, subsidiary_id);
int rowsAffected =
preparedStatement.executeUpdate();
http://use-the-index-luke.com/sql/where-clause/bind-parameters - C#, PHP, Perl, Java, Ruby
Se repeta pentrufiecare parametru
84
Parametri dinamici (bind parameters, bind variables)- Ruby:Fara parametri dinamici:dbh.execute("select first_name, last_name" +
" from employees" +
" where subsidiary_id = #{subsidiary_id}");
Cu parametri dinamici:dbh.prepare("select first_name, last_name" +
" from employees" +
" where subsidiary_id = ?");
dbh.execute(subsidiary_id);
85
Parametri dinamici (bind parameters, bind variables)
• Semnul intrebarii indica o pozitie. El va fiindentificat prin 1,2,3… (pozitia lui) atuncicand se vor trimite efectiv parametri.
• Se poate folosi “@id” (in loc de ? si de 1,2…).
86
Parametri dinamici (bind parameters, bind variables)
• Parametri dinamici nu pot schimba structurainterogarii (Ruby):
String sql = prepare("SELECT * FROM ?
WHERE ?");
sql.execute('employees',
'employee_id = '1');
Pentru a schimba structura interogarii: dynamic SQL. 87
Cautari pe intervale
88
Q: Daca avem doua coloane, una dintre ele cu foarte multe valori diferite si cealalta cu foartemulte valori identice. Pe care o punem prima in index ?
[carte de telefon:numele sunt mai diversificate decat prenumele]
89
Cautari pe intervale
• Sunt realizate utilizand operatorii <, > saufolosind BETWEEN.
• Cea mai mare problema a unei cautari intr-un interval este traversarea frunzelor.
• Ar trebui ca intervalele sa fie cat mai miciposibile. Intrebarile pe care ni le punem:
unde incepe un index scan ?
unde se termina ?
90
Cautari pe intervale
SELECT first_name, last_name,
date_of_birth
FROM employees
WHERE
date_of_birth >= TO_DATE(?, 'YYYY-
MM-DD')
AND
date_of_birth <= TO_DATE(?, 'YYYY-
MM-DD')
Inceput
Sfarsit91
Cautari pe intervale
SELECT first_name, last_name,
date_of_birth
FROM employees
WHERE
date_of_birth >= TO_DATE(?, 'YYYY-
MM-DD') AND
date_of_birth <= TO_DATE(?, 'YYYY-
MM-DD') AND
AND subsidiary_id = ?
???92
Cautari pe intervale
• Indexul ideal acopera ambele coloane.
• In ce ordine ?
93
1 Ianuarie 19719 ianuarie 1971
Sub_id=27
94
Sub_id=27
1 Ianuarie 19719 ianuarie 1971
95
Cautari pe intervale
Regula: indexul pentru egalitate primul
si apoi cel pentru interval !
Nu e neaparat bine ca sa punem pe prima pozitie coloana cea mai diversificata.
96
Cautari pe intervale
• Depinde si de ce interval cautam (pentruintervale foarte mari s-ar putea sa fie maieficient invers).
• Nu este neaparat ca acea coloana cu valorilecele mai diferite sa fie prima in index – vezicazul precedent in care sunt doar 30 de IDurisi 365 de zile de nastere (x ani).
• Ambele indexari faceau match pe 13 inregistrari.
97
Cautari pe intervale
Dupa ce a fostgasit intervalul, datele au fost
filtrate…
Deci prima coloana din index este… ? 98
Cautari pe intervale
• Acces – indica de unde incepe si unde se termina rangeul pentru cautare.
• Filtrul – preia un range si selecteaza doarliniile care satisfac o conditie.
• Daca schimbam ordinea coloanelor din index:
(subsidiary_id, date_of_birth)
99
Cautari pe intervale
100
Cautari pe intervale
• Operatorul BETWEEN este echivalent cu o cautare in interval dar considerand simarginile intervalului.
DATE_OF_BIRTH BETWEEN '01-JAN-71'
AND '10-JAN-71
Este echivalent cu:DATE_OF_BIRTH >= '01-JAN-71' AND
DATE_OF_BIRTH <= '10-JAN-71‟
101
LIKE
102
LIKE
• Operatorul LIKE poate avea repercusiuninedorite asupra interogarii (chiar cand suntfolositi indecsi).
• Unele interogari in care este folosit LIKE se pot baza pe indecsi, altele nu. Diferenta o face pozitia caracterului % .
103
LIKE
SELECT first_name, last_name,
date_of_birth
FROM employees
WHERE UPPER(last_name) LIKE 'WIN%D'
104
LIKE
• Doar primele caractere dinainte de % pot fiutilizate in cautarea bazata pe indecsi. Restulcaracterelor sunt utilizate pentru a filtrarezultatele obtinute.
• Daca in exemplul anterior punem un index peste UPPER(last_name), iata cum ar fiprocesate diverse interogarile in functie in care caracterul % este asezat in diverse pozitii:
105
LIKE
106
LIKE
• Ce se intampla daca LIKE-ul este de formaLIKE '%WI%D' ?
107
LIKE
• A se evita expresii care incep cu %.
• In teorie, %, influenteaza felul in care estecautata expresia. In practica, daca suntutilizati parametri dinamici, nu se stie cum Querry optimizer va considera ca este mai binesa procedeze: ca si cum interogarea ar incepecu % sau ca si cum ar incepe fara?
108
LIKE
• Daca avem de cautat un cuvant intr-un text, nu conteaza daca acel cuvant este trimis ca parametru dinamic sau hardcodat in interogare. Cautarea va fi oricum de tipul%cuvant% . Totusi, folosind parametridinamici, macar evitam SQL injection.
109
LIKE
• Pentru a “optimiza” cautarile cu clauza LIKE, se poate utiliza in mod intentionat alt camp indexat (daca se stie ca intervalul ce va fireturnat de index va contine oricum textul cecontine parametrul din like).
Q: Cum ati putea indexa totusi pentru a optimizao cautare care sa aiba ca si clauza:
LIKE '%WINAND'
110
Contopirea indecsilor
Indecsi de tip Bitmap
111
Contopirea indecsilor
• Este mai bine sa se utilizeze cate un index pentru fiecare coloana sau e mai bine sa fie utilizati indecsi pe mai multe coloane ?
• Sa studiem urmatoarea interogare:
SELECT first_name, last_name, date_of_birth
FROM employees
WHERE UPPER(last_name) < ?
AND date_of_birth < ?
112
Contopirea indecsilor
• Indiferent de cum ar fi intoarsa problema, nu se poate construi un index care sa duca atatnumele cat si data de nastere intr-un interval compact (cu inregistrari consecutive) [decatdaca nu cumva toate mamele si-au botezatcopii nascuti in Iulie drept “Iulian” ].
• Indexul peste doua coloane nu ne ajutaextraordinar. Totusi, daca il construim, punemcoloana cu valorile cele mai diferite pe prima pozitie.
De ce ? 113
Contopirea indecsilor
• O a doua posibilitate este utilizarea de indecsidiferiti pentru fiecare coloana si lasat QO sadecida cum sa ii foloseasca [deja s-ar putea saia mai mult timp pentru ca poate crea de douaori mai multe planuri].
• Pont: o cautare dupa un singur index este mairapida decat daca sunt doi indecsi implicati.
114
Contopirea indecsilor
• Data warehouse (DW) este cel care are grijade toate interogarile ad-hoc.
• Din cauza ca nu poate folosi un index clasic, foloseste un tip special de index: bitmap index (felul cum sunt indexate patratele de pe o tabla de sah).
• Merge oarecum mai bine decat fara (dar nu mai bine ca un index folosit eficient).
115
Bitmap Index
http://www.dba-oracle.com/oracle_tips_bitmapped_indexes.htm
[nu este din luke…+ 116
Contopirea indecsilor
• Dezavantajul folosirii indecsilor de tip bitmap:
timpul ridicol de mare pentru operatii de insert/delete/update.
nu permite scrieri concurente (desi in DW pot fiexecutate serial)
In aplicatii online, indecsii de tip bitmap sunt inutili
• Uneori arborii de acces (B-trees) sunt convertiti(temporar) in bitmaps de catre BD pentru a executa interogarea (nu sunt stocati) – solutiedisperata a QO ce foloseste CPU+RAM.
117
Indecsi Partiali
Indexarea NULL
118
• Sa analizam interogarea:
SELECT message
FROM messages
WHERE processed = 'N'
AND receiver = ?
• Preia toate mailurile nevizualizate (de exemlu). Cum ati indexa ? [ambele sunt cu =]
119
• Am putea crea un index de forma:
CREATE INDEX messages_todo ON
messages (receiver, processed)
• Se observa ca processed imparte tabela in doua categorii: mesaje procesate si mesajeneprocesate.
120
Indecsi partiali
• Unele BD permit indexarea partiala. Astainseamna ca indexul nu va fi creat decat pesteanumite linii din tabel.
CREATE INDEX messages_todo
ON messages (receiver)
WHERE processed = 'N'
Atentie: nu merge in Oracle…
121
Indecsi partiali
• Ce se intampla la executia codului:
SELECT message
FROM messages
WHERE processed = 'N';
122
Indecsi partiali
• Indexul nou construit este redus si pe verticala(pentru ca are mai putine linii) dar si peorizontala (nu mai trebuie sa aiba grija de coloana “processed”).
• Se poate intampla ca dimensiunea sa fie constanta (de exemplu nu am mereu ~500 de mailuri necitite) chiar daca numarul liniilor din BD creste.
123
NULL in Oracle
• Ce este NULL in Oracle ?
• In primul rand trebuie folosit “IS NULL” si nu “=NULL”.
• NULL nu este mereu conform standardului (artrebui sa insemne absenta datelor).
• Oracle trateaza un sir vid ca si NULL ?!?! (de fapt trateaza ca NULL orice nu stie sau nu intelege sau care nu exista).
124
125
NULL in Oracle
• Mai mult, Oracle trateaza NULL ca sir vid:
126
NULL in Oracle
• Daca am creat un index dupa o coloana X siapoi adaugam o inregistrare care sa aiba NULL pentru X, acea inregistrare nu este indexata.
127
NULL in Oracle
INSERT INTO employees ( subsidiary_id,
employee_id , first_name , last_name ,
phone_number)
VALUES ( ?, ?, ?, ?, ? );
• Noul rand nu va fi indexat:SELECT first_name, last_name
FROM employees
WHERE date_of_birth IS NULL
Table access
full
alter table employees modify (date_of_birth null); 128
Neinserand data de nastere, aceasta va fi
NULL
Indexarea NULL in Oracle
CREATE INDEX demo_null ON employees
(subsidiary_id, date_of_birth);
• Si apoi:SELECT first_name, last_name
FROM employees
WHERE subsidiary_id = ?
AND date_of_birth IS NULL
129
NOT NULL
Indexarea NULL in Oracle
• Ambele predicate sunt utilizate !
130
Indexarea NULL in Oracle
• Atunci cand indexam dupa un camp ce s-arputea sa fie NULL, pentru a ne asigura ca siaceste randuri sunt indexate, trebuie adaugatun camp care sa fie NOT NULL ! (poate fiadaugat si o constanta – de exemplu ‘1’):
DROP INDEX emp_dob;
CREATE INDEX emp_dob ON employees
(date_of_birth, '1');
131
NOT NULL CONSTRAINTS….Asta este NOT NULL
132
Indexarea NULL in Oracle
• Fara NOT NULL pus pe last_name (care e folosit in index), indexul este inutilizabil.
• Se gandeste ca poate exista cazul cand ambelecampuri sunt nule si acel caz nu e bagat in index.
133
Indexarea NULL in Oracle
• O functie creata de utilizator este considerataca fiind NULL (indiferent daca este sau nu).
• Exista anumite functii din Oracle care suntrecunoscute ca intorc NULL atunci cand datelede intrare sunt NULL (de exemplu functiaupper).
134
Indexarea NULL in Oracle
• a
In opinia lui, ambele pot fi
NULL.Desi id esteNOT NULL
135
• a
Ii spunem clar ca nu ne intereseaza unde
functia da NULL.
136
Indexarea NULL in Oracle
• a
Sau ii spunem ca acest camp este
mereu NOT NULL.
Si folosimcoloana in index
137
Indexarea NULL in Oracle
• a
Daca initial last_name este nenul va stica upper(last_name) este tot nenul.
138
Emularea indecsilor partiali in Oracle
CREATE INDEX messages_todo
ON messages (receiver)
WHERE processed = 'N'
• Avem nevoie de o functie care sa returnezeNULL de fiecare data cand mesajul a fostprocesat.
139
Emularea indecsilor partiali in Oracle
CREATE OR REPLACE FUNCTION
pi_processed(processed CHAR,
receiver NUMBER)
RETURN NUMBER DETERMINISTIC AS
BEGIN
IF processed IN ('N')
THEN RETURN receiver;
ELSE RETURN NULL;
END IF;
END; /
Pentru a putea fi utilizata in index.
140
Indexarea NULL in OracleDeoarece stie ca aici va veni o valoare, QO face un singur plan (cu
index). Daca ar fi fost null ar fi fost testat cu “IS NULL”.
141
Conditii obfuscate
142
Metode de Ofuscare – siruri numerice
• Sunt numere memorate in coloane de tip text
• Desi nu e practic, un index poate fi folositpeste un astfel de sir de caractere (indexuleste peste sirul de caractere):
SELECT ... FROM ... WHERE
numeric_string = '42„
• Daca s-ar face o cautare de genul:
143
Metode de Ofuscare – siruri numerice
SELECT ... FROM ... WHERE
numeric_string = 42
• Unele SGBDuri vor semnala o eroare(PostgreSQL) in timp ce altel vor face o conversia astfel:
SELECT ... FROM ... WHERE
TO_NUMBER(numeric_string) = 42
144Va merge pe index ? (care era construit peste sirul de caractere ?!?!)
Metode de Ofuscare – siruri numerice
• Problema este ca nu ar trebui sa convertim sirulde caractere din tabel ci mai degraba saconvertim numarul (pentru ca indexul e pe sir):
SELECT ... FROM ... WHERE
numeric_string = TO_CHAR(42)
• De ce nu face baza de date conversia in acestmod ? Pentru ca datele din tabel ar putea fistocate ca ‘42’ dar si ca ‘042’, ‘0042’ care suntdiferite ca si siruri de caractere dar reprezintaacelasi numar.
145
Metode de Ofuscare – siruri numerice
• Conversia se face din siruri in numeredeoarece ‘42’ sau ‘042’ vor avea aceeasivaloare cand sunt convertite. Totusi 42 nu vaputea fi vazut ca fiind atat ‘42’ cat si ‘042’ cand este convertit in sir numeric.
• Diferenta nu este numai una de performantadar chiar una ce tine de semantica.
146
Metode de Ofuscare – siruri numerice
• Utilizarea sirurilor numerice intr-o tabela esteproblematica (de exemplu din cauza ca poatefi stocat si altceva decat un numar).
• Regula: folositi tipuri de date numerice ca sastocati numere.
147
Metode de Ofuscare - Date
• Data include o componenta temporala
• Trunc(DATE) seteaza data la miezul noptii.
SELECT ... FROM sales WHERE
TRUNC(sale_date) =
TRUNC(sysdate – INTERVAL '1' DAY)
Nu va merge corect daca indexul este pus pesale_date deoarece TRUNC=blackBox.
CREATE INDEX index_name ON table_name
(TRUNC(sale_date))
148
Metode de Ofuscare - Date
• Este bine ca indecsii sa ii punem peste dateleoriginale (si nu peste functii).
• Daca facem acest lucru putem folosi acelasiindex si pentru cautari ale vanzarilor de ieridar si pentru cautari a vanzarilor din ultimasaptamana / luna sau din luna N.
149
Metode de Ofuscare - Date
SELECT ... FROM sales WHERE
DATE_FORMAT(sale_date, "%Y-%M") =
DATE_FORMAT(now() , "%Y-%M')
• Cauta vanzarile din luna curenta. Mai rapid este:
SELECT ... FROM sales WHERE
sale_date BETWEEN month_begin(?)
AND month_end(?)
150
Metode de Ofuscare - Date
• Regula: scrieti interogarile pentru perioada ca si conditii explicite (chiar daca e vorba de o singura zi).
sale_date >= TRUNC(sysdate) AND
sale_date < TRUNC(sysdate +
INTERVAL '1' DAY)
151
Metode de Ofuscare - Date
• O alta problema apare la compararea tipurilor date cu siruri de caractere:
SELECT ... FROM sales WHERE TO_CHAR(sale_Date, 'YYYY-MM-DD') = '1970-01-01'
• Problema este (iarasi) conversia coloanei ce reprezintadata.
• Oamenii traiesc cu impresia ca parametrii dinamicitrebuie sa fie numere sau caractere. In fapt ele pot fichiar si de tipul java.util.Date
152
Metode de Ofuscare - Date
• Daca nu puteti trimite chiar un obiect de tip Date ca parametru, macar nu faceti conversiacoloanei (evitand a utiliza indexul). Mai bine:
SELECT ... FROM sales WHERE sale_date
= TO_DATE('1970-01-01', 'YYYY-MM-
DD')
Index peste sale_date
153
Fie direct sir de caractere sau chiar parametrudinamic trimis ca sir de caractere.
Metode de Ofuscare - Date
• Cand sale_date contine o data de tip timp, e mai bine sa utilizam intervale) :
SELECT ... FROM sales WHERE
sale_date >= TO_DATE('1970-01-01',
'YYYY-MM-DD') AND
sale_date < TO_DATE('1970-01-01',
'YYYY-MM-DD') + INTERVAL '1' DAY
sale_date LIKE SYSDATE154
Metode de Ofuscare - Math
• Putem crea un index pentru ca urmatoareainterogare sa functioneze corect?
SELECT numeric_number FROM table_name
WHERE numeric_number - 1000 > ?
• Dar pentru:SELECT a, b FROM table_name
WHERE 3*a + 5 = b
155
Metode de Ofuscare - Math
• In mod normal NU este bine sa punem SGBD-ul sa rezolve ecuatii.Pentru el, si urmatoareainterogare va face full scan:
SELECT numeric_number FROM table_name
WHERE numeric_number + 0 > ?
• Totusi am putea indexa in felul urmator:CREATE INDEX math ON table_name (3*a - b)
SELECT a, b FROM table_name
WHERE 3*a - b = -5;156
Chiar de are index peste numeric_number, nu are peste suma lui cu 0 !
Metode de Ofuscare – “Smart logic”
SELECT first_name, last_name,
subsidiary_id, employee_id FROM
employees WHERE
( subsidiary_id = :sub_id OR :sub_id
IS NULL ) AND
( employee_id = :emp_id OR :emp_id IS
NULL ) AND
( UPPER(last_name) = :name OR :name
IS NULL )
157
Metode de Ofuscare – “Smart logic”
• Cand nu se doreste utilizarea unuia dintre filtre, se trimite NULL in parametrul dinamic.
• Baza de date nu stie care dintre filtre este NULL sidin acest motiv se asteapta ca toate pot fi NULL => TABLE ACCESS FULL + filtru (chiar daca existaindecsi).
• Problema este ca QO trebuie sa gaseasca planulde executie care sa acopere toate cazurile(inclusiv cand toti sunt NULL), pentru ca va folosiacelasi plan pentru interogarile cu var. dinamice.
158
Metode de Ofuscare – “Smart logic”
• Solutia este sa ii zicem BD ce avem nevoie siatat:
SELECT first_name, last_name,
subsidiary_id, employee_id FROM
employees
WHERE UPPER(last_name) = :name
• Problema apare din cauza share execution plan pentru parametrii dinamici.
159
Performanta - Volumul de date
Don't ask a DBA to help you move furniture.They've been known to drop tables…
160
Volumul de date
• O interogare devine mai lenta cu cat sunt maimulte date in baza de date
• Cat de mare este impactul asupraperformantei daca volumul datelor se dubleaza ?
• Cum putem imbunatati ?
161
Volumul de date
• Interogarea analizata:
SELECT count(*) FROM scale_data
WHERE section = ? AND id2 = ?
• Section are rolul de a controla volumul de date. Cu cat este mai mare section, cu atateste mai mare volumul de date returnat.
• Consideram doi indecsi: index1 si index2
162
Volumul de date
• Interogarea analizata:
SELECT count(*) FROM scale_data
WHERE section = ? AND id2 = ?
• Section mic – index1 si apoi index2
163
Volumul de date
• Scalabilitatea indica dependenta performanteiin functie de factori precum volumul de informatii.
164
Volumul de date
• index1 – timp dublu fata de cel initial
• index2 – trimp x20 fata de cel initial
165
Volumul de date
• Raspunsul unei interogari depinde de maimulti factori. Volumul de date e unul dintre ei.
• Daca o interogare merge bine in faza de test, nu e neaparat ca ea sa functioneze bine si in productie.
• Care este motivul pentru care apare diferentadintre index1 si index2 ?
166
Ambele par identice ca executie:
167
Volumul de date
• Ce influenteaza un index ?
table acces
scanarea unui interval mare
• Nici unul din planuri nu indica acces pe bazaindexului (TABLE ACCES BY INDEX ROW ID)
• Unul din intervale este mai mare atunci cand e parcurs…. trebuie sa avem acces la “predicate information” ca sa vedem de ce:
168
169
170
Volumul de date
• Puteti spune cum a fost construit indexulavand planurile de executie ?
171
Volumul de date
• Puteti spune cum a fost construit indexulavand execution plans ?
• CREATE INDEX scale_slow ON
scale_data (section, id1, id2);
• CREATE INDEX scale_fast ON
scale_data (section, id2, id1);
Campul id1 este adaugat doar pentru a pastraaceeasi dimensiune (sa nu se creada ca indexulscale_fast e mai rapid pentru ca are mai putinecampuri in el). 172
Incarcarea sistemului
• Faptul ca am definit un index pe care ilconsideram bun pentru interogarile noastrenu il face sa fie neaparat folosit de QO.
• SQL Server Management Studio Arata predicatuldoar ca un tooltip
173
Incarcarea sistemului
• De regula, impreuna cu numarul de inregistrari, creste si numarul de accesari.
• Numarul de accesari este alt parametru ceintra in calculul scalabilitatii.
174
Incarcarea sistemului
• Daca initial era doar o singura accesare, considerand acelasi scenariu dar cu 1-25 interogari concurente, timpul de raspunscreste:
175
Incarcarea sistemului
• Asta inseamna ca si daca avem toata baza de date din productie si testam totul pe ea, tot sunt sanse ca in realitate, din cauza numaruluimare de interogari, sa mearga mult mai greu.
• Nota: atentia data planului de executie estemai importanta decat benchamarkurisuperficiale ( gen SQL Server Management Studio).
176
Incarcarea sistemului
• Ne-am putea astepta ca hardwareul mai puternicdin productie sa duca mai bine sistemul. In fapt, in faza de development nu exista deloc latenta –ceea ce nu se intampla in productie (unde accesulpoate fi intarziat din cauza retelei).
• http://blog.fatalmind.com/2009/12/22/latency-security-vs-performance/
• http://jamesgolick.com/2010/10/27/we-are-experiencing-too-much-load-lets-add-a-new-server..html
177
Timpi de raspuns + throughput
• Hardware mai performant nu este mai rapid doar poate duce mai multa incarcare.highway
• Procesoarele single-core vs procesoarelemulti-core (cand e vorba de un singur task).
• Scalarea pe orizontala (adaugarea de procesoare) are acelasi efect.
• Pentru a imbunatati timpul de raspuns estenecesar un arbore eficient (chiar si in NoSQL).
178
Timpi de raspuns
• Indexarea corecta fac cautarea intr-un B-tree in timp logaritmic.
• Sistemele bazate pe NoSQL par sa fi rezolvatproblema performantei prin scalare pe orizontala[analogie cu indecsii partiali in care fiecarepartitie este stocata pe o masina diferita].
• Aceasta scalabilitate este totusi limitata la operatiile de scriere intr-un model denumit“eventual consistency” *Consistency / Availability / Partition tolerance = CAP theorem] http://en.wikipedia.org/wiki/CAP_theorem
179
Timpi de raspuns
• Mai mult hardware de obicei nu imbunatateste sistemul.
• Latency al HDD [problema apare cand datelesunt culese din locatii diferite ale HDDului – de exemplu in cadrul unei operatii JOIN]. SSD?
180
“Facts”
• Performance has two dimensions: response time and throughput.
• More hardware will typically not improve query response time.
• Proper indexing is the best way to improve query response time.
181
Join
An SQL query walks into a bar and sees two tables.
He walks up to them and asks ’Can I join you?’
— Source: Unknown
182
Join
• Join-ul transforma datele dintr-un model normalizat intr-unul denormalizat care serveste unui anumit scop.
• Sensibil la latente ale discului (si fragmentare).
183
Join
• Reducerea timpilor = indexarea corecta
• Toti algoritmii de join proceseaza doar douatabele simultan (apoi rezultatul cu a treia, etc).
• Rezultatele de la un join sunt trimise in urmatoarea operatie join fara a fi stocate.
• Ordinea in care se efectueaza JOIN-ulinfluenteaza viteza de raspuns.[10, 30, 5, 60]
• QO incearca toate permutarile de JOIN.
• Cu cat sunt mai multe tabele, cu atat mai multeplanuri de evaluat. [cate ?]
184
Join
• Cu cat sunt mai multe tabele, cu atat maimulte planuri de evaluat = O(n!)
• Nu este o problema cand sunt utilizatiparametri dinamici [De ce ?]
185
Join – Nested Loops (anti patern)
• Ca si cum ar fi doua interogari: cea exterioarapentru a obtine o serie de rezultate dintr-o tabela si cea interioara ce preia fiecare rand obtinut si apoi informatia corespondenta din cea de-a doua tabela.
• Se pot folosi Nested Selects pentru a simulaalgoritmul de nested loops [latenta retelei, usurinta implementarii, Object-relational mapping (N+1 selects)].
186
Join – nested selects [PHP] java, perl on “luke…”
187
Join – nested selects
188
Join – nested selects
189Ce indecsi ati crea ca sa fie mai rapida executia ?
Join – nested selects
• DB executa joinul exact ca si in exemplulanterior. Indexarea pentru nested loops estesimilara cu cea din selecturile anterioare:
1. Un FBI (function based Index) pesteUPPER(last_name)
2. Un Index concatenat peste subsidiary_id, employee_id
190
Join – nested selects
• Totusi, in BD nu avem latenta din retea.
• Totusi, in BD nu sunt transferate dateleintermediare (care sunt piped in BD).
• Pont: executati JOIN-urile in baza de date si nu in Java/PHP/Perl sau in alt limbaj (ORM).
There you go: PLSQL style ;)
191
Join – nested selects
• Cele mai multe ORM permit SQL joins.
• eager fetching – probabil cel mai important (va prelua si tabela vanzari –in mod join–atunci cand se interogheaza angajatii).
• Totusi eager fetching nu este bun atunci candeste nevoie doar de tabela cu angajati (aducesi date irelevante) – nu am nevoie de vanzaripentru a face o carte de telefoane cu angajatii.
• O configurare statica nu este o solutie buna.
192
193
Join
194
Join – nested selects
• Sunt bune daca sunt intoarse un numar mic de inregistrari.
• http://blog.fatalmind.com/2009/12/22/latency-security-vs-performance/
195
Join – Hash join
• Evita traversarea multipla a B-tree din cadrulinner-querry (din nested loops) construindcate o tabela hash pentru inregistrarilecandidat.
• Hash join imbunatatit daca sunt selectate maiputine coloane.
• A se indexa predicatele independente din where pentru a imbunatati performanta. (peele este construit hashul)
196
Join – Hash join
SELECT * FROM
sales s JOIN employees e
ON (s.subsidiary_id = e.subsidiary_id
AND s.employee_id = e.employee_id )
WHERE s.sale_date > trunc(sysdate) -
INTERVAL '6' MONTH
197
Join – Hash join
198
Join – Hash join
• Indexarea predicatelor utilizate in join nu imbunatatesc performanta hash join !!!
• Un index ce ar putea fi utilizat este pestesale_date
• Cum ar arata daca s-ar utiliza indexul ?
199
Join – Hash join
200
Join – Hash join
• Ordinea conditiilor din join nu influenteazaviteza (la nested loops influenta).
201
Bibliografie (online)
• http://use-the-index-luke.com/
( puteti cumpara si cartea in format PDF – darnu contine altceva decat ceea ce este pe site)
202
Join
203