Par to, kÄ man bija jÄoptimizÄ PostgreSQL vaicÄjums un kas no tÄ visa iznÄca.
KÄpÄc tev vajadzÄja? JÄ, jo iepriekÅ”Äjos 4 gadus viss strÄdÄja klusi, mierÄ«gi, kÄ pulkstenis tikŔķÄja.
KÄ epigrÄfs.
Balstīts uz patiesiem notikumiem.
Visi nosaukumi ir mainīti, sakritības ir nejauŔas.
Sasniedzot noteiktu rezultÄtu, vienmÄr ir interesanti atcerÄties, kas bija stimuls sÄkumam, kur tas viss sÄkÄs.
TÄtad, kas notika rezultÄtÄ, ir Ä«si aprakstÄ«ts rakstÄ "
DroÅ”i vien bÅ«s interesanti atjaunot iepriekÅ”Äjo notikumu Ä·Ädi.
VÄsture saglabÄja precÄ«zu sÄkuma datumu - 2018-09-10 18:02:48.
ArÄ« stÄstÄ ir lÅ«gums, no kura viss sÄkÄs:
ProblÄmas pieprasÄ«jumsSELECT
p.āPARAMETER_IDā kÄ parametra_id,
pd."PD_NAME" AS pd_name,
pd."CUSTOMER_PARTNUMBER" AS klienta_daļas numurs,
ar āLRMā AS LRM,
w. "LOTID" AS lotid,
w.āRTD_VALUEā AS RTD_vÄrtÄ«ba,
w.āLOWER_SPEC_LIMITā AS zemÄks_spec_limits,
w.āUPPER_SPEC_LIMITā AS augÅ”Äjais_spec_limits,
p"TYPE_CALCUL" AS type_calcul,
s"SPENT_NAME" AS iztÄrÄtais_nosaukums,
s.āSPENT_DATEā AS iztÄrÄts_datums,
izraksts(gads no "SPENT_DATE") AS gads,
izraksts (mÄnesis no "SPENT_DATE") kÄ mÄnesis,
s."REPORT_NAME" AS pÄrskata_nosaukums,
p."STPM_NAME" AS stpm_name,
p.āCUSTOMERPARAM_NAMEā AS klienta parametra_nosaukums
NO wdata w,
pavadīja s,
pmtr p,
pavadīja_pd sp,
pd pd
WHERE s.āIZLÄDTAIS_IDā = w.āIZLÄDTS_IDā
UN p."PARAMETER_ID" = w."PARAMETER_ID"
UN s.āIZLÄDTS_IDā = sp.āIZDOTÄ_IDā
UN pd."PD_ID" = sp."PD_ID"
UN s.āSPENT_DATEā >= '2018-07-01' UN s.āSPENT_DATEā <= '2018-09-30'
un s.āSPENT_DATEā = (ATLASÄŖT MAX(s2.āSPENT_DATEā)
NO iztÄrÄtÄ s2,
wdata w2
WHERE s2.āIZLÄTOTÄS_IDā = w2.āIZLÄTOTAS_IDā
UN w2.āLRMā = w.āLRMā);
ProblÄmas apraksts ir paredzami standarta - āViss ir slikti. PastÄsti man, kÄda ir problÄma."
Uzreiz atcerÄjos anekdoti no 3 ar pusi collu piedziÅas laikiem:
Lamer nÄk pie hakera.
-Man nekas nelÄ«dz, pasaki kur ir problÄma.
- DNS...
Bet, protams, tas nav veids, kÄ atrisinÄt darbÄ«bas traucÄjumus. "ViÅi var mÅ«s nesaprast" (Ar). Mums tas ir jÄizdomÄ.
Nu raksim. VarbÅ«t rezultÄtÄ kaut kas sakrÄsies.
SÄkta izmeklÄÅ”ana
TÄtad, ko var redzÄt uzreiz ar neapbruÅotu aci, pat neÄ·eroties pie IZSKAIDROT.
1) JOIN netiek izmantoti. Tas ir slikti, it Ä«paÅ”i, ja savienojumu skaits ir vairÄk nekÄ viens.
2) Bet vÄl sliktÄk ir saistÄ«ti apakÅ”vaicÄjumi, turklÄt ar apkopoÅ”anu. Tas ir ļoti slikti.
Tas, protams, ir slikti. Bet tas ir tikai no vienas puses. No otras puses, tas ir ļoti labi, jo problÄmai viennozÄ«mÄ«gi ir risinÄjums un lÅ«gums, ko var uzlabot.
Neej pie zīlnieces (C).
VaicÄjumu plÄns nav tik sarežģīts, taÄu tas ir diezgan orientÄjoÅ”s:
Izpildes plÄns
InteresantÄkais un noderÄ«gÄkais, kÄ parasti, ir sÄkumÄ un beigÄs.
Ligzdota cilpa (maksa = 935.84..479763226.18 rindas = 3322 platums = 135) (faktiskais laiks = 31.536..8220420.295 rindas = 8111656 cilpas = 1)
PlÄnoÅ”anas laiks: 3.807 ms
Izpildes laiks: 8222351.640 ms
Izpildes laiks ir vairÄk nekÄ 2 stundas.
Nepatiesas hipotÄzes, kas prasÄ«ja laiku
1. hipotÄze ā optimizÄtÄjs pieļauj kļūdu un izveido nepareizu plÄnu.
Lai vizualizÄtu izpildes plÄnu, mÄs izmantosim vietni
2. hipotÄze-Ietekme uz pamatni no autovakuuma puses, jÄatbrÄ«vojas no bremzÄm.
Bet autovakuuma dÄmoni uzvedas labi, nav ilgstoÅ”u procesu. Nav nopietnas slodzes. Mums jÄmeklÄ kaut kas cits.
3. hipotÄze - Statistika ir novecojusi, viss ir jÄpÄrrÄÄ·ina
Atkal, ne tas. Statistika ir atjauninÄta. Kas, Åemot vÄrÄ problÄmu trÅ«kumu ar autovakuumu, nav pÄrsteidzoÅ”i.
SÄksim optimizÄt
GalvenÄ tabula 'wdata' noteikti nav maza, gandrÄ«z 3 miljoni ierakstu.
Un tieŔi Ŕai tabulai seko Full Scan.
Jauktais nosacÄ«jums: ((w."SPENT_ID" = s."SPENT_ID") UN ((1. apakÅ”plÄns) = s."SPENT_DATE"))
-> Seq Scan uz wdata w (maksa = 0.00..574151.49 rindas = 26886249 platums = 46) (faktiskais laiks = 0.005..8153.565 rindas = 26873950 cilpas = 1)
MÄs darÄm standarta lietu: "NÄc, izveidosim indeksu, un viss lidos."
LaukÄ āSPENT_IDā tika izveidots rÄdÄ«tÄjs
RezultÄtÄ:
VaicÄjuma izpildes plÄns, izmantojot indeksu
Nu, vai tas palÄ«dzÄja?
Bija: 8 222 351.640 ms (nedaudz vairÄk par 2 stundÄm)
Kļuva: 6 985 431.575 ms (gandrīz 2 stundas)
VispÄr tie paÅ”i Äboli, skats no malas.
AtcerÄsimies klasiku:
āVai jums ir tÄds pats, bet bez spÄrniem? MeklÄsies".
PrincipÄ to varÄtu saukt par labu rezultÄtu, nu, ne labu, bet pieÅemamu. Sniedziet klientam vismaz lielu pÄrskatu, kurÄ aprakstÄ«ts, cik daudz ir paveikts un kÄpÄc paveiktais bija labs.
TomÄr galÄ«gais lÄmums vÄl ir tÄlu. Ä»oti tÄlu.
Un tagad pats interesantÄkais - turpinÄm optimizÄt, pieslÄ«pÄsim pieprasÄ«jumu
Pirmais solis ā izmantojiet JOIN
PÄrrakstÄ«tais pieprasÄ«jums tagad izskatÄs Å”Ädi (nu vismaz tÄ ir skaistÄka):
Pieprasiet, izmantojot JOINSELECT
p.āPARAMETER_IDā kÄ parametra_id,
pd."PD_NAME" AS pd_name,
pd."CUSTOMER_PARTNUMBER" AS klienta_daļas numurs,
ar āLRMā AS LRM,
w. "LOTID" AS lotid,
w.āRTD_VALUEā AS RTD_vÄrtÄ«ba,
w.āLOWER_SPEC_LIMITā AS zemÄks_spec_limits,
w.āUPPER_SPEC_LIMITā AS augÅ”Äjais_spec_limits,
p"TYPE_CALCUL" AS type_calcul,
s"SPENT_NAME" AS iztÄrÄtais_nosaukums,
s.āSPENT_DATEā AS iztÄrÄts_datums,
izraksts(gads no "SPENT_DATE") AS gads,
izraksts (mÄnesis no "SPENT_DATE") kÄ mÄnesis,
s."REPORT_NAME" AS pÄrskata_nosaukums,
p."STPM_NAME" AS stpm_name,
p.āCUSTOMERPARAM_NAMEā AS klienta parametra_nosaukums
NO wdata w INNER JOIN iztÄrÄts s ON w.āSPENT_IDā=s.āāSPENT_IDā
IEKÅ ÄJÄ PIEVIENOÅ ANÄS pmtr p ON p.āPARAMETER_IDā = w.āPARAMETER_IDā
IEKÅ ÄJÄ PIEVIENOÅ ANÄS pavadÄ«ja_pd sp ON s.āSPENT_IDā = sp.āSPENT_IDā
IEKÅ ÄJÄ JOIN pd pd ON pd.āPD_IDā = sp.āPD_IDā
KUR
s.āSPENT_DATEā >= '2018-07-01' UN s.āSPENT_DATEā <= '2018-09-30'AND
s.āSPENT_DATEā = (ATLASÄŖT MAX(s2.āSPENT_DATEā)
NO wdata w2 IEKÅ ÄJÄ JOIN iztÄrÄts s2 ON w2.āSPENT_IDā=s2.āSPENT_IDā
INNER JOIN wdata w
IESLÄGTS w2.āLRMā = w.āLRMā );
PlÄnoÅ”anas laiks: 2.486 ms
Izpildes laiks: 1223680.326 ms
TÄtad, pirmais rezultÄts.
Bija: 6 985 431.575 ms (gandrīz 2 stundas).
Kļuva: 1 223 680.326 ms (nedaudz vairÄk nekÄ 20 minÅ«tes).
Labs rezultÄts. PrincipÄ atkal varÄtu pie tÄ apstÄties. Bet tas ir tik neinteresanti, ka jÅ«s nevarat apstÄties.
PRIEKÅ
Otrais solis ā atbrÄ«vojieties no korelÄtÄ apakÅ”vaicÄjuma
Mainīts pieprasījuma teksts:
Bez korelÄta apakÅ”vaicÄjumaSELECT
p.āPARAMETER_IDā kÄ parametra_id,
pd."PD_NAME" AS pd_name,
pd."CUSTOMER_PARTNUMBER" AS klienta_daļas numurs,
ar āLRMā AS LRM,
w. "LOTID" AS lotid,
w.āRTD_VALUEā AS RTD_vÄrtÄ«ba,
w.āLOWER_SPEC_LIMITā AS zemÄks_spec_limits,
w.āUPPER_SPEC_LIMITā AS augÅ”Äjais_spec_limits,
p"TYPE_CALCUL" AS type_calcul,
s"SPENT_NAME" AS iztÄrÄtais_nosaukums,
s.āSPENT_DATEā AS iztÄrÄts_datums,
izraksts(gads no "SPENT_DATE") AS gads,
izraksts (mÄnesis no "SPENT_DATE") kÄ mÄnesis,
s."REPORT_NAME" AS pÄrskata_nosaukums,
p."STPM_NAME" AS stpm_name,
p.āCUSTOMERPARAM_NAMEā AS klienta parametra_nosaukums
NO wdata w IEKÅ ÄJS JOIN iztÄrÄts s UZ s.āSPENT_IDā = w.āSPENT_IDā
IEKÅ ÄJÄ PIEVIENOÅ ANÄS pmtr p ON p.āPARAMETER_IDā = w.āPARAMETER_IDā
IEKÅ ÄJÄ PIEVIENOÅ ANÄS pavadÄ«ja_pd sp ON s.āSPENT_IDā = sp.āSPENT_IDā
IEKÅ ÄJÄ JOIN pd pd ON pd.āPD_IDā = sp.āPD_IDā
IEKÅ ÄJÄ PIEVIENOÅ ANÄS (ATLASÄŖT w2.āLRMā, MAX(s2.āSPENT_DATEā)
NO iztÄrÄtÄ s2 IEKÅ ÄJÄ PIEVIENOÅ ANÄS wdata w2 ON s2.āIZPÄRTÄTAS_IDā = w2.āIZPÄRTÄTAS_IDā
GROUP BY w2.āLRMā
) md uz w.āLRMā = md.āLRMā
KUR
s."SPENT_DATE" >= '2018-07-01' UN s."SPENT_DATE" <= '2018-09-30';
PlÄnoÅ”anas laiks: 2.291 ms
Izpildes laiks: 165021.870 ms
Bija: 1 223 680.326 ms (nedaudz vairÄk nekÄ 20 minÅ«tes).
Kļuva: 165 021.870 ms (nedaudz vairÄk nekÄ 2 minÅ«tes).
Å is jau ir diezgan labs.
TomÄr, kÄ saka briti "Bet vienmÄr ir bet" PÄrÄk labam rezultÄtam automÄtiski vajadzÄtu izraisÄ«t aizdomas. Å eit kaut kas nav kÄrtÄ«bÄ.
HipotÄze par vaicÄjuma laboÅ”anu, lai atbrÄ«votos no korelÄtÄ apakÅ”vaicÄjuma, ir pareiza. Bet jums tas ir nedaudz jÄpielÄgo, lai gala rezultÄts bÅ«tu pareizs.
RezultÄtÄ pirmais starprezultÄts:
RediÄ£Äts vaicÄjums bez korelÄta apakÅ”vaicÄjumaSELECT
p.āPARAMETER_IDā kÄ parametra_id,
pd."PD_NAME" AS pd_name,
pd."CUSTOMER_PARTNUMBER" AS klienta_daļas numurs,
ar āLRMā AS LRM,
w. "LOTID" AS lotid,
w.āRTD_VALUEā AS RTD_vÄrtÄ«ba,
w.āLOWER_SPEC_LIMITā AS zemÄks_spec_limits,
w.āUPPER_SPEC_LIMITā AS augÅ”Äjais_spec_limits,
p"TYPE_CALCUL" AS type_calcul,
s"SPENT_NAME" AS iztÄrÄtais_nosaukums,
s.āSPENT_DATEā AS iztÄrÄts_datums,
izraksts(gads no s.āSPENT_DATEā) AS gads,
izraksts (mÄnesis no s.āSPENT_DATEā) kÄ mÄnesis,
s."REPORT_NAME" AS pÄrskata_nosaukums,
p."STPM_NAME" AS stpm_name,
p.āCUSTOMERPARAM_NAMEā AS klienta parametra_nosaukums
NO wdata w IEKÅ ÄJS JOIN iztÄrÄts s UZ s.āSPENT_IDā = w.āSPENT_IDā
IEKÅ ÄJÄ PIEVIENOÅ ANÄS pmtr p ON p.āPARAMETER_IDā = w.āPARAMETER_IDā
IEKÅ ÄJÄ PIEVIENOÅ ANÄS pavadÄ«ja_pd sp ON s.āSPENT_IDā = sp.āSPENT_IDā
IEKÅ ÄJÄ JOIN pd pd ON pd.āPD_IDā = sp.āPD_IDā
IEKÅ ÄJÄ PIEVIENOÅ ANÄS ( ATLASÄŖT w2.āLRMā, MAX(s2.āSPENT_DATEā) KÄ āSPENT_DATEā
NO iztÄrÄtÄ s2 IEKÅ ÄJÄ PIEVIENOÅ ANÄS wdata w2 ON s2.āIZPÄRTÄTAS_IDā = w2.āIZPÄRTÄTAS_IDā
GROUP BY w2.āLRMā
) md ON md.āIZLÄDZIS_DATUMSā = s.āIZLÄDZIS_DATUMSā UN md.āLRMā = w.āLRMā
KUR
s."SPENT_DATE" >= '2018-07-01' UN s."SPENT_DATE" <= '2018-09-30';
PlÄnoÅ”anas laiks: 3.192 ms
Izpildes laiks: 208014.134 ms
TÄtad, tas, ko mÄs galu galÄ iegÅ«stam, ir pirmais pieÅemamais rezultÄts, ko nav kauns parÄdÄ«t klientam:
SÄkÄs ar: 8 222 351.640 ms (vairÄk nekÄ 2 stundas)
Mums izdevÄs sasniegt: 1 223 680.326, 20 ms (nedaudz vairÄk par XNUMX minÅ«tÄm).
RezultÄts (starpposms): 208 014.134 ms (nedaudz vairÄk nekÄ 3 minÅ«tes).
Izcils rezultÄts.
Kopsavilkums
MÄs varÄjÄm tur apstÄties.
BETā¦
ApetÄ«te rodas Ädot. Tas, kurÅ” iet, pÄrvaldÄ«s ceļu. JebkurÅ” rezultÄts ir starpposms. ApstÄjÄs un nomira. utt.
TurpinÄsim optimizÄciju.
Lieliska ideja. ÄŖpaÅ”i Åemot vÄrÄ, ka klients pat neiebilda. Un pat stipri par to.
TÄtad, ir pienÄcis laiks pÄrveidot datubÄzi. Pati vaicÄjuma struktÅ«ru vairs nevar optimizÄt (lai gan, kÄ vÄlÄk izrÄdÄ«jÄs, ir iespÄja nodroÅ”inÄt, ka viss tieÅ”Äm neizdodas). Bet sÄkt optimizÄt un attÄ«stÄ«t datu bÄzes dizainu jau ir ļoti daudzsoloÅ”a ideja. Un pats galvenais interesanti. Atkal atcerieties savu jaunÄ«bu. Galu galÄ es ne uzreiz kļuvu par DBA, es uzaugu kÄ programmÄtÄjs (BASIC, montÄtÄjs, C, dubultÄ plus C, Oracle, plsql). Interesanta tÄma, protams, atseviŔķam memuÄram ;-).
TomÄr nenovÄrsÄ«sim uzmanÄ«bu.
TÄtad,
Vai varbÅ«t sadalÄ«Å”ana mums palÄ«dzÄs?
Spoileris ā "JÄ, tas palÄ«dzÄja, tostarp optimizÄjot veiktspÄju."
Bet tas ir pavisam cits stÄsts...
TurpinÄjums sekosā¦
Avots: www.habr.com