UNIVERZA V LJUBLJANI FAKULTETA ZA ELEKTROTEHNIKO MATJAŽ MRGOLE OGRODJE ZA OPTIMIZACIJO INDEKSOV V MYSQL BAZAH PODATKOV DIPLOMSKO DELO UNIVERZITETNEGA ŠTUDIJA Mentor: doc. dr. Boštjan Murovec Ljubljana, 2013 ZAHVALA Iskreno se zahvaljujem svojemu mentorju, doc. dr. Boštjanu Murovcu, za neprecenljivo pomoč in nasvete pri izdelavi naloge ter hitre odzive na vsa moja vprašanja. Posebej se zahvaljujem svoji družini, ki mi je omogočila študij in me podpiralana moji poti. POVZETEK Informacijsko dobo, v kateri se trenutno nahajamo, zaznamuje široka in intenzivna uporaba informacij. Te je potrebno nekam shraniti, da jih ne izgubimo in da lahko kasneje do njih dostopamo. Ta problem v veliki meri rešujejo podatkovne baze. Ena izmed popularnih podatkovnih baz je MySQL. Pri relacijskih podatkovnih bazah do podatkov dostopamo s poizvedbami. Te lahko napišemo na več načinov, zato je neizogibno,da se le–te med seboj po kakovosti razlikujejo. Hkrati je priporočljivo pri poizvedbah, ki iščejo določeno vrednost ali združujejo podatke iz večih tabel, postaviti indekse.Indeks je podatkovna struktura, ki nam omogoča, da v poizvedbi poiščemo vrstice iz tabele mnogo hitreje kot sicer. V primeru, da indeksi v podatkovnih bazah niso ustrezno postavljeni, poizvedbe trajajo dlje časa, kot je dejansko potrebno. Analiza optimalnega postavljanja indeksov in optimalnega pisanja poizvedb zahteva veliko predznanja. Ker za podatkovno bazo MySQL ne obstajajo orodja, ki bi to namesto nas avtomatizirala, smo v ta namen izdelali lastno ogrodje. Podatkovna bazaje v našem primeru integrirana v spletni strežnik s podporo programskega jezika PHP za izdelavodinamičnih spletnih vsebin. Izdelano ogrodje s pregledom PHP izvorne kode zazna poizvedbe in nato postavi indekse ter opozori na potencialne možnosti izboljšav v sestavi poizvedbe. Delovanje smo preizkusili na dveh projektih. Eden je uporabljal podatkovno bazo, ki jo MySQL priporoča kot testno podatkovno bazo za učenje. V obeh primerih je ogrodje zelo dobro služilo svojem namenu, saj je indekse postavilo ekvivalentno dobremu strokovnjaku z nekaj letnimi izkušnjami dela s podatkovnimi bazami. Zato je rešitevprimerna tako za začetnike kot za izkušene uporabnike podatkovnih baz. KLJUČNE BESEDE: optimizacija SQL poizvedb, postavitev indeksov, relacijske podatkovne baze, MySQL ABSTRACT The information age we live in nowadays is marked by a wide and intensive use of information. In order not to be lost and to be accessible in the long term, it needs to be stored. This problem is mostly solved by databases. One of the popular databases is called MySQL. In relational databases,the data is accessed via queries. As these can be written in many ways, it is inevitable for them to be different in quality. At the same time, with queries which search for a specific value or combine data from multiple tables, it is recommendedto create indexes. An index is a data structure which provides a quicker access to rows from tables in a query. Query performances in cases, where indexes in databases aren’t created efficiently, last longer than actually needed. The analysis of optimal index creation and query writing requires a lot of prior knowledge. Since there are no tools available, which would automatize it for MySQL database, our own framework has been designed for this purpose. The database in our case is integrated into an internet server with the support of a programming language PHP for creating dynamic web content. The framework finds queries by checking the PHP source code, creates indexes and informs about potential improvement possibilities of a query structure. Its operation has been tested in two projects. One of them used a database recommended by MySQL as a testing database for learning. In both cases the framework served its purpose very well as it created indexes equivalent to an expert with years of experience in the field of databases. Such solution is therefore appropriate for beginners as well as for experienced users of databases. KEYWORDS: optimizing sql queries, positioning of indexes, relational databases, MySQL VSEBINA 1 UVOD..............................................................................................................................................................1 2 PODATKOVNE BAZE .................................................................................................................................3 2.1 PODATKOVNA BAZA ....................................................................................................................................3 2.1.1 SISTEM ZA UPRAVLJANJE S PODATKOVNO BAZO ................................................................................................. 4 2.1.2 PODATKOVNI MODEL .............................................................................................................................................. 5 2.1.3 JEZIK SQL ................................................................................................................................................................. 6 2.2 PODATKOVNA BAZA MYSQL .....................................................................................................................7 2.2.1 2.3 INDEKSIRANJE .......................................................................................................................................................... 8 OPTIMIZACIJE ........................................................................................................................................... 11 2.3.1 STAVEK SELECT.................................................................................................................................................. 11 2.3.2 STAVEK EXPLAIN ............................................................................................................................................... 14 2.3.3 STAVEK WHERE ................................................................................................................................................. 14 2.3.4 STAVEK UNION ................................................................................................................................................... 15 2.3.5 STAVEK JOIN ........................................................................................................................................................ 15 2.3.6 INDEKS POPRAVKI ................................................................................................................................................ 16 2.3.7 STAVEK ORDER BY ............................................................................................................................................ 17 2.3.8 STAVEK GROUP BY ............................................................................................................................................ 18 3 PHP .............................................................................................................................................................. 19 4 NALOGE OGRODJA.................................................................................................................................. 21 4.1 STAVEK SELECT ..................................................................................................................................... 22 4.2 STAVEK WHERE ..................................................................................................................................... 22 4.3 STAVEK ORDER BY ................................................................................................................................ 22 4.4 STAVEK GROUP BY ................................................................................................................................ 22 5 ARHITEKTURA OGRODJA .................................................................................................................... 23 5.1 OPIS POSTOPKA ....................................................................................................................................... 23 5.2 ISKANJE POIZVEDB ................................................................................................................................... 23 5.2.1 RAZRED SCANCODE ............................................................................................................................................. 24 5.2.2 RAZRED CRAWLER ............................................................................................................................................... 25 5.2.3 RAZRED FILEMANIPULATION ............................................................................................................................ 25 5.3 ANALIZA IN OPTIMIZACIJA POIZVEDB ..................................................................................................... 25 I 5.3.1 RAZRED ANALYZEQUERIES ................................................................................................................................. 25 5.3.2 RAZRED MYSQLPARSER ..................................................................................................................................... 25 5.3.3 RAZRED INDEXFILTER ......................................................................................................................................... 27 5.4 TESTIRANJE ..............................................................................................................................................27 5.4.1 RAZRED BENCHMARK .......................................................................................................................................... 28 5.4.2 RAZRED DATAGENERATOR ................................................................................................................................. 28 5.5 UNITTEST RAZREDI..................................................................................................................................28 5.6 POMOŽNI RAZREDI ...................................................................................................................................29 5.6.1 RAZRED RUN ......................................................................................................................................................... 29 5.6.2 RAZRED CONFIG .................................................................................................................................................... 29 5.6.3 MYSQL RAZREDI................................................................................................................................................... 30 6 REALIZACIJA OGRODJA .........................................................................................................................31 6.1 RAZRED RUN ............................................................................................................................................31 6.2 RAZRED CONFIG .......................................................................................................................................32 6.3 RAZRED FILEMANIPULATION .................................................................................................................33 6.4 RAZRED SCANCODE..................................................................................................................................33 6.5 RAZRED CRAWLER ...................................................................................................................................35 6.6 RAZRED ANALYZEQUERIES .....................................................................................................................36 6.7 RAZRED MYSQLPARSER .........................................................................................................................37 6.8 RAZRED INDEXFILTER .............................................................................................................................40 6.9 RAZRED BENCHMARK ..............................................................................................................................41 6.10 RAZRED DATAGENERATOR ..................................................................................................................42 7 UPORABA OGRODJA ..............................................................................................................................45 7.1 STRUKTURA DATOTEK .............................................................................................................................45 7.2 UKAZI ORODJA ..........................................................................................................................................46 7.2.1 UKAZ INFO .............................................................................................................................................................. 46 7.2.2 UKAZ COMPATIBILITYTEST ................................................................................................................................. 46 7.2.3 UKAZ SCANCODE ................................................................................................................................................... 46 7.2.4 UKAZ CRAWLER ..................................................................................................................................................... 46 7.2.5 UKAZ ANALYZEQUERIES ...................................................................................................................................... 46 7.2.6 UKAZ CLEANUP ...................................................................................................................................................... 46 7.2.7 UKAZ SETUPCONFIG ............................................................................................................................................. 47 8 TESTIRANJE OGRODJA ..........................................................................................................................49 II 8.1 METODOLOGIJA TESTIRANJA................................................................................................................... 49 8.1.1 ANDERSON-DARLING TEST ................................................................................................................................. 49 8.2 TEST PODATKOVNE BAZE SAKILA ........................................................................................................... 50 8.3 TEST PODATKOVNE BAZE 1A-VREME ..................................................................................................... 52 9 SKLEPNE UGOTOVITVE IN IDEJE ZA NADALJNE DELO .............................................................. 55 DODATEK A: NASTAVITVE OGRODJA ..................................................................................................... 57 1. MYSQL NASTAVITVE .................................................................................................................................. 57 2. DIREKTORIJSKE NASTAVITVE .................................................................................................................... 57 3. NASTAVITVE SPLETNEGA PAJKA ................................................................................................................ 57 4. TESTIRANJE ................................................................................................................................................. 57 5. GENERATOR PODATKOV ............................................................................................................................ 58 DODATEK B: IZPIS UKAZNIH LUPIN ........................................................................................................ 59 DODATEK C: SQL POIZVEDBE .................................................................................................................... 63 1. SQL POIZVEDBE PODATKOVNE BAZE SAKILA ........................................................................................... 63 2. PRIMERI SQL POIZVEDB PODATKOVNE BAZE 1A-VREME ....................................................................... 65 DODATEK D: REZULTATI TESTIRANJ ..................................................................................................... 67 1. PODATKOVNA BAZA SAKILA ...................................................................................................................... 67 2. PODATKOVNA BAZA 1A-VREME ................................................................................................................ 69 10 LITERATURA ......................................................................................................................................... 71 III IV SEZNAM SLIK Slika 1: Primer relacije..................................................................................................................................................... 5 Slika 2: Primer iskalnega dvojiškega drevesa. ....................................................................................................... 9 Slika 3: Neuravnoteženo dvojiško drevo............................................................................................................... 10 Slika 4: Stavek EXPLAIN s poizvedbo SELECT [4]. ............................................................................................ 14 Slika 5: Postopek analiziranja poizvedb ................................................................................................................ 23 Slika 6: Diagram poteka iskanja MySQL poizvedb. ........................................................................................... 24 Slika 7: Diagram poteka optimizacije poizvedbe. .............................................................................................. 26 Slika 8: Razredni diagram poenotenega jezika modeliranja (angl.: Unified Modeling Language, krat.: UML) MySQL razredov. ........................................................................................................................... 30 Slika 9: Razredni diagram UML Run razreda. ..................................................................................................... 32 Slika 10: Razredni diagram UML razreda Config. .............................................................................................. 32 Slika 11: Razredni diagram UML razreda FileManipulation. ........................................................................ 33 Slika 12: Razredni diagram UML razreda ScanCode. ....................................................................................... 34 Slika 13: Razredni diagram UML Crawler razreda............................................................................................ 35 Slika 14: Razredni diagram UML razreda AnaylzeQueries. ........................................................................... 36 Slika 15: Razredni diagram UML razreda MySQLParser. ............................................................................... 37 Slika 16: Razredni diagram UML razreda IndexFilter. .................................................................................... 40 Slika 17: Razredni diagram UML razreda Benchmark. ................................................................................... 41 Slika 18: Razredni diagram UML razreda DataGenerator.............................................................................. 42 Slika 19: Direktorijska struktura projekta. .......................................................................................................... 45 Slika 20: Model intetitet in povezav (angl.: Entity–relationship, krat.: ER) diagram podatkovne baze Sakila................................................................................................................................................................ 50 Slika 21: ER diagram podatkovne baze 1a-vreme............................................................................................. 52 SEZNAM TABEL Tabela 1: Tržni delež proizvajalcev podatkovnih baz v letu 2011, vir: Gartner (marec 2012)......... 4 Tabela 2: Časovna zahtevnost operacij [5]........................................................................................................... 21 Tabela 3: Rezultati testiranja podatkovne baze Sakila. .................................................................................. 51 Tabela 4: Rezultati testiranja podatkovne baze 1a-vreme. ........................................................................... 53 Tabela 5: Indeksi, postavljeni na podatkovni bazi Sakila. .............................................................................. 67 Tabela 6: Časi trajanj primerjalnih testov na podatkovni bazi Sakila. ...................................................... 68 Tabela 7: Časi trajanj primerjalnih testov na podatkovni bazi 1a-vreme. .............................................. 69 Tabela 8: Indeksi, postavljeni na podatkovni bazi 1a-vreme. ...................................................................... 70 V SEZNAM SINTAKS Sintaksa 1: Stavek SELECT [22]................................................................................................................................. 12 Sintaksa 2: Izraz expr [23]. .......................................................................................................................................... 13 Sintaksa 3: Stavek EXPLAIN [19]. ............................................................................................................................. 14 Sintaksa 4: Stavek UNION [24]. ................................................................................................................................. 15 Sintaksa 5: Stavek JOIN [25]. ...................................................................................................................................... 16 Sintaksa 6: Sintaksa uporabe indeks popravkov [26]. ..................................................................................... 17 Sintaksa 7: Stavek ORDER BY [21]. .......................................................................................................................... 17 Sintaksa 8: Stavek GROUP BY [21]. .......................................................................................................................... 18 SEZNAM UKAZNIH LUPIN Ukazna lupina 1: Zagon ogrodja. ............................................................................................................................... 59 Ukazna lupina 2: Zagon ogrodja z opcijo compatibilityTest.......................................................................... 60 Ukazna lupina 3: Zagon ogrodja z opcijo scanCode. ......................................................................................... 60 Ukazna lupina 4: Zagon ogrodja z opcijo crawler. ............................................................................................. 60 Ukazna lupina 5: Izvajanje ukaza analyzeQueries. ............................................................................................ 61 Ukazna lupina 6: Izvajanje ukaza analyzeQueries na projektu, kjer ni predlaganih izboljšav........ 62 Ukazna lupina 7: Zagon ogrodja z opcijo cleanup.............................................................................................. 62 Ukazna lupina 8: Zagon ogrodja z opcijo setupConfig. .................................................................................... 62 SEZNAM UPORABLJENIH KRATIC IN SIMBOLOV DDL (angl.: Data Definition Language) DML (angl.: Data Manipulation Language) ER (angl.: Entity–relationship) model intetitet in povezav LAMP Linux, Apache, MySQL in PHP SQL (angl.: Structured Query Language) strukturiran povpraševalni jezik UML (angl.: Unified Modeling Language) poenoten jezik modeliranja URL (angl.: Uniform Resource Locator) spletni naslov WAMP Windows, Apache, MySQL in PHP VI 1 UVOD Današnji svet je poln informacij. Te je potrebno nekam shraniti, da lahko kasneje do njih dostopamo. Ta problem v veliki meri rešujejo podatkovne baze. Glede na to, da lahko poizvedbe (angl.: query), ki nam vrnejo podatke iz podatkovne baze,napišemo na več načinov, je neizogibno,da se le–te med seboj po kakovosti razlikujejo. Hkrati je priporočljivo pri poizvedbah, ki iščejo določeno vrednost ali združujejo podatke iz večih tabel, postaviti indekse.Indeksi so podatkovne strukture, ki omogočajo hitroizvedbo tovrstnih poizvedb.Pri srednjih in večjih projektih imamo veliko uporabnikov in posledično veliko poizvedb na sekundo.S tem se pojavi vprašanje, kakšna je idealna postavitev indeksov ter ali so naše poizvedbe optimalne. To diplomsko delo se posveča MySQL podatkovnim bazam in rešuje problem optimalnepostavitve indeksov, poleg tega pa se tudi dotakne predlogov optimalne zasnove poizvedb.Podatkovno bazo ponavadi uporabljamo v navezi z enim od programskih jezikov. MySQL se pogosto uporablja v povezavi spopularnim programskim jezikom PHP za razvoj dinamičnih spletnih vsebin.Drugi proizvajalci podatkovnih baz za njihponujajo podobna orodjaza svoje podatkovne baze, vendar je potrebno njihove poizvedbe v orodje vnašati ročno.Naše ogrodje to stori samodejno, s pregledom PHP izvorne kode projekta. Poleg tega ima dodatno prednost, da se s časom uči, ali je glede na število vpisov v bazo postavitev indeksa smotrna. Diplomsko delo je sestavljeno iz treh delov. Prvi zajema drugo poglavje, kjerbomo spoznali podatkovne baze in pripadajočesisteme za upravljanje s podatkovnimi bazami.Pojasnili bomo osnovne pojme, ki se pojavljajo v podatkovnih bazah. Nato si bomo ogledalipodatkovno bazoMySQLteropisaliekstrakcijo podatkov iz podatkovne baze.Pod prvi del spada še tretje poglavje, kjer bomo opisali programski jezik PHP in razloge za njegovo uporabo. Drugi del diplomske naloge zajema naslednja tri poglavja, ki se posvečajo orisu ogrodja, ki smo ga razvili. V četrtem poglavju si bomo pogledali naloge ogrodja. Sledi peto poglavje, kjer bomo opisali arhitekturo ogrodja in njegovo delovanje. Implementacijski detajli so zbrani v šestem poglavju. V zadnjem delubomo predstavili uporabo ogrodja in rezultate. V petem poglavju bomo predstavili uporabo ogrodja. Sledi šesto poglavje,kjer bomo na dveh različnih projektih s pripadajočima podatkovnima bazama naredili primerjalne teste(angl.: benchmark test)s stanjem pred in po uporabi ogrodjater ovrednotili rezultate. Sklepne ugotovitve diplomskega dela 1 predstavlja sedmo poglavje, kjer bomo povzeli dosežke, opisali probleme, s katerimi smo se srečali tekom razvoja,ter omenili smernice za nadaljnje delo. 2 2 PODATKOVNE BAZE Poglavje je namenjenopregledu podatkovnih baz s pripadajočimi sistemi za njihovo upravljanje in problematike, ki se ji posveča to diplomsko delo. V prvem podpoglavjubomo spoznali,kaj podatkovne baze sploh so, kaj nam ponujajo in zakaj so tako uporabne, da jih srečujemona vsakem koraku. Naslednje podpoglavje je namenjeno pregledupodatkovne bazeMySQL. Zadnje podpoglavjeje namenjeno problemu ekstrakcije podatkov iz podatkovne baze, kjer si bomo ogledali možnosti za pohitritev izvajanja poizvedb. 2.1 Podatkovna baza Podatkovne bazeso organizirane zbirke podatkov. Pojavile so se zaradi vse večje potrebe po shranjevanju podatkov ter hitrem dostopu do njih. Podatki ponavadi modelirajo stanje iz realnega sveta (primer: zasedenost sob v hotelu), na način, ki nam omogoča premišljeno odločanje o prihodnosti (primer:rezervacija proste sobe v hotelu). Besedna zveza »podatkovna baza« se nanaša na zbirko podatkov in njihove pripadajoče podatkovne strukture, ne pa tudi na sisteme za upravljanje z podatkovnimi bazami. Sliednji so programski paketi, ki nam omogočajo učinkovito, uporabnikom prijazno in večuporabniško okolje, namenjeno shranjevanju, vzdrževanju in dostopanju do medsebojno povezanih podatkov[11]. Prvi začetki podatkovnih baz in njihovih sistemov upravljanja segajo v obdobje, ko se je večina informacij shranjevala na magnetne trakove. V 60-ih letih je Charles Bachman iz General Electric razvil prvo podatkovno bazo za splošno uporabo, za kar je prejel Turingovo nagrado. V začetku 70-ih let je Edgar Corr predlagal prvi relacijski podatkovni model, ki je v naslednjih dveh desetletjih postal standard za upravljanje s podatki v organizacijskih sistemih. V istem desetletju se je za podatkovne baze razvila močna teoretična podlaga, s čimer so podatkovne baze postaleakademsko področje. V 80-ih letih se je razvil strukturiran povpraševalni jezik(angl.: Structured Query Language, krat.: SQL)(IMB-ov projekt System R), ki je bil v poznih letih istega desetletja tudi standardiziran. Standard se imenuje SQL-92. V naslednjem desetletju je veliko proizvajalcev podatkovnih baz (IBM – DB2, Oracle 8, Informix UDS) razširilo svoje sisteme s podporo kompleksnejšim poizvedbam in novim podatkovnim tipom, kot so slike inbesedilo. Naslednja stopnja je bila vstop podatkovnih baz v dobo interneta, kjer so nadomestili prvo generacijo spletnih mest, ki je shranjevala podatke v datotekah operacijskega sistema[1, 2]. 3 2.1.1 Sistem za upravljanje s podatkovno bazo Naloge in zmožnosti sistemov za upravljanje s podatkovno bazo[11, 12]: definiranje sheme podatkovne baze in shranjevanje te sheme na zunanjem pomnilniku, shranjevanjevsebine v podatkovno bazo, poizvedbe po vsebini v podatkovni bazi, spreminjanje vsebine vpodatkovni bazi, omogoča kreiranje, spreminjanje ter brisanje tabel in podatkovnih baz z modulom, imenovanimDDL (angl.: Data Definition Language), skrbi za vzdrževanje podatkovne baze z DML (angl.: Data Manipulation Language)modulom, ki omogoča črpanje, brisanje in spreminjanje podatkov v podatkovni bazi, ščiti podatke, zagotavlja integriteto podatkov, izvaja transakcije. Med velike proizvajalce sistemov podatkovnih baz(v nadaljevanju podatkovne baze) štejemo Oracle, IBM in Microsoft (tabela1).MySQLse razvija pod okriljem podjetja Oracle,kije pod njegovo okrilje prišel z nakupom podjetja Sun Microsystems leta 2010[13]. Proizvajalec Prodaja 2011 (v milijonih $) Tržni delež v letu 2011 (%) 11787 48,8 IBM 4870 20,2 Microsoft 4098 17,0 SAP/Sybase 1101 4,6 882 3,7 1389 5,8 Oracle Teradata Ostali Tabela 1: Tržni delež proizvajalcevpodatkovnih baz v letu 2011, vir: Gartner (marec 2012). 4 2.1.2 Podatkovni model Podatkovni model je povezana zbirka konceptov, namenjenih opisovanju in manipulaciji s podatki.Obstaja več vrst podatkovnih modelov. Hierarhični in mrežni podatkovni model že izginjata iz uporabe.Danes se uporabljajo entitetno-relacijski, objektno-relacijski, objektni in relacijskipodatkovni model. Slednji je daleč najbolj v uporabi in ga podpirajo vsi večji proizvajalci podatkovnih baz[14]. Relacijski podatkovni model odlikujejo predvsem naslednje lastnosti [1]: formalno je definiran in osnovan na matematičnih strukturah – relacijah, ne vsebuje elementov fizičnega shranjevanja, s čimer je zagotovljena fizična podatkovna neodvisnost, relacije so predstavljive s tabelami, ki so človeku dobro razumljive. Relacijsko podatkovno bazo uporabnik vidi kot množico tabel (slika 1). Tabela je sestavljena iz dveh delov– čelne vrstice in podatkovnih vrstic. Atributi Oddelek oddelekID ulica mesto postna_stevilka OD1 Tržaška ulica 55 Ljubljana 1000 OD4 Savinškova ulica 32 Novo mesto 8000 OD2 Gospejna ulica 94 Maribor 2000 OD3 Kopališka ulica 34 Škofja Loka 4220 Primarni ključ Tuji ključ Osebje osebjeID ime priimek spol rojstvo oddelekID OS1 Maja Hribar Ž 12.4.1967 ID1 OS2 Borut Kovačevič M 10.9.1979 ID3 OS3 Luka Cesar M 16.12.1983 ID3 OS4 Sara Lušina Ž 21.2.1965 ID4 OS5 Ivan Novak M 3.6.1959 ID1 OS6 Janez Jelenc M 10.9.1960 ID2 Slika 1: Primer relacije. 5 Osnovna koncepta relacijskega podatkovnega modela sta domena in relacija. Relacija je definirana nad množico domen, ki predstavljajo zalogo vrednosti, ki jih lahko zavzame atribut (podatkovni tipi: niz, število, decimalno število, datum, …) in njegove omejitve (pozitivna števila, točno 10 znakov, unikatni podatki, …).Ime stolpca imenujemo atribut. V vsak stolpec lahko shranjujemo le podatke, ki ustrezajo definiranim zalogam vrednosti in omejitvam. Čelna vrstica je več skupaj združenih atributov, ki definirajo relacijsko shemo. Relacijske podatkovne baze povežejo več tabel v eno relacijo. Osnova za povezovanje tabel so primarni in tuji kjuč.Primarni ključ (angl.: Primary Key) tabele je stolpec ali kombinacija stolpcev znotraj relacije, ki enolično določa vrstico. Je poseben primer enoličnih ključev (angl.: Unique Key), s to razliko, da primarni ključ ne sme vsebovati vrednostiNULL. Vrednost NULL je poseben indikator uporabljen v jeziku SQL, ki pove, da podatek v polje ni vpisan. Primer primarnega ključa je EMŠO. Tuji ključ je stolpec ali kombinacija stolpcev znotraj relacije, ki se ujema s ključem druge relacije (lahko tudi iste). 2.1.3 Jezik SQL Jezik SQL je osnovni gradnik modernih podatkovnih baz. Med vsemi jeziki za delo s podatkovnimi bazami jenajbolj razširjen [2, 13]. Določen je sstandardom ANSI/ISO SQL. Standard SQL se je začel razvijati leta 1986, danes pa obstaja več različic. Standard SQL-92 je bil izdan v letu 1992, SQL:1999 v letu 1999 itd. Uporablja se kot DML in DDLjezik. Čeprav obstajanatančno definiran SQL standard, jejezik SQL vseeno implementiran na različne načine. Oracle imalastnistandard PL/SQL, Microsoft SQL Server pa Transact-SQL.Ne glede na to sta obe verziji zgrajeni na standardu SQL.MySQL verzija 5.* v celoti podpira standard ANSI/ISO SQL [16]. V nadaljevanjusoprimeri osnovnih stavkov, stavke pomembne za optimizacijo pa bomo razčlenili v poglavju 2.3. Osnovni stavki za delo s tabelami: CREATE DATABASE: ustvari novo podatkovno bazo, CREATE TABLE: ustvari novo tabelo v podatkovni bazi, ALTER TABLE: spremeni tabelo v podatkovni bazi, DROP TABLE: odstrani tabelo iz podatkovne baze, INSERT: vnese novo vrstico v tabelo, SELECT: vrne vrstice iz podatkovne baze, UPDATE: posodobi vrstice v podatkovni bazi, DELETE: zbriše vrstice iz podatkovne baze. 6 2.2 Podatkovna baza MySQL Začetki baze MySQL segajo v leto 1979, ko je Michael »Monty« Widenius za švedsko podjetje TcX ustvarilorodje UNIREG za podatkovne baze. Nato je leta 1994 TcX začel iskati podatkovno bazo s podporo zajezik SQL za uporabo pri razvijanju spletnih aplikacijah. Testirali so nekaj komercialnih ponudnikov podatkovnih baz, vendar so ugotovili, da so vsi prepočasni za njihove velike tabele. Ogledali so si mSQL, vendar tani imelzahtevanih funkcionalnosti, kijih je TcX potreboval, zato so se znova obrnili na Michaela Wideniusa, ki je razvil današnji MySQL. Leta 1996 je bil izdan MySQL 3.11.1, ki je bil dostopen v obliki binarne datoteke za operacijska sistema Linux in Solaris. Danes je na voljo v obliki binarnih datotek in izvorne kode za praktično vse operacijske sisteme. Ustanovljeno je bilo podjetje MySQL AB, ki je distribuiralo MySQL pod kombinacijo odprtokodnein komercialne licence; slednja vklučuje tehnično podporo. Leta 2008 je podjetje Sun Microsistems kupilo MySQL AB, slednjega pa je leta 2010 kupil Oracle[3]. Prednosti baze MySQL [3]: je ena najhitrejših podatkovnih baz, katerouporabljajo podjetja Associated Press, Cox Communications, Google, Lufthansa, MIT Lincoln Labs, NASA, Sabre Holdings, Yahoo in drugi [17], veliko lažje vzdrževanje in upravljanje kot pri večjih podatkovnih bazah, celostnapodpora jeziku SQL[15], verzija za skupnost (MySQL Community Edition) je brezplačna, distribucijske datoteke so zelo majhne v primerjavi z drugimi podatkovnimi bazami, je na voljo na vseh komercialno dostopnih operacijskih sistemih (MAC OS X, Windows, HP-UX, Unix, Linux), ima polno podporo za povezljivost preko omrežja, prav tako je možen dostop preko interneta, kjer so povezave enkriptirane z uporabo protokolaSSL, je odprtokodni projekt. Do nedavnega je bilo na račun MySQL tudi nekaj kritik, sajni podpiral transakcij in tujih ključev. Vendar se je MySQL v zadnjih letih močno razvijal in dobil obe omenjeni funkcionalnosti, poleg tega pa tudi poglede (angl.: views), bazne procedure (angl.: stored procedure) in prožilnike (angl.: triggers). S tem se je približal večjim proizvajalcem podatkovnih baz. Posledica tega je, da danes vse več podjetij, ki so v preteklosti uporabljala rešitvevodilnih proizvajalcihpodatkovnih baz,danes uporablja MySQL [3]. 7 2.2.1 Indeksiranje Indeks je podatkovna struktura, ki nam omogoča, da v poizvedbi poiščemo vrstice iz tabele mnogo hitreje kot sicer. Če ne uporabimo indeksa, mora MySQL preiskati celotno tabelo, pri čemer začne pri prvi vrstici in preišče celotnozbirko podatkov, dokler ne najde ustreznih zadetkov. Časovna zahtevnost iskanja v tem primeru narašča linearno s številom vrstic O(n), zato je iskanje hitro, dokler vrstic v tabeli ni preveč. Ko velikost tabele narašča, pa ustrezno postavljen indeks pospeši iskanje, saj je v tem primeru časovna zahtevnost iskanja O(log n). Indeks lahko postavimo čez enegaali več stolpcev[4, 20]. Slabost indeksov je, da zasedajo dodatni prostor v računalniškem pomnilniku in da lahko upočasnijo vnose podatkov v tabelo, saj je potrebno pri vsakem vpisu ponovno uravnotežiti drevo, kar ustreza časovni zahtevnosti O(log n) [4, 20]. Večina MySQL indeksov (primarni ključ, unikaten ključ, indeks, iskanje po polnem besedilu (angl.: full-text)) uporablja kot podatkovno strukturo uravnoteženo iskalno dvojiško drevo [ 21]. To je podatkovna struktura, kjer sta v vsakem vozlišču (elementu oz. očetu)dve povezavi na naslednji vozlišči (levi in desni sin), ki sta enake strukture. Vozlišče, kjer začnemo drevesno strukturo, je koren drevesa, vozlišča brez sinov pa so listi drevesa. Vrednosti elementov v levem poddrevesu so manjše od vrednosti korena, vrednosti elementov v desnem poddrevesu pa so večje od vrednosti korena. V iskalnem dvojiškem drevesu ni podvojenih elementov.Dvojiško drevo je urejeno, če za vsako vozlišče velja, da je vrednost levega sina manjša, vrednost desnega sina pa večja od njegove vrednosti [5]. 8 Predpostavimo, da imamo naslednje podatke: 8, 10, 3, 6, 14, 7, 4, 13, 1. Postopek izgradnje urejenega dvojiškega drevesa je naslednji: 1. vzamemo prvo številko, to je 8, in jo vstavimo v prazno drevo; ta številka postane koren drevesa; 2. naslednja številka je 10;primerjamo jo s korenom drevesa in ker je 10 > 8, jo vstavimo v desno poddrevo; 3. naslednja je 3; primerjamo jo s številko 8 in jo vstavimo v levo poddrevo; 4. naslednja je 6; ker je 6 < 8, jo vstavimo v levo poddrevo, vendar ne smemo pozabiti na številko 3; ker je 3 < 6, jo vstavimo v desno poddrevo številke 3; 5. naslednja je 14; ker je 14 > 8, gremo v desno in ker je 13 > 10, jo vstavimo v desno poddrevo številke 10; 6. naslednja je 7; ker je 7 < 8, gremo v levo; ker je 7 > 3, gremo v desno in ker je 7 > 6, jo vstavimo v desno poddrevo številke 6; 7. naslednja je 4; ker je 4 < 8, gremo v levo; ker je 4 > 3, gremo v desno in ker je 3 < 6, jo vstavimo v levo poddrevo številke 6; 8. naslednja je 13; ker je 13 > 8, gremo v desno; ker je 13 > 10, gremo v levo in ker je 13 < 14, jo vstavimo v levo poddrevo številke 14; 9. zadnja številka je 1; ker je 1 < 8, gremo v levo in ker je 1 < 3, jo vstavimo v levo poddrevo številke 3. Po opravljenem postopku dobimo dvojiško drevo narisano na sliki 2. Slika 2: Primer iskalnega dvojiškega drevesa. V primeru, da bi želeli iz podatkov poiskati številko 7, bi bil postopek sledeč: 1. začnemo pri korenu drevesa in primerjamo številko 7 s številko 8, 2. 7 < 8, zato gremo v levo poddrevo, 3. 7 > 3, zato gremo v desno poddrevo, 4. 7 > 6, zato gremo v desno poddrevo, 5. ker je 7 = 7, smo našli iskani element. 9 Da smo našli številko 7, smo potrebovali 4 operacije (primerjave). V splošnem potrebujemo za iskanje elementa v urejenem dvojiškem drevu toliko operacij, kot imamo nivojev drevesa. Le–te izračunamo z enačbolog2n, kjer je n število elementov v polnem drevesu, rezultat pa nato pretvorimo v celo število. To seveda velja samo takrat, ko je drevo uravnoteženo. Če zgradimo neuravnoteženo dvojiško drevo s prejšnjimi podatki, dobimo v najslabšem primeru dvojiško drevo na sliki 3. V tem primeru je hitrost iskanja linearna, enako kot pri linearnem seznamu [5]. Slika 3: Neuravnoteženo dvojiško drevo. Če poiščemo številko 7 v tem drevesu, imamo postopeksledeč: 1. začnemo pri korenu drevesa in primerjamo številko 7 s številko 1, 2. 7 > 1, zato gremo v desno poddrevo, 3. 7 > 3, zato gremo v desno poddrevo, 4. 7 >4, zato gremo v desno poddrevo, 5. 7 > 6, zato gremo v desno poddrevo, 6. ker je 7 = 7, smo našli iskani element. Da smo našli številko 7, smo potrebovali 5 operacij (primerjav).To jeena operacija več kot pri uravnoteženem drevesu. V najslabšem primeru, ko bi iskali število 14, pa bi potrebovali celo 9 operacij.V primeru neuravnoteženega dvojiškega drevesa je torej časovna zahtevnost iskanja O(n). Iz tega sledi, da je uravnoteženje nujno, da je iskanje optimalno. Za postopek uravnoteženja velja, daje časovna zahtevnost O(log2n)samo, če je pred vnosom novega podatka drevo že bilo uravnoteženo, zato je to nujno delati sproti ob vsakem vnosu. 10 Če bi številko 7 iskali v (linearnem) seznamu, bi potrebovali 6 operacij. V splošnem v seznamu potrebujemo toliko operacij, kolikor je elementov. Vidimo, da je iskanje z indeksi opazno hitrejše. Slabost je ta, da tudi za vnašanje novega elementa v drevo potrebujemo v najslabšem primeru log2n operacij, medtem ko za navaden seznam potrebujemo samo eno operacijo. Poleg tega dvojiško drevo zaseda dodaten prostor v pomnilniku.Postavitev indeksov je torej kompromis med hitrejšim iskanjem podatkov in počasnejšimi vnosi ter večjo porabo pomnilnika. 2.3 Optimizacije Ker za MySQL niorodja, ki bi predlagalo postavitev indeksov glede na dane poizvedbe, smo se odločili, da ga izdelamo sami. Trenutno se indekse tipično postavlja glede na pretekle izkušnje in ročno,kjer si lahko delno pomagamo s stavkomEXPLAIN.Drugi proizvajalci podatkovnih baz ponujajo podobna orodja za svoje podatkovne baze (primer je Index Tuning Wizard v SQL Query Analyzer [18]), vendar je treba poizvedbe v orodje vnašati ročno. Naše ogrodje stori to samodejno s pregledom PHP izvorne kode.Hkrati se s časom uči, kakšno je številostavkovSELECT in koliko je posodobitvenih stavkov. Na podlagi teh podatkov in števila vrstic v tabelah nam predlaga odstranitev indeksov, če to predstavlja optimalno rešitev. V naslednjih podpoglavjih bomo podrobneje razčlenili standardne poizvedbe v MySQL in pogledali možnosti za njihove optimizacije. 2.3.1 Stavek SELECT S stavkom SELECT pridobimo podatke iz ene ali več tabel oziroma pogledov. V večini aplikacij je SELECT najbolj uporabljen stavek. Vključuje lahko stavek JOIN in podpoizvedbe (angl.: subquery). V sintaksi 1 izraz select_expr označuje, katere vrstice iz tabelenaj poizvedba vrne. Opcija table_refences je razčlenjena vpoglavju 2.3.5., opcija expr, ki se pojavlja v sintaksi 2 in vseh naslednjih definicijah sintaks, je podrobno razčlenjena v sintaksi 2. 11 SELECT [ALL | DISTINCT | DISTINCTROW ] [HIGH_PRIORITY] [STRAIGHT_JOIN] [SQL_SMALL_RESULT] [SQL_BIG_RESULT] [SQL_BUFFER_RESULT] [SQL_CACHE | SQL_NO_CACHE] [SQL_CALC_FOUND_ROWS] select_expr [, select_expr ...] [FROM table_references [WHERE where_condition] [GROUP BY {col_name | expr | position} [ASC | DESC], ... [WITH ROLLUP]] [HAVING where_condition] [ORDER BY {col_name | expr | position} [ASC | DESC], ...] [LIMIT {[offset,] row_count | row_count OFFSET offset}] [PROCEDURE procedure_name(argument_list)] [INTO OUTFILE 'file_name' export_options | INTO DUMPFILE 'file_name' | INTO var_name [, var_name]] [FOR UPDATE | LOCK IN SHARE MODE]] Sintaksa 1: Stavek SELECT [22]. Stavek SELECT lahko vsebuje več opcijskih stavkov, od katerih so za naše ogrodje najbolj pomembni stavki WHERE, GROUP BY in ORDER BY. Te bomo v naslednjih poglavjih podrobno razčlenili. 12 expr: expr OR expr | expr || expr | expr XOR expr | expr AND expr | expr&&expr | NOT expr | ! expr | boolean_primary IS [NOT] {TRUE | FALSE | UNKNOWN} | boolean_primary boolean_primary: boolean_primary IS [NOT] NULL | boolean_primary<=>predicate | boolean_primarycomparison_operatorpredicate | boolean_primarycomparison_operator {ALL | ANY} (subquery) | predicate comparison_operator: = | >= | > | <= | < | <> | != predicate: bit_expr [NOT] IN (subquery) | bit_expr [NOT] IN (expr [, expr] ...) | bit_expr [NOT] BETWEEN bit_expr AND predicate | bit_expr SOUNDS LIKE bit_expr | bit_expr [NOT] LIKE simple_expr [ESCAPE simple_expr] | bit_expr [NOT] REGEXP bit_expr | bit_expr bit_expr: bit_expr | bit_expr | bit_expr&bit_expr | bit_expr<<bit_expr | bit_expr>>bit_expr | bit_expr + bit_expr | bit_expr - bit_expr | bit_expr * bit_expr | bit_expr / bit_expr | bit_expr DIV bit_expr | bit_expr MOD bit_expr | bit_expr % bit_expr | bit_expr ^ bit_expr | bit_expr + interval_expr | bit_expr - interval_expr | simple_expr simple_expr: literal | identifier | function_call | simple_expr COLLATE collation_name | param_marker | variable | simple_expr || simple_expr | + simple_expr | - simple_expr | ~ simple_expr | ! simple_expr | BINARY simple_expr | (expr [, expr] ...) | ROW (expr, expr [, expr] ...) | (subquery) | EXISTS (subquery) | {identifierexpr} | match_expr | case_expr| interval_expr Sintaksa 2:Izraz expr [23]. 13 2.3.2 Stavek EXPLAIN {EXPLAIN | DESCRIBE | DESC} tbl_name [col_name | wild] {EXPLAIN | DESCRIBE | DESC} [EXTENDED] SELECT select_options Sintaksa 3: Stavek EXPLAIN [19]. Ena od metod optimizacij, ki jihuporabljamo za MySQL poizvedbe, jestavek EXPLAIN. Uporabljamo ga bodisi za povratno informacijo, kako MySQL izvaja poizvedbo,bodisi kot sinonim stavku DESCRIBE. Če pred stavkom SELECT uporabimo ključno besedoEXPLAIN, MySQL prikaže informacije o tem, kako so tabele združene in katere indekse se uporablja (primer kaže slika 4).Ti dve informaciji nam pomagata pri oceni postavitve indeksov, vendar samo, česo indeksi že predhodno postavljeni[4]. Slika 4: Stavek EXPLAIN s poizvedboSELECT [4]. 2.3.3 Stavek WHERE Stavek WHERE definira pogoje, ki jih morajo vrstice izpolnjevati, da jih bo poizvedba vrnila. Vopcijiwhere_condition, definiraniv sintaksi 1, uporabimo MySQL funkcije in operatorje, definirane v sintaksi 2. Kostavka WHERE ne uporabimo, poizvedba vrne vse vrstice tabele. V relacijski algebri jestavek WHEREekvivalent selekciji. Da MySQL uporabi indeks, mora stavekWHERE ustrezati naslednjim zahtevam [21]: dovoljeni operatorji so =, >, >=, <, <=in BETWEEN, pogojno lahko uporabimo tudi operator LIKE, vendar samo v primeru, da se maskirni znakpojavi drugje kot na začetku konstante (primer: LIKE '%primer' ne bo uporabil indeksa, LIKE 'primer%' pa bo uporabil indeks), logični operator med osnovnimi delistavka WHERE mora biti operator AND, paziti moramo tudi na vrstni red polj v indeksu; indeks i_2(A, B, C) ni enak indeksu i_1(A, C, B), ko združujemo indekse iz različnih poizvedb. 14 Primeri SQL stavkov, kjer MySQL uporabi indekse: SELECT * FROM tbl_name WHERE col1=val1; SELECT * FROM tbl_name WHERE col1=val1 AND col2=val2; SELECT * FROM tbl_name WHERE key_col LIKE 'Patrick%'; SELECT * FROM tbl_name WHERE key_col LIKE 'Pat%_ck%'; Primeri SQL stavkov, kjer MySQL ne uporabi indeksov: SELECT * FROM tbl_name WHERE key_col LIKE '%Patrick%'; SELECT * FROM tbl_name WHERE key_col LIKE other_col; SELECT * FROM tbl_name WHERE index_part1=1 OR index_part2=10; 2.3.4 Stavek UNION Stavek UNION uporabljamo, da združimo rezultate več SELECT stavkov v en sklop rezultatov. V relacijski algebri je stavku UNION ekvivalentna operacija unija. SELECT ... UNION [ALL | DISTINCT] SELECT ... [UNION [ALL | DISTINCT] SELECT ...] Sintaksa 4: Stavek UNION [24]. Primer poizvedbe UNION: (SELECT a FROM t1 WHERE a=10 AND B=1 ORDER BY a LIMIT 10) UNION (SELECT a FROM t2 WHERE a=11 AND B=2 ORDER BY a LIMIT 10); 2.3.5 Stavek JOIN Stavek JOIN združi vrstice iz dveh ali večtabel v en sklop vrstic. Opcijski ukazindex_hint je razčlenjen v naslednjem poglavju.MySQL uporabi indeks na stolpcih,ki so uporabljeni v opcijijoin_condition.Vrstice lahko združimo tudi sstavkom WHERE. Ta možnost je prikazana v primerih. 15 table_references: table_reference [, table_reference] ... table_reference: table_factor | join_table table_factor: tbl_name [[AS] alias] [index_hint] | table_subquery [AS] alias | ( table_references ) | { OJ table_reference LEFT OUTER JOIN table_reference ON conditional_expr } join_table: table_reference [INNER | CROSS] JOIN table_factor [join_condition] | table_reference STRAIGHT_JOIN table_factor | table_reference STRAIGHT_JOIN table_factor ON conditional_expr | table_reference {LEFT|RIGHT} [OUTER] JOIN table_referencejoin_condition | table_reference NATURAL [{LEFT|RIGHT} [OUTER]] JOIN table_factor join_condition: ON conditional_expr | USING (column_list) Sintaksa 5: Stavek JOIN [25]. Primeri JOIN poizvedb, ki ustrezajo sintaksi 5: SELECT A.*, B.* FROM tbl_name AS A, tbl_name AS B WHERE A.col1 = B.col1 SELECT t1.name, t2.salary FROM employee AS t1 INNER JOIN info AS t2 ON t1.name = t2.name; SELECT t1.name, t2.salary FROM employee t1 INNER JOIN info t2 ON t1.name = t2.name; SELECT * FROM (SELECT 1, 2, 3) AS t1; SELECT t1.name, t2.salary FROM employee AS t1 LEFT JOIN b USING (c1,c2,c3) SELECT left_tbl.* FROM { OJ left_tbl LEFT OUTER JOIN right_tbl ON left_tbl.id = right_tbl.id } WHERE right_tbl.id IS NULL; 2.3.6 Indekspopravki Če v poizvedbi uporabimo ukaza USE INDEX aliFORCE INDEX, MySQLpri dani poizvedbi uporabi enega od naštetih indeksov v opciji index_list. Z ukazom IGNORE INDEX MySQL določenega indeksa ne uporabi. Poleg omenjenih možnosti je na voljo še ključna beseda FOR, ki ji sledijo JOIN, ORDER BY ali GROUP BY. 16 tbl_name [[AS] alias] [index_hint_list] index_hint_list: index_hint [, index_hint] ... index_hint: USE {INDEX|KEY} [FOR {JOIN|ORDER BY|GROUP BY}] ([index_list]) | IGNORE {INDEX|KEY} [FOR {JOIN|ORDER BY|GROUP BY}] (index_list) | FORCE {INDEX|KEY} [FOR {JOIN|ORDER BY|GROUP BY}] (index_list) index_list: index_name [, index_name] ... Sintaksa 6: Sintaksa uporabe indekspopravkov [26]. Primeri SQL poizvedb, ki ustrezajo sintaksi 6: SELECT * FROM table1 USE INDEX (col1_index, col2_index) WHERE col1=1 AND col2=2 AND col3=3; SELECT * FROM table1 IGNORE INDEX (col3_index) WHERE col1=1 AND col2=2 AND col3=3; SELECT * FROM t1 USE INDEX (i1) IGNORE INDEX FOR ORDER BY (i2) ORDER BY a; 2.3.7 Stavek ORDER BY Stavek ORDER BY uporabljamo za sortiranje vrstic. Sortiramo jih na dva načina. Če v poizvedbi poleg stavka ORDER BY uporabimo ključno besedo ASC, bodo vrstice sortirane od najmanjše proti največji vrednosti in obratno v primeru uporabe ključne besede DESC. Da lahko MySQL uporabi indeks, mora stavek ustrezati naslednjim zahtevam [27]: vsi stolpci imajo enako vrsto sortiranja(ASC ali DESC), uporablja lahko samo imena stolpcev in ključni besedi ASC ali DESC, ne pa tudi izrazov in funkcij, sestavljen je samo iz stolpcev iste tabele. [ORDER BY {col_name | expr | position} [ASC | DESC], ...] Sintaksa 7: Stavek ORDER BY [21]. Primeri SQL stavkov, kjer MySQL uporabi indekse: SELECT * FROM t1 ORDER BY key_part1, key_part2, ...; SELECT * FROM t1 WHERE key_part1 = 1 ORDER BY key_part2; SELECT * FROM t1 ORDER BY key_part1 DESC, key_part2 DESC; SELECT * FROM t1 WHERE key_part1=1 ORDER BY key_part1 DESC, key_part2 DESC; 17 Primeri SQL stavkov, kjer MySQL ne uporabi indeksov: SELECT * FROM t1 ORDER BY key1, key2; SELECT * FROM t1 ORDER BY key_part1 DESC, key_part2 ASC; SELECT * FROM t1 ORDER BY ABS(key); 2.3.8 Stavek GROUP BY Stavek GROUP BY v povezavi z agregatnimi funkcijami (angl.: aggregate functions) uporabljamo, da združimo vrstice. Da lahko MySQL uporabi indeks, morastavek ustrezati naslednjima zahtevama [28]: vstavku SELECT sta ediniuporabljeni agregatni funkciji MIN in MAX, paziti moramo tudi na vrstni red polj v indeksu;indeks i_2(A, B, C) ni enak indeksu i_1(A, C, B), ko združujemo indekse iz različnih poizvedb. [GROUP BY {col_name | expr | position} [ASC | DESC], ... [WITH ROLLUP]] Sintaksa 8: Stavek GROUP BY [21]. Ob predpostavki, da imamo postavljena dva indeksai_1(c1, c2, c3) in i_2(c1, c2, c3, c4),ju MySQL uporabi v naslednjih primerih: SELECT c1, c2 FROM t1 GROUP BY c1, c2; SELECT c1, MIN(c2) FROM t1 GROUP BY c1; SELECT c1, c2 FROM t1 WHERE c1 < const GROUP BY c1, c2; SELECT MAX(c3), MIN(c3), c1, c2 FROM t1 WHERE c2 > const GROUP BY c1, c2; SELECT c2 FROM t1 WHERE c1 < const GROUP BY c1, c2; SELECT c1, c2 FROM t1 WHERE c3 = const GROUP BY c1, c2; Primeri stavkov, kjer MySQL ne uporabi indeksov: SELECT c1, SUM(c2) FROM t1 GROUP BY c1; SELECT c1, c2 FROM t1 GROUP BY c2, c3; 18 3 PHP PHP jesplošno namenski programski jezik, prvotno namenjen izdelavi dinamičnih spletnih strani. PHP kodo vključimo kar neposrednov HTML stran, izvršena pa je vsakokrat, ko je naša stran obiskana[6, 29]. Jezik je leta 1994 ustvarilRasmus Lerdorf. Kmalu zatem ga je posvojilo veliko število razvijalcev, ki so ga pripeljali skozi štirivečje verzije. Trenutno je aktualna verzija 5.4, ki je izdana marca 2013.Kljub temu naše ogrodje deluje s PHP verzijo od 5.1naprej, s čimer omogočamo združljivost sstarejšimi projekti. Kljub prvotnemu namenu programiranja dinamičnih spletnih strani se je jezik kasneje razvil in danes omogoča samostojno pisanje namiznih aplikacij ter programiranje skript za vmesnik z ukazno vrstico (angl.:command-line interface, CLI) [30]. Prva možnost ni tako zanimiva in je redko uporabljena, zadnja možnost pa je bila uporabljena za zagon našega ogrodja. Razlog, da je izvorna koda našega ogrodjanapisana v PHP, tiči v tem, da je ta najbolj uporabljen jezik za spletne strani[31] in je v navezi z MySQL in Apache spletnim strežnikom tudi eden najbolj uporabljenih paketov za poganjanje spletnih strani. Prednosti PHP [29, 32]: poceni in efektivna horizontalna skalabilnost, poleg MySQL podpore se je možno povezati tudi na PostgreSQL, Oracle, DB2itd., ker je bil PHP zasnovan za uporabo na spletu, ima veliko vgrajenih funkcij, ki so uporabne za splet; primeri so povezovanje na spletne povezovalne tehnologije (angl.: web services), XML podpora, piškotkiali pošiljanje spletne pošte, od verzije 5 dalje ima močno podporo za objektno programiranje (angl.: object oriented programming);ker se zgleduje po Javi in C++, ima skoraj vse, kar odlikuje objektni model Jave in C++: dedovanje, privatne in javne deklaracije, abstraktne razrede, vmesnike (angl.: interface), konstruktorje (angl.: constructor) in ostalo, dostopnost na večini operacijskihsistemov, zaradi česar je izvorna koda prenosljiva, je odprtokodni projekt in s tem brezplačen, je najbolj podprt pri spletnih gostovanjih, ima zelo obširno dokumentacijo, ki jo najdemo na uradni spletni strani in opisujevse aspekte programskega jezika,zaradi razširjenosti jezika pa so na voljo izvorne kode ter ogromno vtičnikov in drugih vsebin, ki namolajšajo razvoj programske opreme. 19 20 4 NALOGE OGRODJA V poglavju 2.3 smo definirali pogoje, katerim mora poizvedba ustrezati, da lahko MySQL uporabi indeks. Te pogoje mora naše ogrodje upoštevati pri predlogih, ki jih sintetizira. Preden indeks postavimo, potrebujemo oceno njegove upravičenosti, kar ugotavljamo z naslednjo cenilko. MySQL poskuša indekse shranjevati v pomnilnik, v kolikor je ta na voljo. V naslednji analizi smo upoštevali, da se celoten indeks nahaja v pomnilniku. Analiza ne vsebuje časa, ki ga podatkovna baza potrebuje za realokacijo podatkov v pomnilniku. Da lahko izračunamo,kolikšno je maksimalno število operacij, ki jih zahtevajo poizvedbe, potrebujemo število poizvedb v podatkovni bazi in časovno kompleksnost operacij, ki so zbrane v tabeli 2. Brez indeksa Z indeksom SELECT O(n) O(log2 n) INSERT O(1) O(log2 n) UPDATE O(1) O(log2 n) DELETE O(1) O(log2 n) Tabela 2: Časovna zahtevnost operacij [5]. Izračunajmo,kolikšno je maksimalno število operacij, ki jih zahtevajote poizvedbe, če indeks ni postavljen: 𝐶brez indeksov 𝑛, 𝑚𝑠 , 𝑚𝑖 , 𝑚𝑢 , 𝑚𝑑 = 𝑚𝑠 𝑛 + 𝑚𝑖 + 𝑚𝑢 + 𝑚𝑑 (1) Pri tem smo uporabili naslednjo notacijo: n število vrstic v tabeli, ms število poizvedb v tabeli, mi število vnosov v tabelo, muštevilo posodobitev tabele, md število zbrisov v tabeli. Izračunajmo še maksimalno število operacij, ki jihzahtevajo iste poizvedbe, če jeindekspostavljen: 𝐶z indeksom 𝑛, 𝑚𝑠 , 𝑚𝑖 , 𝑚𝑢 , 𝑚𝑑 = 𝑚𝑠 log 2 𝑛 + 𝑚𝑖 log 2 𝑛 + 𝑚𝑢 log 2 𝑛 + 𝑚𝑑 log 2 𝑛 = log 2 𝑛 (𝑚𝑠 + 𝑚𝑖 + 𝑚𝑢 + 𝑚𝑑 ) 21 (2) Če delimoenačbo2zenačbo 1, dobimo: 𝐶 𝑛, 𝑚𝑠 , 𝑚𝑖 , 𝑚𝑢 , 𝑚𝑑 = 𝐶z indeksom log 2 𝑛 (𝑚𝑠 + 𝑚𝑖 + 𝑚𝑢 + 𝑚𝑑 ) = 𝐶brez indeksov 𝑚𝑠 𝑛 + 𝑚𝑖 + 𝑚𝑢 + 𝑚𝑑 (3) V kolikor je C ≥ 1, postavimo indeks, v nasprotnem primeru ga izpustimo. Ko imamo na voljo oceno o koristnosti indeksa, se ogrodje odloči, ali je indeks koristno uporabiti. Naše ogrodje poleg ocene pravilne postavitve indeksov pregleda SQL poizvedbe in ugotovi napačne odločitve, ki se pojavijo v poizvedbah. Za te poizvedbe poda predloge za izboljšave. 4.1 Stavek SELECT Ogrodje v primeru uporabe maskirnega znaka (angl.: wildcard) vrne priporočilo, naj se temu izogibamo, saj lahko poizvedba traja dlje zaradi morebitne velike količine vrnjenih podatkov. 4.2 Stavek WHERE Ogrodjepoleg pravilne postavitve indeksov poda še naslednje predloge: v primeru uporabe operatorja LIKE in maskirnega znaka pred konstanto (primer: LIKE '%primer') nas opozori, da indeks ne bo uporabljen, v primeru, da uporabimo kot logični operator operacijoOR, nam svetuje, naj raje uporabimo stavek UNION in združimo dve poizvedbi. 4.3 Stavek ORDER BY Ogrodjepoleg pravilne postavitve indeksov poda še naslednje predloge: v primeru, da je stavek sestavljen iz stolpcev različnih tabel, nas opozori, da v tem primeru ne moremo uporabiti indeksa in se lahko zgodi, da je poizvedba počasna, če uporabimo različna vrstna reda sortiranja (ASC in DESC), nas ogrodje na to ustrezno opozori. 4.4 Stavek GROUP BY Poleg pravilne postavitve indeksov ogrodje v primeru, da je stavek sestavljen iz stolpcev različnih tabel, opozori, da v tem primeru ne moremo uporabiti indeksa in se lahko zgodi, da je poizvedba počasna. 22 5 ARHITEKTURA OGRODJA V poglavjih2.3in 4smo naredili pregledmožnosti izboljšanja poizvedb teropredelili, kje in kako postaviti indekse. V tem poglavju bomo predstavili implementacijo ogrodja, ki to izvede. V prvem podpoglavju bomo na grobo opisali postopek analiziranja poizvedb, v naslednjih podpoglavjih pa bomo vsak korak podrobneje razčlenili. 5.1 Opis postopka Da naše ogrodje za optimizacijo poizvedb deluje, imamo v postopku analiziranja tri korake, kot kaže slika 5. Slika 5: Postopek analiziranja poizvedb Vloga posameznih korakov je naslednja: iskanje poizvedb:preden lahko analiziramo MySQL poizvedbe, jih moramo v PHP izvorni kodi poiskati,čemur je namenjeni prvi korak postopka, analiza in optimizacija poizvedb: ko smo MySQL poizvedbe našli, jih analiziramo; kot izhod koraka so predlogi postavitve indeksovin predlogi za izboljšave poizvedb, testiranje sprememb: ta korak je opcijski in se izvede,če se uporabnik odloči zatestiranje časaizvajanja predlaganih izboljšav. V nadaljevanju bomo vsakega od korakov podrobno opisali. 5.2 Iskanje poizvedb Razred ScanCode preišče PHP izvorno kodo datotek in v njih vrine košček PHP kode. Te koščke kode zažene razred Crawlerin s tem v podatkovno bazo shrani MySQL poizvedbe, katere potrebujemo v drugem koraku. Razred FileManipulation je pomožni razred, namenjen lažjemu delu z datotekami. 23 5.2.1 Razred ScanCode Slika 6 je grobi opis poteka iskanja poizvedb v PHP kodi. Skozi datoteke projekta se sprehodimo zrazredom RecursiveIterator, ki je del standardne PHP knjižnice [34].Najprej preverimo PHP izvorno kodo, četa komunicira z bazo podatkov. To storimo zato, ker se inicializacija objekta lahko zgodi v drugi datoteki, kot se zgodi MySQL poizvedba.MySQL objektezapišemo v mysqliObjects lastnost razreda, da kasneje do njih dostopamo. Slika 6: Diagram poteka iskanja MySQL poizvedb. V PHP kodi iščemo veljavne poizvedbe tako, da jo najprej s PHP Tokenizer-jem spravimo v zaporedje znakov sfunkcijotoken_get_all, katera sprejme izvorno kodo datoteke in vrne poljeznakov [35]. Z njihovim pregledom nato algoritem poišče klice funkcij,v katerih se izvajajo MySQL poizvedbe. Upoštevati moramo naslednje [36, 37]:mysql_query, query, mysql_query, multi_query, mysqli, real_query in mysqli_realy_query. Prav tako moramo upoštevati tudi predhodno najdene MySQLobjekte in z njimi klicane metode: query, multi_query in real_query. Komentirano kodo ignoriramo. 24 V vrstice, kjer najdemo veljavne MySQL poizvedbe, vrinemo PHP kodo: "\$_optimizeQuery = mysql_real_escape_string({query}); mysql_query(\"INSERT INTO " . $config['MYSQL_SCHEMA'] . ".optimizeQueries (query) VALUES('\" . \$_optimizeQuery . \"') \");" Tanam zagotovi, da se bodo poizvedbe zapisale v tabelo optimizeQueries, ko bomo s spletnim pajkom(angl.: web crawler), ustvarjenim vrazreduCrawler,preiskalispletne naslove (angl.: Uniform Resource Locator, krat.: URL) projekta. Na koncu moramo zapisati lokacije datotek in vrstice, kjer smo vrinili PHP kodo, da se izognemo duplikatom v primeru,da uporabnik še enkrat zažene ukaz scanCode, in da lahko počistimo datoteke za sabo in jih s tem vrnemo v prvotno stanje. Te informacije zapišemo v podatkovno bazo. 5.2.2 Razred Crawler Razred Crawler je spletni pajek. Spletni pajek je program, ki pregleduje splet [33]. V primeru ogrodja pajek namestospleta preiskuje projekt, katerega spletni naslov je definiran v nastavitveni datoteki. Namen razreda je vzpostavitev kode, ki smo jo predhodno vstavili v PHP datoteke projekta z razredom ScanCode. 5.2.3 Razred FileManipulation Razred je namenjen lažjemu delu v datotekah. Vsebuje metode, ki jih potrebujeta razreda ScanCode in Run. 5.3 Analiza in optimizacija poizvedb S prejšnjim korakom smo MySQL poizvedbe našli. Sedaj je naloga ogrodja, da jih analizira in ugotovi, kje postaviti indekse in kje je prostor za izboljšave poizvedb. 5.3.1 Razred AnalyzeQueries Razred AnalyzeQueriespredhodno najdene poizvedbe servira razredu MySQLParser, ki nato vrača predloge za optimizacijo,razred IndexFilterpa jih po potrebi filtrira. Na koncu na željo uporabnikarazred izvede šeprimerjalne teste in zapiše potrebne indekse v bazo. 5.3.2 Razred MySQLParser Razred MySQLParser je jedro našega ogrodja.Kot vhod mu razred AnalyzeQueries podaja MySQL poizvedbe, sam pa nato ugotavlja, kje v posamezni poizvedbi postaviti indekse in kje je prostor za izboljšave poizvedb. 25 V prvem korakuz regularnim izrazom (angl.: regular expression) razbijemo poizvedbe v zaporedje znakov[7], s katerimi kasneje operira večina metod razreda(slika7). Slika 7: Diagram poteka optimizacije poizvedbe. 26 Regularni izraz je osnovan na regularnem izrazu za Perl, ki ga je napisal Igor Sutton [38]: ((?:--|\#)[\ \t\S]*|(?:<>|<=>|>=|<=|==|=|!=|!|<<|>>|<|>|\|\||\||&&|&||\+|\*(?!\/)|\/(?!\*)|\%|~|\^|\?)|[\[\]\(\),;`]|\'\'(?!\')|\"\"(?!\"")|".*?(?:(?:""){1,}"|(?<!["\\])"(?!")|\\"{2} )|'.*?(?:(?:''){1,}'|(?<!['\\])'(?!')|\\'{2})|\/\*[\ \t\n\S]*?\*\/|(?:[\w:@]+(?:\.(?:\w+|\*)?)*)|[\t\ ]+|[\.]|[\s]) Sledipreverjanje,ali je poizvedba tipa SELECT. Četemu ni tako in gre za stavek tipa INSERT, UPDATE ali DELETE, preštejemo število izvajanj posameznega stavka. Slednje kasneje potrebujemo za izračun cenilke postavljanja indeksov. Če gre za stavek SELECT, preverimo, ali naša poizvedba vsebuje psevdonime. Ti dodelijo tabeli ali stolpcu drugačno ime, kiga lahko nato uporabljamo v isti poizvedbi. Primera psevdonimov: SELECT column AS psevdonim1 FROM table SELECT column FROM table AS psevdonim2 Nato v teh stavkih iščemo stolpce, ki so kandidati za indekse, kot to definira 2.3 poglavje. To storimo za stavke WHERE, ORDER BY, GROUP BY in JOIN. Algoritem sloni na tem, da se sprehodi čez znake poizvedbe, pri čemer gleda, ali znak ustreza imenustolpca v tabeli,ter preveri, aliznakiv okolici ustrezajo SQL sintaksi in pravilom za postavitev indeksov.Nazadnje upoštevamo še indekspopravke, kot je to definirano v poglavju2.3.6. 5.3.3 Razred IndexFilter Razred IndexFilterfiltriraindekse, ki jih predlaga razred MySQLParser. Med podanimi predlogi odstrani podvojene indekse, jih združuje skupaj in jih na podlagi cenilke, definirane v poglavju 4, izloča ali ohranja. 5.4 Testiranje Po analizi poizvedb imamo podane predloge za postavitve indeksov in za izboljšave poizvedb. Da izvemo, ali so predlogi smiselni, jih je potrebno preizkusiti. Temu je namenjen zadnji in opcijski korak. Razred Benchmarkizvaja meritve, razred DataGenerator pa generira podatke, ki jih morebiti potrebujemo za bolj verodostojne meritve. Pred začetkom testiranja ogrodje zažene naslednjiMySQL stavek: SET SESSION query_cache_type = OFF 27 Taje namenjen temu, da MySQL ne shranjuje rezultatov poizvedb v predpomnilniku (angl.: cache), ker bi to vplivalo na čase trajanj poizvedb. Ogrodje nato zažene poizvedbe, ki jih je predhodno lociralo v PHP kodi, s predhodno postavljenimi indeksi in si zabeleži čase trajanja. Sledi isti postopek, tokrat z indeksi,predlaganimi od ogrodja. Sledi izračun povprečnih časov ter pripadajočih izboljšav ali poslabšanj, izraženih v odstotkih. Nazadnje se podatkovna baza vrne v prvotno stanje. 5.4.1 Razred Benchmark Razred je namenjen shranjevanju časaizvajanja meritev, katere uporabimo, da primerjamo, ali so naši predlogi izboljšav izvedeni časovno hitreje kot rezultati prvotnega stanja. 5.4.2 Razred DataGenerator Razred generira podatke, ki jih potrebujemo pri preizkušanju izboljšav. Potrebujemo ga, kadar imajo tabele premalo zapisov, da bi bili rezultati testiranja verodostojni. Zapisi obstajajo samo v času testiranja. Jedro razreda je metoda generateData, ki glede na podano tabelo ustvari ustrezne podatke, ki ustrezajo podatkovnim tipom, ki so definirani v specifikaciji tabele (slednjo podarazred AnalyzeQueries s pripadajočo metodo loadSchema). MySQL podpira naslednje podatkovne tipe: tinyint, smallint, mediumint, int oz. integer, bigint, float, double, double precision, real, decimal oz. numeric, date, datetime, timestamp, time, year, char, varchar, tinyblob, tinytext, blob, text, mediumblob, mediumtext, longblob, longtext, enum in set[39]. Pri algoritmu za ustvarjanje tipov moramo paziti, da je polje, za katerega ustvarjamo vrednost, lahko tuji ključ stolpca druge tabele, zato moramo izbrati naključno vrednost primarnega ključa. Če je na polju postavljen unikaten ključ, moramo paziti, da generiramo unikatno vrednost. 5.5 UnitTest razredi Ker ima naše ogrodje vsega skupaj okoli 7000 vrstic izvorne kode, je nujno preverjanje posameznih modulov, če delujejo v skladu s pričakovanji. Temu je namenjeno testiranje enot, ki programerjem pomaga identificirati in odpraviti hrošče ter služi kot dokumentacija za metodo, na kateri izvajamo test. Enota je najmanjši del programa, v objektnem programiranju je to ponavadi kar metoda. Metodo testiramo tako, da ji na vhod podamo argumente in opazujemo njen izhod. Če se izhod ujema z našimi pričakovanji, metoda deluje pravilno. Idealno so vsi individualni testi neodvisni med seboj, kar pa je težko dosegljivo (zaradi konstant, globalnih spremenljivk, statičnih metod, itd.)[8]. 28 Problema soodvisnosti se rešimo s strategijo,imenovano dependency injection, ki nam omogoča odstranitev soodvisnosti v izvorni kodi. Eden od možnosti je uporaba vmesnikov namesto imena razredov [40]. Primer vidimo v spodnji PHP kodi, kjer smo kot parameter metode namesto razreda Config uporabili vmesnik ConfigInterface, ki ga kasneje med testiranjem enot nadomestimo z imitiranim objektom (angl.: mock object)[41]: public function __construct(ConfigInterface $config, MysqlInterface $mysql) { $this->config = $config; $this->mysql = $mysql; } V našem ogrodju so napisani testi enot za vsak pomembni del izvorne kode. Vsega skupaj je 93 testnih enot s 165 testnimi primeri, pokritost kode s testnimi enotami pa je 95 %. Kot osnova za testiranje je bilo uporabljeno PHPUnit ogrodje. soConfigDataGeneratorUnitTest, Imitirani razredi ConfigCrawlerUnitTest, ConfigIndexFilterUnitTest, ConfigScanCodeTest in MySQLScanCodeUnitTest. 5.6 Pomožni razredi Poleg do sedaj omenjenih razredov se v ogrodju nahajajo še pomožni razredi, ki so namenjenilažji interakciji z bazo in nastavitvami, ter skrbe za zagon ogrodja preko ukazne vrstice. 5.6.1 Razred Run Ogrodje se zaganjaz razredomRun,kivzpostavipomožne objekte (MySQL, Config, FileManipulation) in prebere argumente, ki smo jih podali preko ukazne vrstice. Glede na uporabnikov vhodnato zažene primerno operacijo. 5.6.2 Razred Config Razred Config je namenjen shranjevanjunastavitev, da do njih lažje dostopamo znotraj drugih razredov. Pripadajoči razredConfigInterface je vmesnik, ki je namenjen testiranju enot (angl.: unit test). 29 5.6.3 MySQL razredi MySQL razredi so namenjenilažjemudelu z bazo. Vmesnik MySQLInterface definira, katere metode morajo vsebovati razredi, ki ga implementirajo. Obenem nam je v pomoč pri testiranju enot, da lahko naredimo imitiran objekt baze, s čimer se izognemo soodvisnosti posameznih modulov in testiranju na podatkovni bazi. RazredaMySQLNormal in MySQLImproved razširjatarazredMySQL.Kateri podrazred MySQL razreda bo uporabljen, odloča Run razred, ki izbere vtičnik MySQLi, vkolikor je ta na voljo, drugače izbere MySQL. Z instancoobjekta MySQL nato izvajamo poizvedbe squery metodo.MetodigetRecords in getOneRecordvrneta rezultate poizvedbe v obliki polja. Razreda vsebujeta tudi metodi za transakcije, in sicer commit in rollback. Metoda getNoOfRecordsvrne število vrstic v trenutni poizvedbi. Slika 8: Razredni diagrampoenotenega jezika modeliranja(angl.: Unified Modeling Language, krat.: UML) MySQL razredov. 30 6 REALIZACIJA OGRODJA V prejšnjem poglavju smo opisali arhitekturo ogrodja. V tem poglavju pa bomo v desetih podpoglavjih podrobneje opisali knjižnice, metode in lastnosti razredov. 6.1 Razred Run Ogrodje zaženemo s priklicem razreda Run,kivzpostavi potrebne objekte (MySQL, Config, FileManipulation) in prebere argumente, ki smo jih podali preko ukazne vrstice. Na podlagi vhoda ukazne vrstice se zgodi naslednje: v primeru, da zaženemo ogrodje brez vhoda ali pa ga kličemo z ukazom info, se kliče metoda runInfo, ki nam izpiše možne ukaze, ukaz compatibilityTest zaženemetodo runCompatibilityTest, ki preveri, čeuporabnikovo okolje ustrezaminimalnim zahtevam, ki so potrebne za delovanje ogrodja, uporaba ukaza scanCodezaženemetodo runScanCode, kiz razredomScanCode preišče PHP datoteke projekta in poišče MySQL poizvedbe, klic ogrodja z ukazom crawlerzažene metodo runCrawler, ki vzpostavi spletnega pajkaz razredom Crawler, ki omogoči, da se zažene koda, dodana z ukazom scanCode, ukaz analyzeQueries zažene metodo runAnalyzeQueries, ki z razredom AnalyzeQueries analizira predhodno zbrane poizvedbe v bazi in jih s pomočjo MySQLParser in IndexFilter optimizira; na koncu lahko izvedemo še primerjalne teste in izbrane indekse zapišemo v bazo, ukazcleanup zažene metodo runCleanup, ki zrazredomScanCodevrne spremenjene datoteke in podatkovno bazo v prvotno stanje, ukazsetupConfigzažene metodo runSetupConfig, ki nastavi nastavitveno datoteko. 31 Slika 9: Razredni diagram UML Run razreda. Metode isWindows, success, info, failure in readInputCLI so namenjene izpisu in vnosu podatkov iz in v orodno vrstico. RazredRunExceptionje namenjen prikazu izjem, ki se pojavijo v času poganjanja ogrodja. 6.2 Razred Config Slika 10 prikazuje metode, njihove vhode in lastnosti razreda Config, katere bomo v nadaljevanju podrobneje opisali. Slika 10: Razredni diagram UML razreda Config. 32 Metode razreda: Metoda __constructzapiše v lastnosti razreda nastavitvene vrednosti, ki so natančneje razložene v dodatku B. Metoda loadje namenjena morebitnemu naknadnemu nalaganju nastavitev, ko je bil objekt že vzpostavljen. Metoda set zapiše nastavitveno vrednost v lastnost razreda. Z metodo __get dostopamo do nastavitev, shranjenih kot lastnosti razreda. 6.3 Razred FileManipulation Slika 11 prikazuje metode, njihove vhode in lastnosti razreda FileManipulation, katere bomo v nadaljevanju podrobneje opisali. Slika 11: Razredni diagram UML razreda FileManipulation. Metode razreda: Metoda getFile prebere datoteko innjene vrstice vrne v obliki polja. Metoda replaceFile zamenja vrstice v datoteki. Kliče metodo writeToFileArray. Metoda writeToFileArray zapiše parameter contentv datoteko. 6.4 Razred ScanCode Slika 12 prikazuje metode, njihove vhode in lastnosti razreda ScanCode, katere bomo v nadaljevanju podrobneje opisali. 33 Slika 12: Razredni diagram UML razreda ScanCode. Lastnosti razreda: Polje replaceArray: lokacije MySQL poizvedb. Niz directory: pot projekta, ki ga bomo pregledali. Objekt MySQL. ObjektFileManipulation. Objekt Config. Polje mysqliObjects: lokacije MySQLi objektov. Metode razreda: Metoda __constructvzpostavi objekt. Metoda setReplaceArray je namenjena testiranju enot, z namenom ponastavitvereplaceArray lastnosti razreda. Metoda scanDirectoryForObjectsrekurzivno poišče datoteke v direktoriju in poddirektorijih projekta. Če je datoteka PHP tipa, kliče metodo findObjects. Metoda scanDiretoryrekurzivno poišče datoteke v direktoriju in poddirektorijih projekta. Če je datoteka PHP tipa, kliče metodo findQuery. Metoda findObjects pregleda vsebino PHP datoteke in išče vzpostavitev MySQL objektov. Vrednosti spremenljivk, ki kažejo na objekt MySQL,shrani v mysqliObjectslastnost razreda. Metoda findQuery pregleda vsebino PHP datoteke in v replaceArraylastnost razreda zapiše vrstico kode, kjer je bila najdena poizvedba. 34 Metoda replaceFiles je iterator čez replaceArraylastnost razreda. Ob vsaki iteraciji kliče metodo writeToFile. Metoda writeToFilevstavi v datoteko PHP košček kode, omenjen v poglavju 5.2.1, v datoteko. Metoda writeToDB zapiše v tabelo optimizeReplacedFiles (ki je bila predhodnoustvarjena) lokacijo in položaj sprememb v datotekah. Metoda cleanup vrne spremenjene datoteke in podatkovno bazo v prvotno stanje. 6.5 Razred Crawler Slika 13 prikazuje metode, njihove vhode in lastnosti razreda Crawler, katere bomo v nadaljevanju podrobneje opisali. Slika 13: Razredni diagram UML Crawler razreda. Lastnosti razreda: Polje checkedUrls: URL naslovi že obiskanih strani. Polje parseUrl: URL projekta, shranjenega zmetodo parse_url. Objekt Config. Metode razreda: Metoda __constructvzpostavi objekt. Metoda getCheckedUrls vrne seznam strani, ki so bile preverjene s spletnim pajkom. Metoda initCrawlPage vzpostavi spletnega pajka. Kličemetodo crawlPage. Rekruzivna metoda crawlPageima kot vhod parameter depth, ki nam pove, koliko nivojev spletnih povezav bo pajek obiskal. Če je argument 1, bo obiskal samo domenski URL, če je argument 2 ali več, pa tudi ustrezno število podnivojev. Metoda dobiargument depth iz nastavitev. Metoda rel2abs pretvori relativni URLv absolutni URL. 35 Metoda curlDownloadvzpostavi URL klic na spletni naslov. cURL je orodje za orodno vrstico, ki omogoča prenašanje podatkov z URL sintakso.Podpira HTTP, HTTPS, FTP, Gopher, Telnet, DICV, file in LDAP protokole. PHP v celoti podpira knjižnicocURL [42]. 6.6 Razred AnalyzeQueries Slika 14 prikazuje metode, njihove vhode in lastnosti razreda AnalyzeQueries, katere bomo v nadaljevanju podrobneje opisali. Slika 14: Razredni diagram UML razreda AnaylzeQueries. Lastnosti razreda: Objekt Config. ObjektMySQL. Polje testParameters: hrani vrednosti dveh nastavitev uporabnika (samodejna nastavitev indeksovin izvajanje testiranja). Polje columns:hrani podatke o strukturi tabele in pripadajočih vrsticah v podatkovni bazi. Polje indexes: hrani podatke o strukturi indeksov v podatkovni bazi. Metode razreda: Metoda __constructvzpostavi objekt. Metoda optimizeIndexes vzpostavi razredaMySQLParser in IndexFilter. Zažene primerjalne teste in po potrebi zapiše nove indekse v bazo. MetodaremoveCharactersodstrani znake iz ukazne vrstice. Metoda queryForIndexesustvari besedilo s priporočeno postavitvijo indeksov glede na argumentaindexQuery in dropOldIndex. 36 Metoda loadSchema shrani stolpce tabele in njihove pripadajoče indekse v columns in indexeslastnostih razreda. Metoda generateQuery ustvari SQL kodo za vnos podatkov iz polja data, v tabelo table. 6.7 Razred MySQLParser Slika 15 prikazuje metode, njihove vhode in lastnosti razreda MySQLParser, katere bomo v nadaljevanju podrobneje opisali. Slika 15: Razredni diagram UML razreda MySQLParser. 37 Lastnosti razreda: Polje filter: znaki, ki jih želimo odstraniti. Polje allowedTypes: tipi poizvedb, ki so relevantne za optimizacijo. Polje statements: ločila stavka SELECT. Polje joinSeparators: ločila stavkov JOIN in SELECT. Polje logicalOperators: logični operatorji v MySQL. Polje aggregateFunctions: agregatne funkcije, ki se uporabljajo v stavku GROUP BY. Polje queries: hrani poizvedbo in njene morebitne pripadajoče podpoizvedbe v obliki znakov. Polje queriesText: hrani poizvedbo in njene morebitne pripadajoče podizvedbe v tekstovni obliki. Polje columns: izhodni parameter, ki shrani stolpce, ki so potencialni kandidati za postavitev indeksa. Polje tokens:znaki poizvedb. Polje tableNames: hrani imena tabel in pripadajočih psevdonimov, ki se pojavijo v poizvedbi. Polje columnNames: hrani imena stolpcev in pripadajočih psevdonimov, ki se pojavijo v poizvedbi. Polje databaseColumns: hrani podatke o strukturi table in pripadajoči vrsticah v podatkovni bazi. Polje databaseIndexes: hrani podatke o strukturi indeksov v podatkovni bazi. Polje optimizationMessages: sporočila za optimizacijo SQL poizvedb. Metode razreda: Metoda __constructvzpostavi objekt. Metoda splitQueries razdrobi SQL poizvedbo na več delov, v kolikor je ta ločena z podpičjem. Metoda checkTypepreveri, ali poizvedba ustreza kriterijem optimizacije (biti mora tipa SELECT, INSERT, UPDATE ali DELETE). Metoda getColumns vrne columns lastnost razreda. Metoda getOptimizationMessagesvrne optimizationMessages lastnost razreda. Metoda getSubTokens vrne znake, ki ustrezajoparametru type. Če je naprimer argument type enak WHERE, bomo dobili WHERE znake. 38 Metoda checkIUDpreveri,koliko INSERT, UPDATE ali DELETE stavkov vsebuje poizvedba. Metoda checkAliasespreveri psevdonime s klicem metodcheckAliasesSelect in checkAliasesFrom. Metoda checkAliasesSelectshrani psevdonime, ki se pojavijo v stavku SELECT, in jih shrani v columnNames lastnost razreda. Metoda checkAliasesFrom shrani psevdonime, ki se pojavijo v stavkihFROM in JOIN, v tableNameslastnost razreda. Metoda kličemetodeoptimizationColumnsWhere, optimizationColumns optimizationColumnsSelect, optimizationColumnsOrderBy, optimizationColumnsGroupBy in optimizationColumnsJoin. Metoda optimizationColumnsWhere išče ustrezne stolpce ali kombinacijo stolpcev, ki bi bili primerni za postavitev indeksa v stavkuWHERE. Upoštevati moramo vsa pravila, ki smo jih definirali v poglavju 2.3.3. Metoda optimizationColumnsSelect pregleda, ali stavek SELECT vsebuje funkcije iskanja po polnem besedilu. Metoda optimizationColumnsGroupByišče ustrezne stolpce ali kombinacijo stolpcev, ki bi bili primerni za postavitev indeksa v stavku JOIN. Upoštevati moramo vsa pravila, ki smo jih definirali v poglavju 2.3.8. Metoda optimizationColumnsJoin išče ustrezne stolpce ali kombinacijo stolpcev, ki bi bili primerni za postavitev indeksa v stavku JOIN. Upoštevati moramo vsa pravila, ki smo jih definirali v poglavju 2.3.5. Metoda checkIndexHintišče ustrezne znake, ki ustrezajo sekciji indeks popravkov (USE, IGNORE, FORCE) in jih posreduje resolveIndexHint metodi. Metoda resolveIndexHint, vkolikor poizvedba vsebuje indekspopravke, upošteva pravila, definirana v poglavju 2.3.6. Metoda resolveTokenNamerazreši znak, v kolikor ta vsebuje psevdonim,ter ga pretvori nazaj v originalno ime. Metoda getSubQueries razbije poizvedbe na več podizvedb, v kolikor te obstajajo. Podizvedbe se shranjujejo v queries lastnost razreda. Metoda tokenize z regularnim izrazom razbije poizvedbe v zaporedje znakov. Metoda removeFilterChars iz znakov poizvedbe odstrani znak, vkolikor je enak eni od filter lastnosti. 39 6.8 Razred IndexFilter Slika 16 prikazuje metode, njihove vhode in lastnosti razreda IndexFilter, katere bomo podrobneje opisali. Slika 16: Razredni diagram UML razreda IndexFilter. Lastnosti razreda: Polje columns: hrani podatke o strukturi tabele in pripadajočih vrsticah v podatkovni bazi. Polje indexes: hrani podatke o strukturi indeksov v podatkovni bazi. Objekt Config. Polje noOfIUD: hrani vrednost, koliko stavkov INSERT, UPDATE in DELETE se je izvedlo v posamezni tabeli. Polje noOfSelects: hrani vrednost, koliko SELECT stavkov se je izvedlo v posamezni tabeli. Metode razreda: Metoda __constructvzpostavi objekt. Metoda extractIndexes na podlagi enačbe 3 ugotovi, ali bo postavila indeks ali ne. V primeru, da je cenilka C ≥ 1, postavi med vsemi možnimi indeksi, ki jih predlaga razred MySQLParser, samo tiste, ki ustrezajo pravilom, definiranim v poglavju 2.3. Metoda groupIndexesišče identične indekse in jih združuje. Metoda reshapeIndexespreuredi vhodoptimizeIndexes v groupedIndexes, da je slednjibolj primeren za metodo removeSetIxdexes. Metoda removeSetIndexes odstrani indekse, ki že obstajajo v podatkovni bazi. 40 Metoda removeDuplicateIndexes odstrani indekse, ki so nepotrebni (indeks i_1(A, B) je v MySQL enak indeksu i_2(A, B, C), zato moramo slednjega odstraniti). 6.9 Razred Benchmark Slika 17 prikazuje metode, njihove vhode in lastnosti razreda Benchmark, katere bomo v nadaljevanju podrobneje opisali. Slika 17: Razredni diagram UML razreda Benchmark. Lastnosti razreda: Polje startTime: začetni časi v obliki UNIX časovnega žiga (angl.: timestamp). Polje savedTimes: končni časi testiranja v milisekundah. Metode razreda: Metoda startTime se kliče pred začetkom testiranja. Parameter group predstavlja ime, ki ga želimo uporabiti za trenutni sklop rezultatov. Metodo endTime se uporabi ob zaključku testiranja. Metoda showTimevrne čas testiranja,shranjenega v polju savedTimes. Parametra group in index predstavljata pozicijo rezultata, ki se nahaja v polju savedTimes. Metoda showAverage uredirezultate po velikosti in izloči zgornjih in spodnjih 10 % rezultatov ter vrne povprečje. Parameter size definira število decimalnih mest rezultata, ki ga metoda vrne. Metoda roundToSignificantDigit zaokroži število number na n pomembnih mest. Parameter roundCeil definira, ali se število zaokroži navzgor ali navzdol. Metoda standardDeviationvrne strandardni odklon, izračunan iz parametra values. Metoda standardError vrne standardno napako. Parameter standardDeviation predstavlja standardni odklona, parameter sampleSize pa število vzorcev. 41 Metoda roundMeanAccToUncertaintyštevilo mean zaokroži na enako število decimalk, kot jo ima uncertainty število. 6.10 Razred DataGenerator Slika 18 prikazuje metode, njihove vhode in lastnosti razreda DataGenerator, katere bomo v nadaljevanju podrobneje opisali. Slika 18: Razredni diagram UML razreda DataGenerator. Lastnosti razreda: Polje columns: hrani podatke o strukturi tabele in pripadajočih vrsticah v podatkovni bazi. Polje indexes: hrani podatke o strukturi indeksov v podatkovni bazi. Objekt Config. Metode razreda: Metoda __constructvzpostavi objekt. MetodagenerateDataiterira skozi stolpce v tabletabeli in glede na tip stolpca pokliče metodo generateRecords. Metoda generateRecordsustvari podatke za vpis v bazo. Preveri, ali je zahtevan podatek unikaten ter prisotnost tujega ključa. Metoda generateRandomIntegervrne naključno število, dolžine parametra length. MetodagenerateRandomFloat vrne naključno decimalno število, dolžineparametra length. MetodagenerateRandomDecimalvrne naključno decimalno število. 42 Metoda generateRandomString vrne naključni niz, dolžine parametra length. Metoda generateRandomDatevrne naključen datum, ki je definiran med vrednostima 01.01.1000 00:00:00 in 9999-12-31 23:59:59. Metoda generateRandomEnum ustvari naključno enum vrednost. Enum je niz, katerega vrednost je izbrana iz polja dovoljenih vrednosti, definiranih ob kreiranju tabele. Metoda generateRandomBit generira naključno binarno vrednost. 43 44 7 UPORABA OGRODJA V tem poglavju bomo predstavili uporabo ogrodja. Prvo podpoglavje je namenjeno predstavitvi potrebne datotečnestruktureprojekta, ki ga želimo optimizirati. Sledijo možne uporabeogrodja. 7.1 Struktura datotek Predpostavljamo, da ima uporabnikže nameščeno programsko opremo, ki omogoča poganjanje paketov PHP in MySQL. Potrebna programska oprema zajema operacijski sistem Windows,spletni strežnik Apache,podatkovno bazo MySQL inprogramski jezik PHP(krat.: WAMP)aliustrezno ekvivalentno zbirko na operacijskem sistemu Linux(krat.: LAMP). Na sliki 19vidimo priporočeno osnovno strukturoogrodja spripadajočim projektom. V direktoriju »myProject« se nahaja PHP projekt, kateremu bi radi optimizirali MySQL poizvedbe. Slika 19: Direktorijska struktura projekta. 45 V »FMQO« direktoriju se nahaja naše ogrodje z vsemi pripadajočimi datotekami. V »config«poddirektoriju se nahajajo nastavitve ogrodja, katere so podrobno predstavljene v prilogi A.Poddirektorij »Library«vsebuje knjižnice, ki so jedro našega ogrodja, »tests«vsebuje datoteke s testnimi enotami, kizagotavljajo, da knjižnice delujejo v skladu s pričakovanji. Nazadnje je tu še »run.php« datoteka, katere naloga je izvajanje operacij, ki jih ogrodje omogoča.Za direktorij »FMQO« ni potrebno, da se nahaja v istem domenskem direktoriju, kot se nahaja projekt, je pa priporočena praksa. 7.2 Ukazi orodja Ogrodje zaganjamo z ukazno vrstico. Teče tako na operacijskem sistemu Linux kot na operacijskem sistemu Windows.V naslednjih sedmih podpoglavjih bomo predstavili možnosti, ki jih ogrodje ponuja. Izpisi ukazov so v dodatku B. 7.2.1 Ukaz info Ukaz prikaže možnosti, ki jih lahko uporabimo pri zagonu ogrodja,ter njihovo obrazložitev. 7.2.2 Ukaz compatibilityTest Ukaz sporoči, ali ima uporabnik nameščene potrebne knjižnice. Če jih nima, uporabnika primerno opozori. 7.2.3 Ukaz scanCode Ukazpregledadirektorij, podan v nastavitveni datoteki. Ustvari potrebne tabele v podatkovni bazi in vrine potrebno PHP kodo v datoteke projekta. 7.2.4 Ukaz crawler Ukazvzpostavi spletnega pajka, kise sprehodi čez spletne naslove projekta, da se vzpostavi koda, dodana z ukazom scanCode. Pri izpisu nam poda spletne naslove, ki jih je pajek obiskal. 7.2.5 Ukaz analyzeQueries Ukaz analizira poizvedbe, zbrane v podatkovni bazi. Pred analizo nas vpraša, ali želimo izvesti primerjalni preizkus in ali želimo vpis predlaganih indeksov v bazo. Vrne priporočene indekse in optimizacije, obenem pa nam pove,kolikšne hitrostne izboljšave lahko pričakujemo. 7.2.6 Ukaz cleanup Ukazvrne datotekev prvotno stanje. Enako stori s podatkovno bazoob pogoju, da nismo zahtevali vpisa predlaganih indeksov v bazo. 46 7.2.7 Ukaz setupConfig Poleg spreminjanjanastavitvenih vrednostiv datoteki »config.conf.php« imamo to možnost tudi z uporabo ukazasetupConfig. Spremenimo lahko vrednosti hostname, password, schema, project path in projectUrl.Ostale vrednosti spremenimo v nastavitvenidatoteki. 47 48 8 TESTIRANJE OGRODJA Testiranje ogrodja smo izvedli na dveh različnih testih. Prvi test vključuje podatkovno bazo, ki jo MySQL priporoča kot testno podatkovno bazo za učenje MySQL[43]. Pri drugem testu smo optimizirali projekt 1a-vreme, ki je na voljo na spletnem naslovu http://www.1a-vreme.si. 8.1 Metodologija testiranja V rezultatih v naslednjih poglavjih je razš irjena negotovost določ ena kot s tandardna negotovost, pomnož ena s faktorjem razš iritve k = 2, ki pri normalni porazdelitvi ustreza ravni zaupanja približ no 95 %. Standardna negotovost je sestavljena iz standardne negotovosti povprečne vrednosti, ki jo izračunamo z enačbo 4. Za izračunanje povprečne vrednosti upoštevamo rezultate meritev, s tem da ne upoštevamo zgornjih in spodnjih 10 %urejenih meritev. Standardni odklon vseh enot statistične populacije je definiran kot [9]: 𝑁 𝑖=1(𝑥𝑖 𝜎= − 𝑥) 𝑁 (4) kjer je xii-ta enota v statistični populaciji, 𝑥 aritmetična sredina populacije, N pa število vseh enot. Standardna napaka vseh enot statistične populacije [9]: 𝐸𝜎 = 𝜎 𝑛 (5) 8.1.1 Anderson-Darling test Ker bomo v nadaljevanju za naše teste računali standardni odklon in standardno negotovost, predpostavljamo, da imajo časi testov normalno porazdelitev. Vendar, če je ta predpostavka napačna, naši rezultati niso zanesljivi. V ta namen uporabimo Anderson-Darling test,ki nam pove, ali naši podatki ustrezajo določeni porazdelitveni funkciji [10, 44]. 𝑛 𝐴𝐷 = 𝑖=1 1 − 2𝑖 [ln 𝐹 𝑌𝑖 𝑛 + ln (1 − 𝐹 𝑌𝑛+1−𝑖 )] − 𝑛 49 (6) Fje porazdelitvena funkcija, n je število vzorcev, Yi pa predstavlja i-ti vzorec iz sortirane tabele vzorcev.V našem primeru bomo preverjali, če rezultati ustrezajo normalni porazdelitvi, zato je porazdelitvena funkcija [45]: 𝐹 𝑥, 𝜇, 𝜎 = 1 2𝜋𝜎 𝑒 (𝑥−𝜇 )2 2𝜎 2 − (7) Simbol μpredstavlja aritmetično sredino populacije in σ standardniodklon (enačba4). V primeru, da velja enačba 8, naši vzorci ne pripadajo pripadajoči porazdelitvi [10]: 𝐴𝐷 > 0.752 1+ 0.75 𝑛 + 2.25 𝑛2 (8) 8.2 Test podatkovne bazeSakila Podatkovno bazo Sakila je razvil Mike Hilyer, nekdanji član MySQL dokumentacijske ekipe, in je namenjena kot primer standardne podatkovne sheme, ki se uporablja v knjigah, člankih in tečajih [43]. Slika 20: Model intetitet in povezav (angl.: Entity–relationship, krat.: ER) diagram podatkovne bazeSakila. 50 Podatkovna baza ima že definirane poglede, katerih poizvedbe so navedene v prilogi C.Za te so indeksi že optimalno postavljeni. Za namen testiranja smo ustvarili testni projekt, kjer smo uporabili omenjeneSQL poizvedbe. Z ogrodjem smo optimizirali podatkovno bazo, iz katere smo odstranili vse pripadajoče indekse, ki se nahajajov prilogi D. Na podatkovni bazi s postavljenimi indeksi od ogrodja smo nato pognali 33 testov in izračunali povprečje časov izvajanja teh testov s pripadajočo standardno negotovostjo (metodologija testiranja je razložena v poglavju 8.1). Nato smo naredili enakos prvotno postavljenimi indeksi in primerjali čase. Predlagani indeksi ogrodja se nahajajo v prilogi D. Predlagani indeksi Prvotni indeksi AD 0,23 0,34 Čas izvajanja 1,3882 s ± 3,4 ms 1,3541 s ± 3,8 ms Izboljšava –2,5 % ± 0,3 % Tabela 3: Rezultati testiranja podatkovne bazeSakila. Časov izvajanja stavkov brez postavljenih indeksov nismo merili, saj imajo poizvedbe veliko število JOIN stavkov. Kot primer naj omenimo spodnjopoizvedbo, ki ima JOIN stavke v sedmih tabelah: rental, inventory, store, address, city, country in staff. SELECT CONCAT(c.city, _utf8',', cy.country) AS store , CONCAT(m.first_name, _utf8' ', m.last_name) AS manager , SUM(p.amount) AS total_sales FROM payment AS p INNER JOIN rental AS r ON p.rental_id = r.rental_id INNER JOIN inventory AS i ON r.inventory_id = i.inventory_id INNER JOIN store AS s ON i.store_id = s.store_id INNER JOIN address AS a ON s.address_id = a.address_id INNER JOIN city AS c ON a.city_id = c.city_id INNER JOIN country AS cy ON c.country_id = cy.country_id INNER JOIN staff AS m ON s.manager_staff_id = m.staff_id GROUP BY s.store_id ORDER BY cy.country, c.city Če ni postavljenih indeksov, MySQL ustvari začasno tabelo,ki je v tem primeru sestavljena iz 1,15939×1016 vrstic. Poizvedba bi brez postavljenih indeksov trajala zelo dolgo časa.Iz tega lahko predpostavljamo, da bi primerjava pokazala, da je izboljšava blizu 100 %.Iz rezultatov meritev je razvidno, daje čas izvajanja poizvedb z originalnimi indeksi približno 2,5 % hitrejši kot v primeru izvajanja poizvedb z indeksi, ki jih predlaga ogrodje. Poraba prostora je v korist ogrodju, saj podatkovna baza v prvotnem stanju zaseda 6,6 MB, z indeksi, postavljenimi z ogrodjem, pa 4,3 MB. 51 8.3 Test podatkovne baze1a-vreme Napodatkovni bazi 1a-vreme je bilo ogrodje na produkcijskem strežnikuvklopljeno slab dan. V tem času se je izvršilo in zabeležilo preko 14000 poizvedb, izmed katerih smo jih nekaj omenili v prilogi C. Slika 21: ER diagram podatkovne baze1a-vreme. 52 Z ogrodjem smo nato optimizirali podatkovno bazo, iz katere smo odstranili prvotno postavljene indekse, ki so definirani v prilogi D. Pognali smo 33 testov in izračunali povprečje časov izvajanja teh testov s pripadajočo standardno negotovostjo (metodologija testiranja je razložena v poglavju 8.1). Nato smo z ogrodjem postavili indekse definirane, ki se nahajajo v prilogi D. Nazadnje smo to naredili še sprvotno postavljenimi indeksi. Te je postavil strokovnjak s petimi leti izkušenj s podatkovno bazo MySQL. Brez indeksov Ogrodje indeksi Prvotni indeksi AD 0,51 0,35 0,41 Čas izvajanja 0,7493 s ± 2,4 ms 0,76368 s ± 0,30 ms 0,79432 s ± 0,26 ms Izboljšava 89,8 % ± 0,4 % in 3,9 % ± 0,4 % Tabela 4: Rezultati testiranja podatkovne baze1a-vreme. Iz rezultatov razberemo, da smo z uporabo ogrodja izboljšali hitrost izvajanja poizvedb za okoli 89,8 % v primerjavi s poizvedbami, kjer ni postavljenih indeksov. 3,9 % pa je izboljšava s prvotnim stanjem. Poleg predlaganih indeksov nam je ogrodje podalo še naslednje predloge, ki pa v primeru projekta 1a-vreme niso relevantni, ker se pri izpisu uporabljajo vsi stolpci v tabeli. Predloga sta: »Selecting all columns with the * wildcard is not recommended, because the query might have to retrieve too much data. (query: "SELECT * FROM forecastDataLarge WHERE forecastCityID = 3")« in »Selecting all columns with the * wildcard is not recommended, because the query might have to retrieve too much data. (query: "SELECT * FROM skiingForecast WHERE forecastCityID = 17")«. 53 54 9 SKLEPNE UGOTOVITVE IN IDEJE ZA NADALJNE DELO Analiza optimalnega postavljanja indeksov in optimalnega pisanja poizvedb zahteva veliko predznanja. Ker na trgu za podatkovno bazoMySQL ne obstaja orodje, ki bi to namesto nas avtomatiziralo,smo v ta namen izdelali lastno ogrodje, ki optimalno postavi indekse in opozori na potencialne izboljšave v sestavi poizvedbe. Ogrodje smo preizkusili na dveh podatkovnih bazah. Prva podatkovna baza je bila Sakila in je primer standardne MySQL podatkovne sheme, ki se uporablja v knjigah, člankih in tečajih podatkovnih baz. Ima že vnaprej pripravljene poizvedbein indekse.Ogrodje za skoraj 100 % izboljša hitrost izvajanja poizvedb v primerjavi sSakilapodatkovno bazo, ki nima postavljenih indeksov. V primerjavi spredhodno postavljenimi indeksi pa je razlika v hitrosti približno 2,5 % v prid prvotnemu stanju. Poraba prostora je v prid ogrodju, saj podatkovna baza v prvotnem stanju zaseda približno 53 % več prostora kot podatkovna baza z indeksi, postavljenimi z ogrodjem.Ogrodje smo nato preizkusili še na projektu 1a-vreme, ki se uporablja v produkciji, in sicer na spletnem naslovu http://www.1avreme.si.Iz rezultatov smo razbrali, da smo z uporabo ogrodja izboljšali hitrost izvajanja poizvedb za okoli 89,8 % v primerjavi s poizvedbami, kjer ni postavljenih indeksov. Približno 3,9 % pa je izboljšava s stanjem, kot je bilo, ko so bili indeksi postavljeni predhodno. V obeh primerih je ogrodje zelo dobro služilo svojem namenu. Indekse je postavilo ekvivalentno dobro strokovnjaku z nekajletnimi izkušnjami dela s podatkovnimi bazami. Kot tako je zato ogrodje primerno tako za začetnike kot izkušene uporabnike podatkovnih baz. Izvorno kodo nameravamo preko spletne strani Github ponuditi širši skupnosti. Čeprav ogrodje izpolnjuje zadane cilje, pa je v prihodnosti možnih kar nekaj izboljšav oz. odprav pomanjkljivosti, ki smo jih odkrili že v času razvoja. Ena od pomanjkljivosti je ta, da ogrodje zaenkrat deluje samo v primeru, če ima projekt, ki ga optimiziramo s povezavo samo na eno podatkovno bazo. Torej bi bila potencialna izboljšava povezovanje na več podatkovnih baz. Ker MySQL ni edina podatkovna baza, s katero se PHP lahko poveže, bi bila naslednja potencialna izboljšava razširitev optimizacij na še druge podatkovne baze. Zadnja možna izboljšavapa je seveda razširitev ogrodja za druge programske jezike, ki se povezujejo napodatkovno bazo MySQL. 55 56 DODATEK A: NASTAVITVEOGRODJA V tem razdelku podajamo možne nastavitve ogrodja, ki jih nastavimo v datoteki »config.conf.php«. 1. MySQL nastavitve Nastavitev MYSQL_HOSTNAME: IP-naslov ali ime gostitelja (angl.: hostname) MySQL strežnika. Če optimiziramo projekt na strežniku, je to vrednost IP-naslova strežnika, kjer se nahaja MySQL. V primeru razvoja na lokalnem računalniku je ta vrednost navadno kar localhost ali "127.0.0.1". Nastavitev MYSQL_USERNAME: Ime uporabnika, s katerim dostopamo do podatkovne baze. Nastavitev MYSQL_PASSWORD: Geslo za MySQL uporabnika, s katerim dostopamo do podatkovne baze. Nastavitev MYSQL_SCHEMA: Ime podatkovne baze, ki je uporabljena v projektu in čigar poizvedbe želimo optimizirati. 2. Direktorijske nastavitve NastavitevPROJECT_PATH: Pot do projekta. Lahko je v absolutni ali relativni obliki. Če se direktorij FMQO nahaja v istem domenskem direktoriju kot projekt, je lahko ta vrednost relativna: "../ime_projekta/". Nastavitev PROJECT_URL: Spletni naslov, preko katerega dostopamo do našega projekta. Ta vrednost je opcijska, potrebna le, če uporabimo spletnega pajka, ki smo ga predstavili v poglavju 5.2.2. Nastavitev SCAN_DIRECTORY_EXTENSIONS: Polje, ki definira končnice PHP datotek. Ogrodje jih bo upoštevalo pri pregledu datotečne strukture. 3. Nastavitve spletnega pajka Nastavitev CRAWLER_DEPTH: Koliko nivojev spletnih povezav bo pajek obiskal. 4. Testiranje Nastavitev BENCHMARK_NO_OF_INSERTS: Število vnosov vrstic v tabele, uporabljene za testiranje. Večja kot je številka, boljša bo natančnost rezultatov testiranja (v kolikor imajo tabele malo zapisov). Nastavitev BENCHMARK_REPEATS: Število ponovitev testa. Za dobro oceno primerjave testiranja naj bo številka čim večja. 57 5. Generator podatkov Tukaj se nahajajo nastavitve, ki jih uporablja generator podatkov (razred DataGenerator). Nastavimo lahko dolžine podatkovnih tipov. Vrednosti naj bodo manjše, kot je maksimalna vrednost podatkovnega tipa, saj se bodo tako testi izvajali hitreje. Ogrodje samodejno prilagaja dolžino teh vrednosti, če je vrstica v podatkovni bazi definirana kot unikatna in vkolikor ima podatkovni tip manjšo vrednost, kolikor je zapisov v tabeli. 58 DODATEK B: IZPIS UKAZNIH LUPIN V tem razdelku prikažemo različne izpise ogrodja, ki jih dobimo z zagonom tega preko ukazne vrstice z različnimi opcijami. >php run.php Framework for MySQL optimization Usage: php run.php [switches] --info Shows all possible commands. --compatibilityTest Runs compatibility test. --scanCode Scans the code and prepares database structure. --crawler Scans website for links. --analyzeQueries Analyzes queries and returns prepositions for optimization. --cleanup Cleans database structure and code inserts. --setupConfig <config>Sets config.conf.php file. Example: --setupConfig -hostname 1 -username 2 -password 3 -schema 4 -projectPath ../ -projectUrl http://localhost/ Total time: 0 seconds, Memory: 1.00 MB Ukazna lupina 1: Zagon ogrodja. 59 > php run.php --compatibilityTest Framework for MySQL optimization PHP Environment Compatibility Test (CLI) ---------------------------------------PHP 5.1 or newer...............Yes 5.3.6 MySQL.....................................Yes MySQLi....................................Yes cURL.........................................Yes ---------------------------------------Your environment meets the minimum requirements. Total time: 0 seconds, Memory: 1.00 MB Ukazna lupina 2: Zagon ogrodja z opcijo compatibilityTest. > php run.php --scanCode Framework for MySQL optimization The code was scanned and update. Total time: 0 seconds, Memory: 1.25 MB Ukazna lupina 3: Zagon ogrodja z opcijo scanCode. > php run.php --crawler Framework for MySQL optimization URL: http://localhost/diplomska/myProject/file1.php URL: http://localhost/diplomska/myProject/file2.php URL: http://localhost/diplomska/myProject/subfolder/file1.php URL: http://localhost/diplomska/myProject/subfolder/file2.php URL: http://localhost/diplomska/myProject/index.html Site was successfully scanned by crawler. Total time: 0 seconds, Memory: 1.25 MB Ukazna lupina 4: Zagon ogrodja z opcijo crawler. 60 > php run.php --analyzeQueries Framework for MySQL optimization Do you want to run benchmark? Type 'yes' if you do: yes Do you want the system to set indexes automatically? Type 'yes' if you do: no ---------------------------------------Suggested indexes: ALTER TABLE language ADD INDEX AISPM_index1 (section); ALTER TABLE cities ADD INDEX AISPM_index3 (id,name); ---------------------------------------Suggested optimizations on queries: - ORDER BY is using both descending and ascending ordering. Index can't be used, which can be a performance problem. (query: SELECT section, sKey, sValue FROM language ORDER BY section DESC, sKey ASC) - Selecting all columns with the * wildcard is not recommended, because the query might have to retrieve too much data. (query: SELECT * FROM `forecastDataShort` WHERE `iconTodayMorning` = 'overcast') ---------------------------------------Number of repeats: 33 Mean time without index: 1.976 s +/- 0.021 s Mean time with index: 1.918 s +/- 0.016 s Improvement: 2.9 % +/- 1.9 % -------------------------------------------------------------------------------Total time: 65 seconds, Memory: 14.00 MB Ukazna lupina 5: Izvajanje ukazaanalyzeQueries. 61 > php run.php --analyzeQueries Framework for MySQL optimization Do you want to run benchmark? Type 'yes' if you do: yes Do you want the system to set indexes automatically? Type 'yes' if you do: no ---------------------------------------Suggested indexes: Indexes are already set correctly. Congratulations :)! ---------------------------------------Total time: 4 seconds, Memory: 3.00 MB Ukazna lupina 6: Izvajanje ukaza analyzeQueries na projektu, kjer ni predlaganih izboljšav. > php run.php --cleanup Framework for MySQL optimization The code was cleaned. Total time: 0 seconds, Memory: 1.25 MB Ukazna lupina 7: Zagon ogrodja z opcijo cleanup. > php run.php --setupConfig -hostname 1 -username 2 -password 3 -schema 4 -projectPath ../ -projectUrl http://localhost/ Framework for MySQL optimization Config file was updated. Total time: 0 seconds, Memory: 1.25 MB Ukazna lupina 8: Zagon ogrodja z opcijo setupConfig. 62 DODATEK C: SQL POIZVEDBE 1. SQL poizvedbe podatkovne baze Sakila SELECT film.film_id AS FID, film.title AS title, film.description AS description, category.name AS category, film.rental_rate AS price, film.length AS length, film.rating AS rating, GROUP_CONCAT(CONCAT(actor.first_name, _utf8' ', actor.last_name) SEPARATOR ', ') AS actors FROM category LEFT JOIN film_category ON category.category_id = film_category.category_id LEFT JOIN film ON film_category.film_id = film.film_id JOIN film_actor ON film.film_id = film_actor.film_id JOIN actor ON film_actor.actor_id = actor.actor_id GROUP BY film.film_id SELECT film.film_id AS FID, film.title AS title, film.description AS description, category.name AS category, film.rental_rate AS price, film.length AS length, film.rating AS rating, GROUP_CONCAT(CONCAT(CONCAT(UCASE(SUBSTR(actor.first_name,1,1)), LCASE(SUBSTR(actor.first_name,2,LENGTH(actor.first_name))),_utf8' ',CONCAT(UCASE(SUBSTR(actor.last_name,1,1)), LCASE(SUBSTR(actor.last_name,2,LENGTH(actor.last_name)))))) SEPARATOR ', ') AS actors FROM category LEFT JOIN film_category ON category.category_id = film_category.category_id LEFT JOIN film ON film_category.film_id = film.film_id JOIN film_actor ON film.film_id = film_actor.film_id JOIN actor ON film_actor.actor_id = actor.actor_id GROUP BY film.film_id SELECT CONCAT(c.city, _utf8',', cy.country) AS store , CONCAT(m.first_name, _utf8' ', m.last_name) AS manager , SUM(p.amount) AS total_sales FROM payment AS p INNER JOIN rental AS r ON p.rental_id = r.rental_id INNER JOIN inventory AS i ON r.inventory_id = i.inventory_id INNER JOIN store AS s ON i.store_id = s.store_id INNER JOIN address AS a ON s.address_id = a.address_id INNER JOIN city AS c ON a.city_id = c.city_id INNER JOIN country AS cy ON c.country_id = cy.country_id INNER JOIN staff AS m ON s.manager_staff_id = m.staff_id GROUP BY s.store_id ORDER BY cy.country, c.city 63 SELECT a.actor_id, a.first_name, a.last_name, GROUP_CONCAT(DISTINCT CONCAT(c.name, ': ', (SELECT GROUP_CONCAT(f.title ORDER BY f.title SEPARATOR ', ') FROM sakila.film f INNER JOIN sakila.film_category fc ON f.film_id = fc.film_id INNER JOIN sakila.film_actor fa ON f.film_id = fa.film_id WHERE fc.category_id = c.category_id AND fa.actor_id = a.actor_id ) ) ORDER BY c.name SEPARATOR '; ') AS film_info FROM sakila.actor a LEFT JOIN sakila.film_actor fa ON a.actor_id = fa.actor_id LEFT JOIN sakila.film_category fc ON fa.film_id = fc.film_id LEFT JOIN sakila.category c ON fc.category_id = c.category_id GROUP BY a.actor_id, a.first_name, a.last_name SELECT cu.customer_id AS ID, CONCAT(cu.first_name, _utf8' ', cu.last_name) AS name, a.address AS address, a.postal_code AS `zip code`, a.phone AS phone, city.city AS city, country.country AS country, IF(cu.active, _utf8'active',_utf8'') AS notes, cu.store_id AS SID FROM customer AS cu JOIN address AS a ON cu.address_id = a.address_id JOIN city ON a.city_id = city.city_id JOIN country ON city.country_id = country.country_id SELECT c.name AS category , SUM(p.amount) AS total_sales FROM payment AS p INNER JOIN rental AS r ON p.rental_id = r.rental_id INNER JOIN inventory AS i ON r.inventory_id = i.inventory_id INNER JOIN film AS f ON i.film_id = f.film_id INNER JOIN film_category AS fc ON f.film_id = fc.film_id INNER JOIN category AS c ON fc.category_id = c.category_id GROUP BY c.name ORDER BY total_sales DESC 64 2. Primeri SQL poizvedb podatkovne baze 1a-vreme SELECT observationData.temperature, cities.name, cities.id, observationData.icon, forecastDataShort.temperatureTodayAfternoon, forecastDataShort.temperatureTodayMorning FROM observationData INNER JOIN cities ON observationData.observationCityID = cities.observationCityID INNER JOIN forecastDataShort ON cities.forecastCityID = forecastDataShort.forecastCityID WHERE cities.name LIKE 'portorož%' ORDER BY cities.name DESC LIMIT 0, 8 SELECT cities.id, observationData.temperature, cities.forecastCityID, observationData.pressure, observationData.humidity, observationData.rain, observationData.dateIssued, observationData.windSpeed, observationData.windDirection, observationData.icon, observationData.text, cities.name FROM observationData INNER JOIN cities ON observationData.observationCityID = cities.observationCityID WHERE cities.id = 37 UPDATE forecastDataLarge SET d1t = 'Danes', d1lt = -4, d1ht = -3, d1i = 'overcast_lightSN', d2t = 'Jutri', d2lt = -5, d2ht = -2, d2i = 'overcast_lightSN', d3t = 'Torek', d3lt = -4, d3ht = 1, d3i = 'prevCloudy_lightSN', d4t = 'Sreda', d4lt = -5, d4ht = -2, d4i = 'overcast_lightSN', d5t = 'Četrtek', d5lt = -4, d5ht = -2, d5i = 'overcast_modSN' WHERE forecastCityID = 22 SELECT id, dateIssued FROM observationDataHistory WHERE observationCityID = 43 ORDER BY id DESC LIMIT 0, 1 65 66 DODATEK D: REZULTATI TESTIRANJ 1. Podatkovna baza Sakila Tabela Prvotni indeksi Predlagani indeksi ogrodja actor (actor_id); (last_name) (actor_id) address (address_id); (city_id) (address_id,city_id); (city_id) category (category_id) (category_id) city (city_id); (country_id) (city_id,country_id);(country_id); (city, city_id, country_id) country (country_id) (country_id); (country, country_id) customer (customer_id); (store_id); / (address_id); (last_name) film (film_id); (title); (film_id) (language_id); (original_language_id) film_actor (actor_id, film_id); (actor_id); (film_id, actor_id) (film_id) film_category (film_id, category_id); (film_id, category_id); (category_id, film_id) (category_id) film_text (film_id); (title, description) inventory (inventory_id); (film_id); (inventory_id, film_id); (inventory_id, store_id) (store_id, film_id) language (language_id) / payment (payment_id); (staff_id); (amount, rental_id); (rental_id) (customer_id); (rental_id) rental (rental_id); (rental_date, (rental_id, inventory_id); inventory_id, (inventory_id) customer_id); (inventory_id); (customer_id); (staff_id) staff (staff_id); (store_id); (staff_id); (address_id); (address_id) store (store_id); (store_id,address_id,manager_staff_id);(address_id); (manager_staff_id); (manager_staff_id) (address_id) Tabela 5: Indeksi, postavljeni na podatkovni baziSakila. 67 Predlagani indeksi [ms] Prvotni indeksi [ms] 1,376591 1,344317 1,377894 1,344799 1,379005 1,345092 1,380190 1,345359 1,380679 1,345973 1,382905 1,346942 1,383053 1,349032 1,383097 1,349298 1,384258 1,349599 1,384380 1,350148 1,385689 1,350956 1,386336 1,351078 1,386667 1,351446 1,387462 1,351453 1,387684 1,352699 1,387991 1,353527 1,388050 1,353574 1,388467 1,354766 1,388539 1,354849 1,388591 1,355607 1,389749 1,356701 1,389942 1,356937 1,390001 1,358312 1,392227 1,358886 1,392650 1,359662 1,393390 1,359751 1,393520 1,359902 1,393654 1,360293 1,396079 1,360914 1,396380 1,362436 1,396773 1,363531 1,398712 1,368839 1,399968 1,392605 Tabela 6: Časi trajanj primerjalnih testov na podatkovni baziSakila. 68 2. Podatkovna baza 1a-vreme Brez indeksov [s] Predlagani indeksi [ms] Prvotni indeksi [ms] 0,745436 75,651 78,912 0,745450 75,676 78,957 0,745533 75,756 78,967 0,745548 75,775 78,969 0,745564 75,778 78,973 0,746067 75,871 78,985 0,746178 75,991 78,990 0,746208 75,996 79,080 0,746228 76,030 79,098 0,746297 76,059 79,178 0,746507 76,107 79,254 0,747690 76,175 79,281 0,747840 76,192 79,303 0,748077 76,276 79,318 0,748443 76,286 79,342 0,748571 76,302 79,377 0,749210 76,304 79,400 0,749421 76,318 79,412 0,749628 76,406 79,421 0,749824 76,432 79,496 0,750213 76,469 79,500 0,750876 76,517 79,554 0,751217 76,532 79,558 0,751642 76,586 79,578 0,751666 76,741 79,744 0,751693 76,859 79,834 0,753241 76,903 79,868 0,754085 76,984 79,993 0,755061 76,997 80,047 0,755297 77,040 80,110 0,755424 77,047 80,112 0,757751 77,290 80,185 0,759634 77,406 80,262 Tabela 7: Časi trajanj primerjalnih testov na podatkovni bazi1a-vreme. 69 Tabela Prvotni indeksi Predlagani indeksi ogrodja cities (id); (name) (observationCityID,forecastCityID); (id,name,observationCityID,forecastCityID); (name,observationCityID,forecastCityID); (id,observationCityID,forecastCityID) forecastCities (id) / forecastDataLarge (forecastCityID) (forecastCityID) forecastDataShort (forecastCityID) (forecastCityID) forecastTenDays (id) / generalForecast (id); (datetime) (id); (datetime) observationCities (id) / observationData (observationCityID) (observationCityID) observationDataHistory (id); / (observationCityID) radar (id); (datetime) / skiingCities (id) (id); skiingForecast (forecastCityID) / skiingObservationalData (id) (id,observationCityID);(observationCityID,id); Tabela 8: Indeksi, postavljeni na podatkovni bazi1a-vreme. 70 10 LITERATURA [1] Tomaž Mohorič.Podatkovne baze. Ljubljana, str. 11–20 in 125–151, 2002. [2] Thomas M. Connolly, Carolyn E. Begg.Database Systems A Practical Approach to Design, Implementation and Management, Pearson Education, str. 24–26 in 89–103, 2005. [3] Paul DuBois.MySQL (4th Edition). Pearson Education, 2008. [4] Baron Schwartz, Peter Zaitsev, Vadim Tkachenko.High Performance MySQL Optimization, Backups, and Replication (3rd Edition). O'Rielly Media, str. 719–734, 2012. [5] Thomas H. Cormen, Charles E. Leiserson, Ronald L. Rivest, Clifford Stein. Introduction to Algorithms (3th Edition). Massachusetts Institute of Technology, str. 286–734, 2009. [6] Luke Welling, Laura Thomson.PHP and MYSQL Web Development (4th Edition). Pearson Education, str. 2–10, 2009. [7] Jeffrey E. F. Friedl. Mastering Regular Expressions (3rd Edition). O'Rielly Media, str. 4–33, 2006. [8] Sebastian Bergmann, Stefan Priebsch.Real-World Solutions for Developing High-Quality PHP Frameworks and Applications. Wiley Publishing, str. 15–71, 2011. [9] Gregor Geršak.Merilna negotovost za začetnike. Ljubljana, str. 8–15, 2006. [10] Jorge Luis Romeu.Anderson-Darling: A goodness of Fit Test for Small Samples Assumptions. START, letnik X, št. 5,str. 1–3, 2003. Spletni viri (dostopnost vseh preverjena marca 2013) [11] Sistem za upravljanje podatkovne baze. Dostopno na: http://colos1.fri.unilj.si/ERI/RACUNALNISTVO/PODATKOVNE_BAZE/opredelitev_pojma_supb.html [12] Sistem za upravljanje s podatkovno bazo. Dostopno na: http://sl.wikipedia.org/wiki/Sistem_za_upravljanje_s_podatkovno_bazo [13] Oracle acquired Sun. Dostopno na: http://www.oracle.com/us/sun/index.htm [14] Podatkovni model. Dostopno na: http://colos1.fri.unilj.si/ERI/RACUNALNISTVO/PODATKOVNE_BAZE/podatkovni_model.html 71 [15] SQL. Dostopno na: http://en.wikipedia.org/wiki/SQL [16] What Standards MySQL Follows. Dostopno na: http://dev.mysql.com/doc/refman/5.0/en/standards.html [17] Benchmarks. Dostopno na: http://www.mysql.com/why-mysql/benchmarks/ [18] Overview of SQL Query Analyzer. Dostopno na: http://msdn.microsoft.com/en-us/library/aa216945(v=sql.80).aspx [19] EXPLAIN Syntax. Dostopno na: http://dev.mysql.com/doc/refman/5.0/en/explain.html [20] Database index. Dostopno na: http://en.wikipedia.org/wiki/Database_index [21] How MySQL Uses Indexes. Dostopno na: http://dev.mysql.com/doc/refman/5.0/en/mysql-indexes.html [22] SELECT Syntax. Dostopno na: http://dev.mysql.com/doc/refman/5.0/en/select.html [23] Expression Syntax. Dostopno na: http://dev.mysql.com/doc/refman/5.0/en/expressions.html [24] UNION Syntax. Dostopno na: http://dev.mysql.com/doc/refman/5.0/en/union.html [25] JOIN Syntax. Dostopno na: http://dev.mysql.com/doc/refman/5.0/en/join.html [26] Index Hint Syntax. Dostopno na: http://dev.mysql.com/doc/refman/5.0/en/index-hints.html [27] ORDER BY Optimization. Dostopno na: http://dev.mysql.com/doc/refman/5.0/en/order-by-optimization.html [28] GROUP BY Optimization. Dostopno na: http://dev.mysql.com/doc/refman/5.0/en/group-by-optimization.html [29] PHP. Dostopno na: http://en.wikipedia.org/wiki/PHP 72 [30] What can PHP do. Dostopno na: http://www.php.net/manual/en/intro-whatcando.php [31] PHP Usage Trends. Dostopno na: http://trends.builtwith.com/framework/PHP [32] PHP. Dostopno na: http://www.php.net/ [33] Web crawler. Dostopno na: http://en.wikipedia.org/wiki/Web_crawler [34] The RecursiveIteratorIterator class. Dostopno na: http://php.net/manual/en/class.recursiveiteratoriterator.php [35] Function token_get_all. Dostopno na: http://www.php.net/manual/en/function.token-get-all.php [36] MySQL Functions. Dostopno na: http://php.net/manual/en/ref.mysql.php [37] The MySQLi Extension Function Summary. Dostopno na: http://php.net/manual/en/mysqli.summary.php [38] SQL::Tokenizer. Dostopno na: http://search.cpan.org/~izut/SQL-Tokenizer-0.24/lib/SQL/Tokenizer.pm [39] Data Type Overview. Dostopno na: http://dev.mysql.com/doc/refman/5.0/en/data-type-overview.html [40] Dependency injection. Dostopno na: http://en.wikipedia.org/wiki/Dependency_injection [41] Mock Objects. Dostopno na: http://www.phpunit.de/manual/3.0/en/mock-objects.html [42] Client URL Library. Dostopno na: http://php.net/manual/en/book.curl.php [43] Sakila Sample Database. Dostopno na: http://dev.mysql.com/doc/sakila/en/index.html [44] Anderson–Darling test. Dostopno na: http://en.wikipedia.org/wiki/Anderson%E2%80%93Darling_test [45] Normal distribution. Dostopno na: http://en.wikipedia.org/wiki/Normal_distribution2 73 IZJAVA Izjavljam, da sem diplomsko delo izdelal samostojno pod vodstvom mentorja doc . dr. Boš tjana Murovca, univ. dipl. inž . el. Izkazano pomoč drugih sodelavcev sem v celoti navedel v zahvali. Ljubljana, 22.05.2013 Matjaž Mrgole
© Copyright 2024