Jump to content

Jautājums ORACLE specam


Ronalds
 Share

Recommended Posts

Varbūt te ir kāds Oracle specs kurš spēs pakomentēt.

 

Pirmā problēma - ir divas tabulas REKINI un REKINI_PRECES.  Precēs ~1 miljons ierakstu. Softs automātiski ģenerē rēķinus (vairākus simtus), kļūdas gadījumā viņi jādzēš ārā. 

Ja dzēšam ārā ar SQL (delete from REKINI where id in (1,2,3,4,5,6,7..... utt utjp)) dzēšas ārā nesamērīgi ilgi - gaidīju kādu stundu, nesagaidīju.... 

ID sarakstu ģenerē klienta GUI .  Problēma ir nenormāli lēnā dzēšanā no tabulas REKINI_PRECES, kas notiek pēc foreign key delete cascade. 

Pārtaisīju gui lai dzēš ārā pa vienam ierakstam. Tad dzēšana notika "ņiprāk" -  apmēram 1 -2 rēķini sekundē un pēc ~10min 700 uzģenerētie rēķini tika izdzēsti.

Padomi ko google ātrumā izmeta - atslēgt indeksus, izmantot ierakstu kopēšanu uz pagaidu tabulām ar pēcāku pārsaukšanu neder - dzēšanai jānotiek no gui uz strādājošas DB. 

On delete trigeru nav. 

Tiešām ORACLE nemāk normāli dzēst ierakstus? 

 

 

Otrā problēma - Rēķinu rindām vajag lauku "numurs pēc kārtas" -NPK lai varētu useris no gui kārtot preces rēķinā kā viņiem iepatīkas. 

Vajag šo lauku aizpildīt ieteicams ar trigeri ar soli 10. 

 

Trigerī on insert or update rakstām:

 

if :new.NPK is null then
 select max(npk)+10 into :new.npk from REKINI_PRECES where rekins_id=:new.rekins_id;
end if;
 
if :new.NPK is null then
 :new.npk := 10;
end if;

 

 

Skuju ziepes -  mutating trigger table error. Izrādās ORACLE neļauj no trigera veikt nekādus pieprasījums tabulai no kuras šis trigers ir izsaukts...  Labi, ir situācijas kad tas var radīt problēmas, tomēr vismaz uz firebird tas strādā.... Workarounds - viltīgas manipulācijas iekš package...

 

Nu labi, uztaisīšu NPK aizpildīšanu no GUI. Bet ierakstu dzēšanas ātrums reāli kretinē.......

 

Link to comment
Share on other sites

Varbūt vienkāršāk būtu ielikt rēķinu ģenerēšanu transakcijā, nekā čakarēties ar dzēsanu.

  • Patīk 1
Link to comment
Share on other sites

Bet ir takš rēķinu generēšana tranzakcijā. Problēma tur ka kļūdas vēlāk pamana. 

Link to comment
Share on other sites

Nu, tad vēl vari pamēģināt atteikties no IN operatora, dzēšamo ierakstu ID ievietot pagaidu tabulā un to džoinot pie REKINI tabulas.

Link to comment
Share on other sites

nevertell

Dari kā beisiks saka, uztaisi temp tabulu ar dzēšamajiem ID, džoino un dzēs. 

Vispār jau transakciju modelis tam arī ir domāts, lai kļūdas izravētu pirms tiek veiktas izmaiņas tavā kaķu bāzē.

Link to comment
Share on other sites

ir mēģināts, nelīdz. In nav pie vainas.

 

Delete from rekini where rekini.grupa_id= 1000

 

Arī nenormāli lēni. Pie vainas ir nenormāli lēnā dzēšana no tabulas rekini_preces. Tabula ir salīdzinoši liela, bet nekas īpašs priekš mūsdienām.

Link to comment
Share on other sites

Tātad 

 

Select * from rekini_preces where rekins_id in (1,2,3,... utt kopā pāris simti id)  - Izpildās praktiski momentāli, visu ierakstu (pāris tūkstoši) fech notiek pāris sekundēs.

 

DELETE from rekini_preces where rekins_id in (1,2,3,... utt kopā pāris simti id) - nevar sagaidīt kamēr izpildīsies, pa 1h nebija pabeidzies. Serverim vienai corei 100% noslodze un viss. 

 

Tabulā REKINI_PRECES ap 1 miljons ierakstu, kādi 20 lauki, pāris indeksu.  Kā jau teicu nav maza tabula, bet nu ne jau tik traki! 

Link to comment
Share on other sites

Viens variants ir fiziski nedzēst, bet vienkārši atzīmēt, ka rēķins ir dzēsts un nerādīt to vairs GUI.

 

Bet nu pie 1 miljona ierakstiem nevajadzētu būt šādām problēmam. Tas, ka pie dzēšanas ar IN, ir lēnu varētu liecināt, ka neizmantoja indeksu uz rekini_preces tabulu un tāpēc tā arī nebeidzās. Ar statistikām viss kārtībām?
 

 

edit: anyway vajag trace palaist un tad skatīties, kas bremzē

Labots - Biete
  • Patīk 1
Link to comment
Share on other sites

nevertell

Erm, laikam tad beigšu uzbāsties ar nepareizajiem piedāvājumiem. 

Tikai izsaku līdzjūtību, ka tev jācīnās ar dupšainiem risinājumiem.

Link to comment
Share on other sites

(labots)
Viens variants ir fiziski nedzēst, bet vienkārši atzīmēt, ka rēķins ir dzēsts un nerādīt to vairs GUI.

 

Lūk, lieta ir tāda ka es šo sistēmu netaisīju no nulles, bet pārņēmu. Iepriekšējais programmētājs tā ari darīja - atzīmēja ierakstu un nerādīja iekš gui. Tāpēc jau ir tik mega daudz rēķinu - firma ir salīdzinoši neliela un vismaz 2/3 no rēķiniem ir dzēšami. Bet nu dēļ tā lielā daudzumu arī daži select pieprasījumi uz tabulu REKINI_PRECES sāk iebremzēt.... Negribās to bezjēgā audzēt.

 

 

 

Ar statistikām viss kārtībām?

Kā šo pārbaudīt? Kas ir labi, kas nē? 

Ps. Man ir divi minējumi - pirmais ka Oracle tiešām nemāk normāli dzēst ierakstus, ne velti pilns webs ar padomiem uztaisīt temp tabulu ar tādiem pašiem laukiem, pārkopēt ar merge visu vajadzīgo uz to tabulu, nomest īsto tabulu un pārsaukt temp tabulu par īsto, pievienot indeksus.  Jo cik ir bijusi darīšana ne uz mssql, ne firebird, ne mysql ar dzēšanu problēmu nav bijis.

 

Otrs - ka kaut kas servera konfigā nav kārtībā..... 

Labots - ronalds_
Link to comment
Share on other sites

Oracle parasti problēmas sākas, ja dzēš miljons rindas no daudzmiljonu tabulām :) Tad vajag veikt viltīgas mahinācijas (vai nu merge vai truncate+insert), bet šim nevajadzētu būt tādam gadījumam. Vai arī dzelzis ir sūds...

 

Statistikas var nočekot no all_tables tabulas where table_name = 'tabulas_nosaukums'. Tur ir lauks last_analyzed, kas tad norāda, kad pēdējo reizi ir savāktas statistikas. Ja tas ir nesen, tad vajadzētu būt ok, tur galvenais, lai vispār tiek vāktas.

Link to comment
Share on other sites

(labots)

Tā lauks last_analyzed=2014/06/09/ 22:49:35 Vai nav tā kā drusku pasen? 

 

Dzelzis ~5 gadi vecs 2 proču Xeon (kopā 8 cores) 8 gb ram, 7200 rpm  sas diski piektajā raidā. 

Labots - ronalds_
Link to comment
Share on other sites

Nu tur atkarīgs, cik daudz dati mainījušies pēc tā datuma. Ja tad bija 100 ieraksti un tagad ir 1 miljons, tad statistikas ir vecas. Ja bija 900k un tagad ir 1 miljons, tad +- OK.

Anyway var tās savākt ar dbms_stats. gather_table_stats (tur vajag norādīt tikai owner un table_name, pārējos parametrus atstāj defaultos) un tad vēlreiz patestēt.

 

Ja problēma saglabājas, tad var jau arī būt kāds Oracle/OS bugs.

 

Bet es ieteiktu palaist trace (http://docs.oracle.com/cd/B10500_01/server.920/a96533/sqltrace.htm), pēc tam pēc tkprof parsēšanas varēs redzēt, kas tieši bremzē. Ja to veic pirmoreiz, tagad bik jāiebrauc procesā, bet tas nav nekas sarežģīts. Savādāk tagad sanāk tikai zīlēt.


Vēl var pamēģināt palaist ko šādu, ja saki, ka atlasīšana strādā ātri:

DELETE FROM rekini_preces WHERE rowid IN (SELECT rowid FROM rekini_preces WHERE rekins_id IN (1,2,3, ..) ).

  • Patīk 1
Link to comment
Share on other sites

Par to trace - Oracle dokumentācija ir diezgan nesaprotama... Moš ir kāda step by step guide  iesācējiem. Serveris ir uz linux, kā klientu izmantoju TOAD freeware (mož ir kas labāks...?)

 

Par to ROWID - būs rīt jāpamēģina, moš nostrādā. 

Link to comment
Share on other sites

Mezavecis

Jebkurā citā lielā DB ir šādas problēmas un ierakstu dzēšana ir viena no lēnākām darbībām. 

 

 

Oracle parasti problēmas sākas, ja dzēš miljons rindas no daudzmiljonu tabulām

 

Cik nācies veidot n-tās CRM sistēmas, rēķinu dzēšana tiek aizliegta pilnībā nederīgās pozīcijas atzīmējot ar mārķeriem, jo parasti rēķini ir saistīti ar vēl daudzām tabulām, kas grauj datu integritāti Ļoti vēlams, lai kļūdaina informācija nenonāk datubāzē izmantojot transakcijas, vai sliktākā gadījumā starptabulu, kuru pa laikam ar truncate var nonest pilnībā. 

 

Normālai indeksētai tabulai nav problēmas ar ātrdarbību pat ar n miljoniem ierakstiem.

  • Patīk 1
Link to comment
Share on other sites

Trigger vietā vajadzētu izmantot SEQUENCE. Ātrdarbības problēmu izraisa droši vien neadekvāts izpildes plāns. Vajag pārliecināties, ka eksistē indekss VALID statusā, vajag daudzmaz atbilstošu statistiku tabulai un indeksam. Ja SQL trace un explain atgriež stipri atšķirīgu ierakstu skaitu, tad ir skaidrs, ka izpildes plāns būs nepareizs. Vēl var paskatīties, kādi wait eventi notiek tai sesijai. Varbūt patiesībā ir citi traucēkļi.

Link to comment
Share on other sites

Izveido kontu, vai pieraksties esošajā, lai komentētu

Jums ir jābūt šī foruma biedram, lai varētu komentēt tēmas

Izveidot jaunu kontu

Piereģistrējies un izveido jaunu kontu, tas būs viegli!

Reģistrēt jaunu kontu

Pierakstīties

Jums jau ir konts? Pierakstieties tajā šeit!

Pierakstīties tagad!
 Share

×
×
  • Izveidot jaunu...