Sunteți pe pagina 1din 18

VII - MS- SQL Data Partitioning

Aspecte legate de modul de organizare al fiierelor bazelor de date O baz de date poate fi compus din mai multe fiiere (.mdf, .ndf, .ldf). Se recomand ca fiierele ce compun filegroupul primary (fiierele .mdf) s nu fie folosite pentru gzduirea obiectelor asupra crora sunt aduse modificri n mod repetat (tabele, indeci, etc.). Minimiznd procesele de scriere asupra acestor fiiere (care totodat definesc i starea bazei de date), se reduce riscul coruperii acestora n cazul ntreruperilor neprevzute sau din cauza problemelor hardware. Fiierele cu extensia .ndf (secondary database file) sunt folosite n cazul optimizrilor i vor gzdui tabelele i indecii bazei de date. Fiierele .ndf pot fi gzduite pe discuri diferite mbuntind astfel timpii de rspuns ai SGBD -ului. Transaction log files (.ldf) sunt cunoscute ca fiind fiierele asupra crora MSSQL efectueaz scrieri secveniale. Se recomand ca aceste fiiere s fie izolate de fiierele filegroupurilor primary & secondary. Decizia de a distribui baza de date pe mai multe fiiere (.mdf, .ndf, .ldf) este dictat n principal de estimri referitoare la dimensiunea bazei de date, frecvena interogrilor, frecvena operaiilor de actualizare, etc. Nu consider c este greit a crea o baz de date compus doar din dou fiiere (.mdf i .ldf), dar susin ideea c n etapa de design a bazei de date este bine a organiza tabelele i indecii pe mai multe filegroupuri astfel nct s oferim posibilitatea administratorului serverului de baze de date s distribuie fiierele pe mai multe discuri.

n prima versiune, baza de date COMANDA este alctuit din dou fiiere (.mdf i .ldf).

n a doua versiune, baza de date COMANDA este compus din mai multe fiiere .mdf, .ndf, .ldf.

Aadar, n a doua versiune, baza de date COMANDA este organizat pe mai multe fiiere, iar tabelele i indecii sunt grupai pe filegroupuri separate (n funcie de dinamica nregistrrilor). La o astfel de organizare se poate ajunge chiar i plecnd de la o baz de date (aflat n producie) distribuit doar pe dou fiiere (.mdf i .ldf), ns n prealabil administratorul SGBD-ului va trebui s efectueze o analiz a structurii bazei de date. Pan n acest punct am vrut s subliniez cteva aspecte legate de modul de organizare al fiierelor bazelor de date. Mai departe am s demonstrez beneficiile partiionrii tabelelor. Am s evit pe ct de mult teoria (poate fi gsit pe MSDN, SQL Server Books Online, Training Kit, etc.) i am s m axez pe un exemplu concret. Baza de date COMANDA (219.30 MB) este populat astfel:

Agent: 305 nregistrri (0.023 MB); Client: 306 nregistrri (0.023 MB); Produs: 17 nregistrri (0.008 MB); Comanda: 500 000 nregistrri (84.992 MB); LinieComanda: 2 426 916 nregistrri (127.258 MB);

n cazul n care dorii s urmai exemplul, putei descrca o copie a bazei de date, sau putei popula baza de date cu ajutorul MSSQLDataPartitioning_02.sql (presupune existena celei de-a doua versiuni a bazei de date COMANDA).

nainte de a efectua partiionarea tabelelor Comanda i LinieComanda, am verificat viteza de execuie a dou interogri SQL. Fraza SELECT-SQL Interval execuie (secunde) Totalul vnzrilor produselor comercializate n 2009 13 Totalul vnzrilor produselor comandate n 2009 7 Partiionarea permite distribuia unui tabel, index, index view pe mai multe filegroupuri, mprirea efectundu -se pe baza unor reguli stabilite de administratorul SGBD-ului. n forma actual, tabelele Comanda i LinieComanda sunt gzduite de filegroupul SECONDARY2.

Datorit numrului relativ mare de nregistrri al tabelelor Comanda i LinieComanda, ne propunem s efectum partiionarea pe baza anului n care comenzile au fost create. Partiionarea presupune:

Definirea unei funcii de parionare prin intermediul creia se definesc limitele de partiionare; Definirea / stabilirea filegroupurilor folosite la partiionare; Definirea schemei de partiionare pe baza schemei de partiionare vor fi specificate filegroupurile implicate n partiionare precum i funcia de partiionare pe baza creia datele vor fi distribuite.

Avnd n vedere c n baza de date avem comenzi din anii 2008, 2009, 2010, vom crea o funcie de partiionare ale crei limite vor defini trei partiii, partiii ce vor fi mapate pe trei filegrupuri. Una, mai multe, sau chiar toate partiiile pot fi mapate pe un singur filegroup. n acest exemplu am decis ca fiecare partiie s fie gzduit pe filegroupuri separate.

Partiionarea tabelei Comanda n cazul partiionrii tabelei Comanda se va crea o funcie de partiionare cu limitele incluse n partiia din dreapta. Partiionarea tabelei se va face n funcie de data la care comanda a fost creat (tip de date DATETIME2).

Pe baza acestei funcii de partiionare vom putea partiiona comenzile (nregistrrile) per ani. Deci conform acestei funcii: Partiia numrul Minimum Maximum 1 0001-01-01 00:00.0000000 2008-12-31 23:59:59.9999999 2 2009-01-01 00:00.0000000 2009-12-31 23:59:59.9999999 3 2010-01-01 00:00.0000000 9999-12-31 23:59:59.9999999 sys.partition_range_values, sys.partition_functions, sys.partition_parameters, sys.types MSSQLDataPartitioning_06.sql

nainte de a crea schema de partiionare (a defini cum anume se va face efectiv partiionarea) este necesar a crea filegroupurile. Avnd n vedere c vor fi trei partiii, am decis crearea a trei filegroupuri.

sys.filegroups, sys.database_files

Crem schema de partiionare.

Deoarece tabela Comanda deja conine nregistrri va fi necesar recrearea indexului clustered pentru ca partiionarea s se realizeze efectiv. nainte de a recrea indexul, haidei s vedem care este structura actual.

Aadar, tabela Comanda este nc gzduit de fiierele ce compun filegroupul SECONDARY2. Dac ne uitm i la dimensiunea pe disc a fiierelor COMANDA_SECONDARY3_DATA1.ndf, COMANDA_SECONDARY4_DATA1.ndf, COMANDA_SECONDARY5_DATA1.ndf vom observa c acestea au rmas la dimensiunea specificat n momentul crerii lor (512 KB).

Dac vom recrea indexul clustered va trebui s avem urmtoarea distribuie.

Deci conform rezultatului obinut putem afirma c tabela Comenzi va fi partiionat astfel: Partiia numrul 1 2 3 Minimum 0001-01-01 00:00.0000000 2009-01-01 00:00.0000000 2010-01-01 00:00.0000000 Maximum 2008-12-31 23:59:59.9999999 2009-12-31 23:59:59.9999999 9999-12-31 23:59:59.9999999 Detalii 25000 de nregistrri (ultima comand din an: 25000) 375000 de nregistrri (ultima comand din an: 400000) 100000 de nregistrri (ultima comand din an: 500000)

tergerea indexului clustered PK_Comanda.

Una din condiiile unei chei primare este aceea de a nu conine valori nule printre valorile sale. Conform comenzii DDL de creare a tabelei Comanda, indexul clustered era realizat pe baza valorilor atributului ce definea cheia primar (atributul CodComanda). n momentul n care se partiioneaz o tabel, indexul clustered obligatoriu va avea n componen atributul pe baza cruia se va face partiionarea. Implicit un index clustered are o singur partiie. Atunci cnd o tabel este mprit pe mai multe partiii, indexul clustered este la rndul su partiionat, fiecare partiie avnd structura B-tree pentru datele din respectiva partiie. n cazul nostru, atributul pe baza cruia se efectueaz partiionarea este DataComanda deci, indexul de tip clustered va trebui s aib n componen i acest atribut.

Totui, cheia primar trebuie s identifice n mod unic o nregistrare dintr-o tabel, iar atributul CodComanda este ideal n cazul tabelei Comanda (n plus de asta, ntre tabela Comanda i tabela LinieComanda este stabilit relaia 1 n). Deci, va trebui s redefinim cheia primar - dar de data aceasta vom avea grij ca indexul cheii primare s fie nonclustered. Indexul cheii primare l vom gzdui n filegroupul SECONDARY 2 (indexul nu va putea fi partiionat deoarece nu are n componena sa atributul DataComanda).

Indexul realizat n urma redefinirii cheii primare va avea o selectivitate ridicat - deci, n cazul operaiilor SELECTSQL, SGBD-ul va prefera s se foloseasc de acest index (n special n cazul jonciunilor cu tabela copil LinieComanda). Avnd n vedere c acest index nu l putem partiiona pe mai multe partiii, se recomand gzduirea lui ntr -un filegroup dedicat (filegroup ale crui fiiere s fie gzduite pe discuri cu performane ridicate n privina operaiunilor scriere/citire). Pentru acest exemplu am decis gzduirea lui n filegroupul SECONDARY2 (deoarece tabelele Comanda i LinieComanda vor fi partiionate i vor "face loc", permind astfel s transformm filegroupul SECONDARY 2 ntr un filegroup dedicat indecilor). Urmtorul pas const n crearea indexului clustered, moment n care va avea loc i mutarea datelor din filegroupul SECONDARY2 n filegroupurile schemei de partiionare PartitionComanda (deci procesul de recreare a indexului va fi ceva mai costisitor n privina consumului de resurse).

Am s fac o mic discuie pe baza acestui index. Este evident de ce anume am ales atributul DataComanda n componena indexului clustered, dar oare o combinaie de atribute (care s includ i atributul CodComanda) nu ar fi mai avantajoas? Rspuns: Depinde! Depinde foarte mult de scopul tabelei partiionate, de tipul de operaii care se execut asupra datelor respectivei tabele, de frecvena lor, etc. Indecii mbuntesc considerabil accesul la date (SELECT-SQL), dar dac e s cdem n extrema crerii multor indeci, eventual indexarea pe baza unui numr mare de atribute, etc., cu siguran vom reduce performanele operaiunilor INSERT, UPDATE, DELETE, BULK INSERT, BCP. S presupunem c am fi ales combinaia de atribute CodComanda, DataComanda.

Cel puin pe baza frazelor SELECT SQL ale cror performan a fost testat n cadrul acestui post, cu siguran acest index nu ar aduce niciun fel de imbuntiri interogrilor, asta deoarece indexul nonclustered PK_Comanda creat n urma redefinirii cheii primare va avea o selectivitate mai ridicat dect IDX_Comanda. Redefinim constrngerea referenial FK_LinieComanda_Comanda (care am fost nevoii s o tergem nainte de a redefini indexul clustered al tabelei Comanda).

Vizualizm modul n care tabela Comanda a fost partiionat.

Partiionarea tabelei LinieComanda Intenionat am ales aceast structur a tabelelor bazei de date - pentru uurina exemplificrii i nelegerii, abordarea unor aspecte particulare, precum i discutarea cazurilor generale. Pn n acest punct am reuit de am partiionat tabela Comanda (tabela printe tabelei LinieComanda). Logic ar fi s efectum i partiionarea tabelei LinieComanda astfel nct s respectm regula impus de la bun nceput (reorganizarea nregistrrilor per ani), ns atributele tabelei LinieComanda nu au n componen un atribut de legtur cu Comanda.DataComanda.

Totui, dac ne uitm mai atent asupra modului de organizare a nregistrrilor din tabela LinieComanda, putem spune c nregistrrile sunt ordonate ascendent pe baza atributului LinieComanda.CodComanda - acest lucru se datoreaz faptului c ordinea de inserare a nregistrrilor din tabela LinieComanda coincide cu ordinea n care au fost inserate nregistrrile n tabela Comanda. Dac e s privim din punct de vedere tranzacional, o comand (sub form de nregistrri ale unei baze de date) ar fi compus:

dintr-o nregistrare n tabela Comanda (nregistrare identificat prin CodComanda - valoare atribuit secvenial de SGBD); una sau mai multe nregistrri n tabela LinieComanda (nregistrri identificate prin combinaia de atribute CodComanda, CodProdus).

ntre DataComanda i CodComanda exist o relaie dat de faptul c nregistrrile asociate comenzilor sunt introduse n ordine cronologic, iar atributul CodComanda este incrementat la fiecare nregistrare adugat. Altfel spus, pe baza atributului DataComanda pot calcula ultima comand din an. Bingo! Pe baza ultimei comenzi din an voi putea defini funcia i schema pe baza creia voi putea partiiona tabela LinieComanda.

Deci conform rezultatului obinut putem afirma c tabela LinieComanda va fi partiionat astfel: Partiia numrul 1 2 3 Minimum Maximum Detalii

25000 9223372036854775808 25001 400001

121427 de nregistrri (corespunztoare comenzilor din 2008) 1819069 de nregistrri (corespunztoare comenzilor 400000 din 2009) 486420 de nregistrri (corespunztoare comenzilor 9223372036854775807 din 2010)

10

Vizualizm modul n care tabela LinieComanda a fost partiionat.

Dup ce am efectuat partiionarea celor dou tabele (Comanda i LinieComanda), am verificat din nou viteza de execuie a celor dou interogri SQL. Interval execuie (secunde) Inainte de partiionare Dupa partiionare Totalul vnzrilor produselor comercializate n 2009 13 4 Totalul vnzrilor produselor comandate n 2009 7 3 Fraza SELECT-SQL Grafic, organizarea fiierelor i tabelelor bazei de date COMANDA ar putea fi prezentat astfel:

11

Pentru a nu crea confuzie filegroupul SECONDARY2 gzduiete indexul PK_Comanda, dar n imaginea alturat este prezentat doar organizarea fiierelor i tabelelor bazei de date COMANDA.

Extinderea schemei de partiionare (exemplul 1) Schema de partiionare poate fi modificat ulterior. n cele ce urmeaz am s prezint un prim exemplu de extindere a schemei de partiionare. S prespunem c ne aflm n anul 2011 i dorim s crem nc un filegroup pentru a stoca nregistrrile anului calendaristic 2011.

12

S listm noile modificri aduse partiiei PartitionComanda.

ns nu este suficient doar a modifica schema de partiionare. Pentru a salva nregistrrile din 2011 n filegroupul SECONDARY6, trebuie s modificm i funcia de partiionare.

Listm noile modificri aduse partiiei PartitionComanda.

13

Conform listing-ului putem spune c noua partiionare va arta astfel: Partiia numrul Minimum Maximum 1 0001-01-01 00:00.0000000 2008-12-31 23:59:59.9999999 2 2009-01-01 00:00.0000000 2009-12-31 23:59:59.9999999 3 2010-01-01 00:00.0000000 2010-12-31 23:59:59.9999999 4 2011-01-01 00:00.0000000 9999-12-31 23:59:59.9999999 Trebuie s aducem modificri i partiiei PartitionLinieComanda astfel nct nregistrrile asociate comenzilor din 2011 s fie salvate n filegroupul SECONDARY6. Lund n calcul c "ne aflm" n anul 2011 i avnd n vedere modul n care datele sunt salvate n tabela LinieComanda, putem calcula care este ultima comand din anul 2010, iar n funcie de valoarea obinut se va modifica funcia de partiionare PartitionLinieComandaByCodComanda.

14

Deci, toate comenzile ale cror CodComanda este mai mare de 500000 vor aparine comenzilor create ncepnd cu anul 2011.

S listm noile modificri aduse schemei i funciei de partiionare.

Testm modificrile adugnd ceva nregistrri pentru anul 2011.

15

Verificm dac am efectuat partiionarea aa cum ne-am propus.

Extinderea schemei de partiionare (exemplul 2) Din cauza numrului mare de comenzi nregistrate n perioada anului 2009, se ia decizia de a extinde schema de partiionare (comenzile anului 2009 s fie distribuite pe dou partiii).

16

Verificm dac am efectuat partiionarea aa cum ne-am propus.

Restrngerea schemei de partiionare Se ia decizia de a unifica toate comenzile nregistrare n perioada anului 2009 ntr-o singur partiie (a anula modificrile aduse n exemplul 2)

Verificm dac am efectuat partiionarea aa cum ne-am propus.

Renunarea la partiionare

17

Se ia decizia de a renuna la partiionare i de a aduce datele la forma iniial (mutarea tabelelor n filegroupul SECONDARY2).

Recomandri

nainte de a efectua partiionarea asigurai-v c avei copii de siguran. nainte de a efectua partiionarea trecei baza de date n SINGLE_USER (la final, dup partiionare, trecei baza de date n modul MULTI_USER). Avnd baza de date n modul SINGLE_USER vom fi siguri c doar o singur conexiune poate fi iniiat cu respectiva baza de date (evident, respectiva conexiune va fi cea folosit de administratorul SGBD-ului i va fi folosit la partiionare). Dac trebuie s definii mai multe funcii de partiionare, ncercai s definii toate funciile doar cu limit la stnga, sau doar cu limit la dreapta. Recomand acest lucru din simplul motiv c de foarte multe ori suntem nevoii s partiionm pe aceleai filegroupuri att tabele printe ct i tabele copil (asemeni exemplului nostru), iar atunci cnd schema este extins, s putem pstra sincronizarea (ex: nregistrrile tabelei Comanda din 2008 i nregistrrile LinieComanda din 2008 n acelai filegroup, nregistrrile tabelei Comanda din 2009 i nregistrrile LinieComanda din 2009 n acelai filegroup, etc.). Partiionai tabelele cu un numr foarte mare de nregistrri (sau cele care vei ti c vor avea multe nregistrri). Analizai interogrile nainte de a ncepe partiionarea. O soluie ar fi analiza cache -ului. Dac v ateptai la modificri repetate asupra atributului pe baza cruia s-a definit schema de partiionare, se recomand alegerea unor intervale mai mari de partiionare (intervale care s nu determine mutarea efectiv a datelor dintr-un filegroup n altul).

18