MySQL profiler

februāris 23, 2009

Es ik pa laikam iedomājos vai MySQLā arī var lietot līdzīgas iespējas, kā piemēram Oracle autotrace, lai varētu mērīt izpildes laiku, paveiktos soļus un kaut kādu statistiku vaicājumiem, un lai salīdzinātu, kas tad izpildījās ātrāk un kāpēc. Tad nu izrādās, ka jau vismaz kopš 2007. gada pavasara eksistē tāda lieta, kā MySQL profiler, kas lielā mērā to nodrošina. Jau pašā sākumā jābrīdina, ka MySQL ir visai dīvaina DBVS un visai dīvainas izstrādes metodes vismaz no mana skatupunkta, jo pirmkārt MySQL Profiler nav pieejams MySQL Enterprise Server un notiek arī tāda mistiska dīvainība, ka vecākās versijās ir, bet jaunākās nē, piemēram, 5.0.37 ir, bet 6.0.4 nav (uz to arī es uzrāvos un brīnījos kā gan tas nākas), savukārt pēdējā novelkamajā 6.0.9. alpha atkal ir. Tā kā iespējams ne visiem lietotājiem būs tā iespēja šo rīku arī izmantot. Vēl tāds interesants fakts, ka šajā brīdī meklējot Googlē MySQL profiler latviskās lapās (tas ir pirms šī raksta, ko pašlaik lasat, publicēšanas) tiek atrasti 17 rezultāti, no kuriem tieši 1 ir kādā sakarā ar meklēto frāzi.

Kā jālieto?

Profiler sākšana un beigšana ir ļoti vienkārša. Lai sāktu, rakstam:

mysql> set profiling=1;
Query OK, 0 rows affected (0.00 sec)

Lai beigtu, rakstam:

mysql> set profiling=0;
Query OK, 0 rows affected (0.00 sec)

Lai noskaidrotu, kādā stāvoklī esam:

mysql> select @@profiling;
+-------------+
| @@profiling |
+-------------+
|           0 |
+-------------+
1 row in set (0.00 sec)

Ko ar to var redzēt?

Lasīt pārējo šī ieraksta daļu »


7 lietas, ko nevajag darīt

janvāris 23, 2009

Arī mani ir sasniegusi sērga par 7 lietām, kas neesot par mani zināmas. Bet nu nekā nebija, es šeit netaisos pagaidām apspriest savas privātās lietas vai kaut ko tādu, kas pārāk tālu attālinās no datubāzēm un ar to saistīto. Ja vien mani nenovedīs līdz tam briestošo priekšvēlēšanu laikā 😉 Bet tagad nē. Tagad Jums būs 7 lietas saistītas ar datubāzes ātrdarbību (faktiski lēndarbību), ar kurām visām  es pašlaik cīnos vai man ir nācies cīnīties un par kurām varu izteikties tikai [cenzēts], [cenzēts], [cenzēts].

  1. Nelietojiet SQL vaicājumos lietotāja definētas (user-defined) funkcijas. Nelietojiet tās lieliem datu apjomiem. Vēl vairāk nelietojiet tās, ja tajās atkal kaut kas tiek lasīts no datubāzes. Un tas attiecas tikpat labi uz Oracle, kā uz SQL serveri. Izbaudu to uz savas ādas gandrīz katru reizi, kad nākas cīnīties ar bremzīgiem Select vaicājumiem. Kāpēc? Oracle tas ir tāpēc, ka vaicājums tiek nosacīti izpildīts zem SQL dziņa (SQL engine), savukārt jebkurš lietotāja definēts funkcijas izsaukums prasa PL/SQL dzini (PL/SQL engine) un mētāšanās no viena uz otru ir relatīvi dārgs process. To pašu esmu novērojis SQL Server, nezinu precīzu tehnisku skaidrojumu, bet tā vien izskatās, ka tur ir kaut kas ļoti līdzīgs.
  2. Nelasiet no datubāzes liekus datus. Nerakstiet SELECT * no 50 tabulām (jā 50!), rakstiet tikai tās kolonas no tām tabulām, ko Jums vajag. Tas ir pilnīgs ārprāts, ja Jūs atlasat 80 kolonas, jā 80! un pēc tam attēlojat 10. Un tas viss tikai tāpēc, ka šis vaicājums tagad derēs visās 17 vietās, kur Jums kaut ko no tā vajag attēlot. Autors par laimi (viņam) bija jau atlaists, citādi tas noteikti beigtos ar asinsizliešanu 😉
  3. Nekārtojiet liekus datus. Ja nu ir jākārto (ORDER BY) kādi dati, tad vienmēr raugieties, lai kārtojamo kolonu skaits nebūtu vairāk nekā nepieciešams. Nerakstiet SELECT * ORDER BY <1, 2, 3 kolonas>, ja izrādās, ka * nozīmē 20 kolonas no kurām tālāk Jūs lietojat tikai 10. Katra lieka kolona ir lieki dati, kas datubāzes serverim jātur atmiņā un jāvazā līdz kārtošanas laikā. Tā ir papildus atmiņa, papildus apstrādes laiks un bezjēdzīgi iztērēti resursi.
  4. Neatlasiet unikālās kolonas (DISTINCT jeb UNIQUE) tikai tāpat vien, drošības pēc. DBVS nezin, ka tas ir tikai tāpat, aiz nekā darīt. Ja tas patiesi ir pārāk bieži nepieciešams, tad diezgan droši tā ir kļūda datubāzes modelī. Kāpēc to nevajag? Tāpēc, ka katrs DISTINCT prasa unikālo ierakstu atlasi un jo vairāk kolonas tiks atlasītas, jo vairāk atmiņas un resursu tam būs nepieciešami. Ja tas ir izdarīts uz ierakstu kopu, kas jau tāpat ir ar unikāliem elementiem, tad tie ir burtiski zemē nomesti CPU cikli, atmiņas operācijas un iespējams pat diska apgriezieni.
  5. Nerakstiet dinamisko SQLu ar iešūtām mainīgo vērtībām. Datu bāzu vadības sistēmās (Oracle, MS SQL Server), kuru izstrādātāji ir ilgi pūlējušies, lai izveidotu kopīgu atmiņas apgabalu visiem SQL teikumiem (attiecīgi shared pool un procedure cache), maz kas var būt paradoksālāk kā nezinoši vai piedodiet par izteicienu stulbi izstrādātāji, kas katru savu SQL teikumu uzģenerē ar iešūtām mainīgo vērtībām, līdz ar to visus sākotnējos pūliņus izslaukot miskastē. Iešūtas mainīgo vērtības nozīmē praktiski nulles varbūtību, ka izveidotais SQL teikuma izpildes plāns būs lietojams arī nākošajam lietotājam, jo viņa SQL teikums būs gandrīz tāds pats, bet tikai gandrīz. Tajā atšķirsies iešūtie identifikatori vai arī kādi citi mainīgie un hopsā – tas vairs nav tas pats SQL teikums, kuram izpildes plāns jau bija zināms. Tā ir viena no tūkstoš hidras galvām, kam atkal jāpārbauda tiesības uz objektiem, jāģenerē savienojumu iespējamās kombinācijas un viss SQL teikuma izpildes plāns. Sīkums vienam lietotājam, kas reizi pusstundā palaiž SQL teikumu uz 15 minūtēm, bet nežēlīga sāpe kaut vai 10 lietotājiem, kuri katrs izpildītu desmitiem vai pat simtiem SQL teikumu sekundē, ja vien katram SQL teikumam nebūtu analīzes (parse) fāze, kas konstanti aizņem sekundi…
  6. Nelietojiet procedurālo valodu ciklus, lai apstrādātu ierakstus pa vienam, jo sevišķi, ja iterāciju skaits ir proporcionāls datu apjomam. Visizplatītākā lieta – kursori. Mans mazais skaistais kursoriņš, kurš izpildās zibenīgi uz dažiem ierakstiem, pārvēršas par milzīgu nekustīgu monstru, ja tas tikpat akli dodas caur reālajiem produkcijas miljons ierakstiem. Cikli, kuru iterāciju skaits ir tieši proporcionāls datu daudzumam nav savienojami ar vārdu ātrdarbība. Tie var būt tikai un vienīgi atbilstoši vārdam lēndarbība.
  7. Testējiet uz reālu datu apjomu, kādu Jūsu sistēma sasniegs pēc gada, diviem. Tas, ka Jūsu vaicājums izstrādes vidē uz 10 ierakstiem atgriež funkcionāli pareizu rezultātu zibenīgi ir nekas. Burtiski nekas. Sliktākajā gadījumā saģenerējiet datus pats, ja esošus reālus daudz nevar dabūt. Jo tad, kad Jūsu vaicājums sastapsies ar miljons ierakstiem, kam nāksies katram izsaukt lietotāja definētu funkciju, nolasīt visu ierakstu 50 kolonas, visu miljonu sakārtot dēļ liekā Distinct, un to darīs vismaz 10 lietotāji vienlaicīgi palaižot jūsu dinamiski ģenerēto SQL teikumu, lūk tad iestāsies brīdis, kad klients pacels cepuri un dosies pie Jūsu konkurentiem. Jo diemžēl lielāks dzelzis nederēs. Neviens dzelzis pie kaut cik ievērojama datu apjoma nespēj pārciest šeit uzskaitīto, tā lai lietotāji nesāktu dusmās vārīties un klusiņām lādēt izstrādātāju.

Man principā diez ko nepatīk visādas ķēdes un piramīdas, galu galā Medofs arī slikti beidza 🙂 , taču gribu pievērst lasītāju uzmanību vienam visnotaļ interesantam un (cerams, ka arī turpmāk) daudzsološam blogam, kurš raksta arī par lietām, kas saistās ar tīmekli un ātrdarbību.

Lasīt arī:


MySQL performance tuning seminārs

septembris 20, 2008

Šo sestdien Rīgā bija Software freedom day, kas notika LU Linux centrā un par ko informēju jau iepriekš. Pirms došanās uz pasākumu izjutu nelielu skepsi, jo pierakstīšanās procesā uz MySQL ātrdarbības skaņošanas semināru valdīja mērens bardaks, tas ir, sākumā tas bija kā visiem pieejams, tad pazuda, tad atkal uzradās, kā arī visu laiku mainījās semināra sākuma laiks, piedevām pēdējo izmaiņu piefiksēju tikai tāpēc, ka nejauši vēlreiz iepētīju pasākumu plānu. Bet nu “viss labs, kas labi beidzās”, un pasākums izvērtās gana interesants.

Semināru vadīja Jay Pipes un slaidi bija tāds kā apkopojums no viņa pēdējām abām prezentācijām, kas redzamas viņa mājaslapā Legend of Drunken Query Master: The Apprentice’s Journey un Join-fu: The Art of SQL – ZendCon 2008. Tātad tie, kas seminārā tādu vai citādu iemeslu dēļ nepiedalījās, var vismaz paskatīties galvenās idejas no tām. Lielākais pluss, protams, bija iespēja uzdot jautājumus un saņemt kompetentas atbildes. Ašākais no klausītājiem, kas pareizi atbildēja uz Jay Pipes jautājumu, savā īpašumā ieguva grāmatu High Performance MySQL, Second Edition. Vēl jāpiebilst, ka semināra pasniedzējs arī ir līdzautors grāmatai Pro MySQL.

Dažas pasākuma bildes var redzēt šeit.

Tā kā neesmu nekāds baisais MySQL specs un lietoju to tā sakot brīvajos brīžos, tad iespējams, ka mani iespaidi ir mazliet savādāki nekā tie, kas būtu radušies MySQL ikdienas lietotājiem, bet daži no tiem bija šādi:

  • Tika atgādināts par to, ka MySQLā ir daudz un dažādi tabulu tipi un tas, ka Jūs izmantojat tikai vienu no tiem, visdrīzāk nozīmē, ka Jūsu aplikācija nedarbojas optimāli. Ko tur piebilst, tieši tāpat ir arī, piemēram, Oraclē, bet cik vispār zin, ka Oraclē ir vairāki tabulu tipi, nemaz nerunājot par to, ka ir arī tos lietojuši?
  • Atgādināts, ka visa pamatā ir shēma un, ja tā ir izveidota neoptimāli, tad tādi būs arī Jūsu vaicājumi, un neviens pasaules optimizators Jums neko daudz nepalīdzēs. Atliek tikai piekrist.
  • Diezgan smagi tika spiests uz piemērotu minimālu datu tipu pielietošanu, lai vienā datu blokā pēc iespējas vairāk sapakotu ierakstus.
  • Vertikālā particionēšana – ja Jūsu tabula satur daudzas kolonas, no kurām tikai dažas tiek bieži izmantotas, tad sadalīt tabulu divās – vienā ar bieži izmantotajām kolonām, otrā attiecīgi retāk izmantotās, lai nepiesārņotu kešu. Tehnika, kuru nekur citur tā īsti neesmu redzējis iesakam, ja neskaita kādus ekstrēmus gadījumus ar blobu un clobu likšanu atsevišķās tabulās, lai tās neafektētu pamattabulas.
  • Atgādinājums par MySQL vaicājumu kešu (query cache), kurš noklusēti ir 0. Kešošanas algoritms gan ar nekādu dziļu inteliģenci neizceļas tāpēc jābūt uzmanīgam ar vaicājumu kešošanu, kas darbojas uz mainīgām tabulām.
  • Atgādinājums un piemērs par to, ka rakstot SQL jādomā kopās nevis ierakstos (think in sets not in rows). Atbalstu ar abām rokam un kājām!
  • Īss pārskats par Explain komandu un tās doto rezultātu.

Bija, protams, ne tas vien, bet ne jau visu var atcerēties un šo to no pārējā var redzēt augšminētajās prezentācijās. Pārskatot tagad slaidus, man piesaistīja uzmanību šajā uz beigām parādītās atskaišu iespējas kā ar vienkāršu SQLu (savienojumi un grupēšanas) iegūt sakārtojumus un tekošās summas (running total). Lai gan seminārā Jay Pipes teica, ka neko nezinot par analītiskajām funkcijām, šie ir tipiski analītisko funkciju piemēri, tikai realizēti bez tām. Atliek tikai piebilst, ka izmantojot analītiskās funkcijas, šos SQL teikumus varētu vismaz 3 reizes saīsināt 😉


Autotrace

janvāris 30, 2008

Turpinot tēmu par ātrdarbības meklējumumiem Oracle datubāzēs šoreiz paskatīsimies uz SQL*Plus rīka komandu autotrace. Tā jau dod vairāk informācijas nekā vienkārši patērētais laiks, ko var noskaidrot vairākos veidos.
Jāpiebilst gan, ka izpildes plānu un statistiskos rādītājus izmantojot autotrace ir iespējams dabūt tikai DML teikumiem – SELECT, INSERT, UPDATE, MERGE, DELETE.
Tātad par visu pēc kārtas:

Autotrace priekšnosacījumi

Lai varētu pilnvērtīgi izmantot šo SQL*Plus komandu, ir divi priekšnosacījumi:

  • Lietotājam jābūt iedotai PLUSTRACE lomai. Lomas izveides skripts atrodas $oracle_home\sqlplus\admin\plustrce.sql, kur $oracle_home ir direktorija, kur uzinstalēta Oracle datubāze.
  • Lietotājam jābūt pieejamai tabulai PLAN_TABLE. Tā var būt uzinstalēta kādā datubāzes lietotāja shēmā un iedotas tiesības visiem pārējiem lietotājiem, vai arī katra paša lietotāja shēmā, tas nav svarīgi. Tabulas izveides skripts atrodas $oracle_home\rdbms\admin\utlxplan.sql . Vajadzētu lietot tieši konkrētajai Oracle versijai paredzēto tabulu tāpēc, ka katrā nākošajā versijā parasti nāk klāt jaunas kolonas.

Autotrace iespējošana/atspējošana

  • SET AUTOTRACE OFF  – autotrace atskaite netiek ģenerēta. Normālā situācija.
  • SET AUTOTRACE ON EXPLAIN  – autotrace atskaite parāda tikai izpildes plānu.
  • SET AUTOTRACE ON STATISTICS – autotrace atskaite parāda tikai SQL teikuma izpildes statistiku.
  • SET AUTOTRACE ON – autotrace atskaite attēlo gan izpildes plānu, gan SQL teikuma izpildes statistiku.
  • SET AUTOTRACE TRACEONLY – autotrace atskaite attēlo gan izpildes plānu, gan SQL teikuma izpildes statistiku, bet netiek attēlots SELECT vaicājuma izpildes rezultāts. Ērti izmantot tad, ja vaicājuma izpildes rezultāts ir liels un mūs neinteresē, bet interesē tikai izpildes plāns un statistika.
  • SET AUTOTRACE TRACEONLY EXPLAIN – autotrace atskaite attēlo izpildes plānu, bet netiek attēlots vaicājuma izpildes rezultāts. Ja tas ir SELECT teikums, tad šajā gadījumā patiesībā SQL SELECT teikums NETIEK izpildīts.
  • SET AUTOTRACE TRACEONLY STATISTICS – autotrace atskaite attēlo SQL teikuma izpildes statistiku, bet netiek attēlots vaicājuma izpildes rezultāts.

Dažas lietas, ko vērts atcerēties:

  • INSERT, UPDATE, DELETE, MERGE teikumi tiek reāli izpildīti vienmēr, bet SELECT teikums patiesībā netiek izpildīts, ja ir SET AUTOTRACE TRACEONLY EXPLAIN. Šis variants reizēm ir noderīgs, ja select teikums izpildās stundu, bet mēs gribam redzēt tikai izpildes plānu. Kā arī reizēm rodas nesapratne – kāpēc, ja ir SET AUTOTRACE TRACEONLY EXPLAIN, tad select teikums izpildās zibenīgi, bet citādi iet stundu? Atbilde tātad – select pieprasījums patiesībā netiek izpildīts, tiek uzģenerēts tikai izpildes plāns.
  • Nelietot autotrace SYS lietotājam. Šis lietotājs ir īpašs un šim lietotājam autotrace atskaite nav izmantojama.
  • Autotraces rezultātā iegūtais SQL pieprasījuma izpildes plāns var nebūt īstais, kas patiesībā ir jūsu programmā. Vairumā gadījumu izpildes plāni sakrīt un ir vienādi, bet var būt gadījumi, kad tas tā nav, piemēram, ja atšķiras vides uzstādījumi sesijām (izdalītā atmiņa utml). Otrs iemesls, kad izpildes plāni var atšķirties ir tad, ja jūs lietojat BIND mainīgos un Oracle datubāze reālā vaicājuma izpildes plāna ģenerēšanas laikā pirmajā reizē skatās uz doto mainīgo vērtībām. Autotrace ģenerējot SQL vaicājuma izpildes plānu to nedara. Piemērs – jums ir tabula ar kolonu, kurā ir viena “A” vērtība un 1000 “B” vērtības. Ja atlasa ierakstu ar “A” vērtību, tad tabulu ir vērts lasīt pēc indeksa, ja atlasa ierakstus ar “B” vērtību, tad tabulu ir izdevīgāk lasīt visu neizmantojot indeksu. Šajā gadījumā autotrace var rādīt vienu izpildes plānu, bet reālais var būt atšķirīgs.

Izmantošanas piemērs

Izmantotā tabula ir šāda: 

CREATE TABLE personas (
  prs_personas_kods VARCHAR2(11) NOT NULL PRIMARY KEY,
  prs_vards VARCHAR2(40),
  prs_uzvards VARCHAR2(40));
INSERT INTO personas VALUES ('11111112345', 'JĀNIS', 'BĒRZIŅŠ');
INSERT INTO personas VALUES ('12121212345', 'PĒTERIS', 'SŪNIŅŠ');
INSERT INTO personas VALUES ('13131312345', 'RŪDIS', 'BĒRZIŅŠ');
COMMIT;
SQL> set autotrace on
SQL> SELECT * FROM personas WHERE prs_personas_kods = '11111112345';
PRS_PERSONA PRS_VARDS                                PRS_UZVARDS
----------- ---------------------------------------- --------------
11111112345 JĀNIS                                    BĒRZIŅŠ
Execution Plan
----------------------------------------------------------
   0      SELECT STATEMENT Optimizer=ALL_ROWS (Cost=1 Card=1
Bytes=51)
   1    0   TABLE ACCESS (BY INDEX ROWID) OF 'PERSONAS' (TABLE)
(Cost=1 Card=1 Bytes=51)
   2    1     INDEX (UNIQUE SCAN) OF 'SYS_C00112708' (INDEX (UNIQUE))
(Cost=1 Card=1)
Statistics
----------------------------------------------------------
          0  recursive calls
          0  db block gets
          2  consistent gets
          0  physical reads
          0  redo size
        459  bytes sent via SQL*Net to client
        377  bytes received via SQL*Net from client
          1  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
          1  rows processed

Tātad mēs šeit redzam izpildes plānu, kurā tiek parādīts:

  • kādas darbības (SQL vaicājuma izpildes plāns) Oracle DB veic, lai iegūtu rezultātu,
  • kāds ir izpildes plāna un tās soļu izmaksu novērtējums (Cost);
  • kāds ir sagaidāmo ierakstu skaits ko Oracle DB cer iegūt katra soļa rezultātā (Card, no cardinality);
  • kāds ir rezultāta apjoms baitos (Bytes).

Ja Cost, Crad un Bytes nav, tad tas nozīmē, ka jūs izmantojat RBO (rule based optimizer)  un šeit ir rakstīts, kāpēc to nevajag darīt.

Par katru no statistikām vairāk nākošajā sadaļā.
Lai paskatītos, cik grūti ir iegūt visus mums pieejamos objektus no datu vārdnīcas, varam pašus rezultātus neskatīties, bet tikai statistiku.

SQL> set autotrace traceonly statistics
SQL> select * from all_objects;
 61295 rows selected.
Statistics
------------------------------------------------------
       5467  recursive calls
          0  db block gets
     113664  consistent gets
          0  physical reads
          0  redo size
    3032446  bytes sent via SQL*Net to client
      45458  bytes received via SQL*Net from client
       4088  SQL*Net roundtrips to/from client
          1  sorts (memory)
          0  sorts (disk)
      61295  rows processed

Tātad kā redzam, ieraksti rādīti netika, bet statistikas atskaite ir redzama.

Statistiku nozīme

  • recursive calls – rekursīvo izsaukumu skaits (SQL teikumu skaits), ko veic sistēmas vai lietotāja līmenī. Daži no izplatītākajiem iemesliem varētu būt lietotāja definēto funkciju izsaukumi, kas kaut ko dara datu bāzē un sistēmas izsaukumi, lai varētu izveidot SQL Pieprasījuma izpildes plānu.
  • db block gets – bloka nolasīšana current mode. Pārsvarā tas parādās datu koriģēšanā, kad jāmaina tikai bloka pēdējā versija.
  • consistent gets – bloka lasīšana no Oracle DB bufera keša read consistent mode. Pārvarā tas parādās vaicājumos un iekļauj arī bloka iegūšanu no UNDO segmentiem (iepriekšējām bloka versijām atmiņā).
  • physical reads – bloka lasīšana no diska gan izmantojot tiešo lasīšanu, gan bufera kešu. Protams, arī šeit jāatceras, ka ne vienmēr tā patiesi ir lasīšana no diska – jo pastāv vēl gan operētājsistēmas kešs, gan iespējams arī katram diskam ir kaut kāds kešs. Bet no Oracle DB viedokļa tā ir lasīšana no diska.
  • redo size – norāda cik daudz tiek ģenerēts REDO. Pārsvarā attiecas tikai uz datu koriģēšanas teikumiem.
  • bytes sent through SQL*Net to client – no servera uz klienta pārsūtīto baitu skaits.
  • bytes received via SQL*Net from client – no klienta uz servera pārsūtīto baitu skaits.
  • SQL*Net roundtrips to/from client – SQL*Net ziņojumu skaits, kas sūtīts starp datu bāzi un klientu.
  • sorts (memory) – veikto kārtošanu skaits atmiņā.
  • sorts (disk) – kārtošanu skaits, kam ir bijusi nepieciešamība pēc pagaidu vietas uz diska.
  • rows processed – atlasīto (select), pievienoto (insert, merge), koriģēto (update, merge), dzēsto (delete, merge),  ierakstu skaits.

Kam pievērst uzmanību (nosacītā svarīguma dilšanas kārtībā):

  • Pats svarīgākais ir censties samazināt consistent gets un db block gets. Jo tas nozīmē, ka jums mazāk datu būs jālasa no atmiņas, mazāk datu būs jāapstrādā, mazāk būs jāveic atmiņas struktūru skanēšana, kas protams ir ļoti ātra, bet tai pašā laikā prasa nozīmīgus CPU resursus. Nevajadzētu iedomāties, ka “ieraujot visu datu bāzi” atmiņā tiks atrisinātas visas ātrdarbības problēmas. Pie tam samazinot šo statistiku automātiski parasti samazinās arī physical reads. Consistent reads ir atkarīgs arī no tā kāds ir vienā reizē pārsūtīto ierakstu skaits starp datubāzi un klientu un līdz ar to pārsūtīto ziņojumu skaits (SQL*Net roundtrips to/from client) vienam un tam pašam SQL vaicājumam. Jo šis skaits ir lielāks, jo vienam un tam pašam SQL vaicājumam var būt vairāk consistent gets. Katrā vidē to nosaka savādāk, bet SQL*Plusā to nosaka izmantojot komandu SET ARRAYSIZE <skaitlis>.
  • recursive calls visu laiku (ne tikai pirmajā izsaukuma reizē) saglabājas liels skaitlis (simti, tūkstoši). Tas var norādīt uz to, ka vai nu nepārtraukti SQL teikums tiek parsēts atkal un atkal (kas autotraces un vienkārša DML teikuma gadījumā ir neparasti), vai arī tiek izpildītas lietotāja definētas funkcijas, kas var būt paslēptas skatījumā un vispārīgā gadījumā var būt pamatīgs ātrdarbības grāvējs.
  • Liels redo size. Jo lielāks redo size, jo vairāk datu Oracle ir spiesta rakstīt uz diska. Jāatceras, ka katrs indekss, kas datu modificēšanas laikā ir papildus jāuztur, palielina šo metriku.
  • Liels physical reads. Jānoskaidro kāpēc tas tāds ir. Iespējams, ka tas ir neizbēgami – ja jums piemēram ir jānolasa liela tabula un tā ir jānolasa visa, lai iegūtu kādu atskaiti, tad parasti visefektīvākais veids ir to visu arī vienkārši nolasīt.
  • Sorts – mērķis ir samazināt metriku sorts (disk), jo tas nozīmē, ka kārtošana nesatilpst atmiņā. Ir 2 iespējas kā to paveikt – palielināt atmiņu vai samazināt kārtošanu skaitu vispār 🙂

Turpmākā lasāmviela


Kā noskaidrot, kur paliek laiks?

novembris 6, 2007

Virsraksts ir ļoti filozofisks, bet tai pašā laikā ļoti saistīts ar datubāzēm un programmēšanu kā tādu. Ikviens no programmētājiem ir saskāries ar problēmu, ka kods izpildās lēnāk nekā iecerēts vai katrā ziņā vismaz klientam tā šķiet. Tajā brīdī katrs no mums pielieto sev mīļākās metodes ko nu darīt. Daži tūlīt metas pie darba devēja vai klienta un sāk runāt par niknāka dzelža iegādi, daži drudžaini mēģina uzlabot tur kaut ko un šeit kaut ko, ja cilvēks ir veiksmīgs, iespējams tas viņam pat izdodas.
Diemžēl ne visi dzīvē ir veiksminieki un ne visi dzīvē ir tik pieredzējuši, lai ar savu intuīciju vai iepriekšējo pieredzi spētu izdomāt, kur tad šis laiks paliek. Un šajā gadījumā nekas cits neatliek kā izveidot precīzu atskaiti, kur tad laiks tiek pavadīts.
Ja es dzīvoju Jūrmalā (gribētos jau nu gan, bet patiesībā nekā:(), braucu ar mašīnu uz darbu Rīgā un katru rītu ierodos darbā par vēlu, tad ko man darīt? Tīri intuitīvi ko mēs darām? Pareizi – skriešus veicam pēdējos metrus no stāvvietas līdz darbam. Vai tiešām tam ir kāda jēga? Nu neapšaubāmi tam ir sportiska jēga un iespējams arī emocionāla jēga, kad priekšnieks redz, cik ļoti padotais vēlas strādāt. Taču attiecībā pret mūsu galveno mērķi – ierasties darbā ātrāk – jēga ir ļoti maza. Kāpēc? Tāpēc, ka sadalot pa sastāvdaļām mūsu maršruts izskatās apmēram šādi:

  • 5 minūtes, lai no Jūrmalas tiktu ārā;
  • 10 minūtes no Jūrmalas robežas līdz pirmajiem sastrēgumiem Rīgā;
  • 30 minūtes, lai tiktu pāri tiltam līdz darbam;
  • 2 minūtes, lai no stāvvietas uzkāptu pa trepēm un ienāktu birojā.

Pat, ja mēs iemācītos teleportēties no stāvvietas līdz birojam, tas kopējo laiku 47 minūtes samazinātu līdz 45 minūtēm un ietaupījums būtu ~4%. Diez ko iepriecinoši vis neizskatās.
Jūs teiksiet muļķīgi darām, vai ne? Jāminimizē kaut kā tie lielākie laika posmi!
Piemēram, varētu sākt ar 30 minūšu tupēšanu sastrēgumos. Kādas ir iespējas?

  • Izbraukt ātrāk?
  • Izbraukt vēlāk un sarunāt ar priekšnieku, ka mainam darba dienas sākumu un beigas?

Varbūt kļūt radošākiem un “domāt ārpus kastes” (think out of the box)? Piemēram:

  • Iegādāties helikopteru?
  • Mainīt darbu?
  • Mainīt dzīvesvietu?
  • Kļūt par rantjē?

Tieši tas pats attiecas arī uz standarta problēmu, kad programma strādā lēni. Nav haotiski un drudžaini jācenšas veikt kaut kādas maģiskas darbības, kuras palīdzēja Jānim pagājušogad un Pēterim vēl nupat nesen. Nav vērts savas pūles ieguldīt līdz neprātam skaņojot lielu SQL teikumu, kurš izpildās vienreiz un aizņem 5% no kopējā izpildes laika, bet tajā pašā laikā ir viens it kā sīks un necils SQL teikums, kas ciklā izpildās 10 tūkštoš reižu un aizņem 95% laika. Ir vienkārši jānoskaidro, kur laiks tiek patērēts. Jāsastāda atskaite ar darbībām, kas tiek veiktas pēc pogas nospiešanas un katrai šai darbībai jānomēra tās izpildes laiks. Un tad, kad ir skaidrs, kas bremzē un kas aizņem lielāko daļu laika, ir jāķeras pie šīs bremzes novēršanas.
Tikai tad jūs beidzot sapratīsiet, ko patiesībā jūs kods dara 🙂 Tikai tad jūs beidzot sapratīsiet kāda funkcionalitāte vispār zem šīs pogas slēpjas. Tikai tad jūs beidzot droši un precīzi varēsiet pateikt, lai beidz visās nelaimēs vainot Kanādu t.i. datu bāzi, vai arī tieši otrādi ķerties pie sliktā SQL teikuma vai procedūras (kas noteikti ir jāanalizē ar tādu pašu metodi tālāk) uzlabošanas/pārrakstīšanas/izmešanas.
Kādā veidā izveidot atskaiti, kurā parādās izpildītie soļi un to patērētais laiks, kā arī kādā veidā tad mēģināt panākt, lai konkrētā bremze nebūtu tik bremzīga, tas jau nav vairs šī raksta uzdevums.