pirmdiena, 2010. gada 29. novembris

Indeksu fragmentācija

Indeksu fragmentācija nav vislielākā problēma strādājot ar indeksiem. Tomēr atsevišķās situācijās tas var būtiski (atkarībā no situācijas) ietekmēt ātrdarbību. Šajā rakstā aprakstīts kas ir iekšējā un ārējā fragmentācija, dots teorētiskais skaidrojums. Doti ieteikumi kā minimizēt ārējo fragmentāciju (iekšējās fragmentācijas novēršana aprakstīta rakstā- Indeksu apkope).

Ārējā fragmentācija

Ārējā frgmentācija ir fragmentācija failu līmenī.
Nedomājot par datu bāzēm- ja datorā ieraksta lielu filmas failu (protams, legālu), tad realitātē fails datora cietajā diskā netiek glabāta  kā secīga bitu virkne. Ļoti iespējams, ka pirmie 100 mb fiziski glabāsies vienā vietā kamēr pārējie 500 mb glabāsies pavisam citā. Tikpat labi šo daļu var būt tūkstošiem (realitātē gan parasti OS to mēģina darīt pēc iespējas racionāli).
Domājot par datu bāzēm- Datu bāzes fails ir gandrīz kā visi citi faili- arī datu bāzes fails var tikt sadalīts fragmentos.
Labākais ko varam darīt: 
* pareizi izvēlēties datu bāzes sākotnējo izmēru un augšanas soli- jo tuvāk realitātei, jo labāk. Pēc noklusējuma datu bāze sākumā tiek veidota kā 3 MB fails ar 1 MB automātisko augšanas soli- tātad kamēr sasniedz pāris GB, fails potenciāli var izveidot daudz, daudz mazu daļu.
* tieši tas pats arī ja datu bāzei tiek uzstādīts lai tas tiek samazināta (brīvā vieta var nebūt faila beigās).

Iekšējā fragmentācija

Iekšējai fragmentācijai var izdalīt vairākus veidus/līmeņus.
* Tabulu līmenī
* Extents (1 Extent = 8 lapas, par to var palasīt- Datu glabāšana SQL Server) līmenī
* Lapu līmenī.

Jebkurā no šiem veidiem/līmeņiem fagmentācijas ideja ir līdzīga.
* Tabulai augot. Rakstā Datu glabāšana SQL Server tika minēts- dati SQL server tiek glabāti lapās. Tabulai sākotnēji tiek piešķirta atmiņa vienai lapai, kad tā ir pilna, nākamai līdz tabula sasniedz 8 lapu (= 1 Extent) līmeni. Pēc tam jau tiek piešķirta vieta Extent (8 lapu) izmērā. Un tā kā parasti dati tiek ievietoti vairākās tabulās, tad arī piešķirtie atmiņas apgabali datu bāzes failā nav secīgi.
* Tabulā mainot datus. Principā jau tā arī ir tabulas augšana, tomēr ar šo vēlos uzsvērt lapas dalīšanās nozīmi. Rakstā Tabulas ar klusterētu (clustered) indeksu aprakstīta datu lapu dalīšanās (un dods arī Piemērs: Lapu dalīšanās (Page splits)). Lapu dalīšanās var rasties gan datu ievietošanas gan arī datu mainīšanas gadījumos.
Atgādināšanai ilustrācija kur redzama situācija pēc lapu dalīšanās:

Lai arī ievietotā lapa ir loģiski pareizā secībā, tomēr fiziski uz diska šī lapa var atrasties jebkur datu bāzes faila vietā.
fragmentācijas līmeni var apskatīt kā aprakstīts rakstā Informācijas par indeksiem apskatīšana. uzmanībā jāpievērš lielumie avg_fragmentation_in_percent, fragment_count, avg_fragment_size_in_pages. Ja zinām kopējo lapu skaitu un fragmentu skaitu, tad uzminēt pārējos lielums arī varam.

Pāris 'āķi'
  • Ar ārējo fragmentāciju var cīnīties kārtīgi apdomājot datu bāzes izmēru, defregmentējot disku pirms faila izveides, pirms datu bāzes izmēra samazināšanas trīsreiz padomājot kas notiks (brīvā vieta datu bāzē fiziski var būt datu bāzes vidū).
  • Iekšējā fragmentācija ir ļoti slidena lieta!
    • Ja viena Extent līmenī esošās lapas nav sakārtotas pareizā secībā, tad indeksu defregmentācija noteikti šo situāciju uzlabos. Savukārt ja datu bāzes failā Extents nav pareizā secībā, nekur nav teikts, ka defregmentācija palīdzēs!
      (Principā ja grib lai datu bāze būtu ideāla- vajag uz jauna diska bez fragmentācijas izveidot datu bāzes failu maksimālā nepieciešamā izmērā. Tad visus datu bāzes indeksus (klusterētos un neklusturētos) pārvietot uz jauno datu bāzes failu vienlaicīgi tos sakārtojot pareizā secībā, novēršot visu fragmentāciju- un tas strādā tikai līdz nākamajām datu mainīšanas operācijām, kas var izsaukt lapu dalīšanos vai lapu pievienošanu ārpuss pareizās fiziskās secības.
      Šo neesmu mēģinājis un visdrzāk nemēģināšu izpildīt.. Tas ir pārāk laikietilpīgi un.. izlasot nākamo punktu..
      )
    • Fragmentācija pati par sevi var neiespaidot ātrdarbību. Kādēļ nē?
      • Augsta fragmentācija traucē, ja jānolasa secīgi dati. Tas nozīmē- ja jānolasa 100 datu lapas pēc kārtas (piemēram, klusterētais indeks), bet tās nav fiziski pareizā secībā, tad diska galviņai ir daudz jālēkā pa disku un tas kavē procesu.
        (Agrāk bija raksts, kurā tika pieminēts bet netika paskaidrots, kas ir "Read-ahead reads"- Vaicājuma statistika. Ja vaicājumam ir daudz šo "Read-ahead reads", tad augsta fragmentācija šo daļu "salēninās". Tikai jāņem vērā, ka šīs nolasīšanas operācijas ir tikai tad, kad datus lasa no diska! Visdrīzāk (garantēt nevaru- atkarīgs no daudzām dažādām lietām) izpildot to pašu vaicājumu uzreiz otreiz, "Read-ahead reads" būs pazuduši, jo dati jau būs pieejami no operatīvās atmiņas!)
      • Bet (!) jo mazāks un biežāk izmantots indekss, jo lielāka varbūtība, ka tas atradīsies operatīvajā atmiņā un defragmentācija vispār neatstās nekādu iespaidu!
      • Un (!) jo mazāk secīgu lapu mums vajag, jo mazāk tas iespaido ātrumu! Principā tā kopsakarība ir tāda, ka OLTP sistēmām (kurām daudz mazu transakciju) fragmentācija drīzāk neatstāj pārāk sliktu iespaidu.
Kopsavilkums

Ņemot vērā "Par" un "Pret" visdrīzāk lielākajā vairumā gadījumu fragmentācija nav primārais kam jāpievērš uzmanība pētot indeksus. Tomēr fragmentāciju iespaido arī lapu dalīšanās- tāpat kā iespaido lapu "pilnumu".
(lapu dalīšanās teorija rakstā tabulas ar klusterētu (clustered) indeksu un dots arī piemērs: Lapu dalīšanās (Page splits)).
Cīnoties ar vienu problēmu (kā cīnīties būs aprakstīts kādā no nākamajiem rakstiem), mēs reāli cīnāmies ar abām. Tiesa gan, kā minēts, fragmentāciju pilnībā novērst ir visai grūti.
Principā šī ir nianse, kas kādreiz var noderēt.

Papildus literatūra

2 komentāri:

  1. Nu vēl runājot par ārējo fragmentāciju - puslīdz nopietnām sistēmām tie laiki, kad rūpējās par to kā kurš datu bloks uz diska izvietots, ir diezgan sen garām, visādiem disku masīviem neviens vairs no opsistēmas neko nespēj nokontrolēt, kur tas bloks reāli noliksies, saprātīgāki masīvi paši spēj darīt visādas lietas, piemēram:
    1) dinamiski optimizēt fizisko datu bloku izvietojumu tā, lai noslodze būtu izlīdzināta pa fiziskajiem diskiem
    2) izmantot visādas read ahead metodes, kur nekādām diska galvām nekur vairs nav vienādi otrādi jālēkā
    utt.
    Un kā jau rakstīji, indeksu fragmentācija, piemēram, pie datu izmaiņām ir dabisks process, tas ir tāpat kā cīnīties ar vējdzirnavām. Un jēga ar to ir cīnīties tikai tad, ja patiesi ir noskaidrots, ka fragmentācija ir problēma.

    AtbildētDzēst
  2. Jā, par ārējo fragmentāciju pilnīgi piekrītu- tas arī rakstiņā pieminēts.
    Par iekšējo fragmentāciju- brīžiem var samulst, jo tur kur ir atsauces uz indeksu "pilnumu"- tas tiek dēvēts arī par iekšējo fragmentāciju. Iespējams tāpēc, ka cēloņi ir vieni un tie paši abām lietām. Savukārt indeksu "pilnums" ir būtiska lieta un ar to cīnās tāpat kā ar fragmentāciju- pārbūvējot indeksu (Par to vēl neesmu uztaisījis rakstiņu). Un tajā gadījumā esmu redzējis kā pēkšņi milzīgs apjoms time-out pārtop normāli funkcionējošā sistēmā. piemēram- ja indeksu lapu "pilnums" ir 40% (ekstrēms piemērs, bet ne neiespējams), tad sanāk ka 40 lapu vietā ir jānolasa 100 (pārlasot indeksu), tātad - 60*8KB lieka lasīšana..

    AtbildētDzēst