[ darkosos @ 01.02.2011. 12:53 ] @
Recimo da sam dva puta trazio sledeci select:
select * from table t where ... and rownum < 1000;

Pod pretpostavkom da se tabela izmedju dva poziva nije ni na koji nacin menjala,
tj. nije bilo ni DML i DDL akcija, da li ima nesto sto moze da garantuje da ce u oba slucaja
result set biti isti?
[ nebojsa_1 @ 08.02.2011. 21:13 ] @
Ne.

Rezultat moze da se promeni ako se promeni execution plan.
[ nebojsa_1 @ 08.02.2011. 21:14 ] @
Ne.

Rezultat moze da se promeni ako se promeni execution plan.
[ darkosos @ 09.02.2011. 10:12 ] @
Jasno. Sad je samo pitanje zasto bi se execution plan menjao u dva uzastopna poziva, u istoj sesiji.
[ djoka_l @ 09.02.2011. 11:19 ] @
Citat:
darkosos:da li ima nesto sto moze da garantuje da ce u oba slucaja result set biti isti?


Ne postoji ništa što može da ti garantuje da će redosled slogova (tj. result set, ako tabela u slučaju iz tvog selecta ima više od 1000 slogova) biti isti.
To važi za Oracle i za svaku drugu relacionu bazu i nikada neće biti promenjeno.

Tabela je po definiciji skup slogova (a skup je neuređen).

Može se zamisliti hiljadu scenarija zašto je to tako. Kao prvo, način na koji baza čita slogove u slučaju tvog upita nije dokumentovan. Na primer, kod Oracle baze, optimizator će napraviti neki execution plan i odlučiti kako da pristupi blokovima iz baze. Neki od tih blokova biće na disku, neki u data bufferu. Između dva čitanja baze neki blokovi u data bufferu će biti izbačeni, pa će svaki upit imati drugačiji physical IO u odnosu na logical IO. Upit može da ima PARALLEL EXCUTION pa će paralelni procesi različitom brzinom i različitim redosledom da čitaju blokove. Disk kontroler može da ima optimizacione potprograme koji će blokove sa diskova čitati u različitom redoslodu u zavisnosti od trenutne pozicije glava (znači redosled čitanja blokova sa diska ne zavisi samo od tog jednog upita nego od svih procesa na serveru koji pokušavaju da pristupe disku).

Možeš da probaš tvoj upit 1000 puta i on može 999 puta da da isti result set, ali će se desiti da bar jednom ne uradi na isti način. Ako sad testiraš program u potpunoj izolaciji od ostatka sveta, sve ostalo pogasiš, onda će možda i svih 1000 testova dati isti rezultat, ali probaj to na živom sistemu i onda nemaš nikakvu garanciju.
[ darkosos @ 09.02.2011. 12:54 ] @
Ok, hvala na odgovorima.

U principu, pokusao sam na ovaj nacin da resim sledeci problem (mozda treba da otvorim novu temu):
iz tabele S prebaciti odgovarajuce slogove u tabelu D (iste strukture kao S);
Posto je broj slogova poprilican, hteo sam da napravim porcije u kojima cu prvo da prebacim n slogova, a onda da ih izbrisem iz source tabele.
Izveo sam to sa nekom kombinacijom bulk collect-a u plsql tabelu (da bih zapamtio id-eve) i dve forall naredbe, za insert i delete.
(probao sam i insert sa returning ... bulk collect into ..., ali nesto me opsovao...)

To radi, ali kada vidim kako je "rownum < n" brz, pomislio sam da bi to mogao da iskoristim...

Da li postoji neka naredba, slicna MERGE, koja bi istovremeno punila dest tabelu i praznila source tabelu?
[ nebojsa_1 @ 16.02.2011. 19:42 ] @
Ako sam dobro shvatio hoces odredeni broj slogova da prebacis u novu tabelu i da iset slogove izbrises iz originalne tabele.

Posto je broj slogova veliki verovatno je problem da transakcija dugo traje ili nemas dovoljno resursa (undo space)


Najbolji nacin da ubrzas ovakav tip transakcije je da smanjis redo informacije koje Oracle generise.


Postupak je sledeci:



1. Napravi particionisanu tabelu sa istom strukturom kao i originalna tabela.
Partition key treba da bude takav da svi slogovi koje hoces da zadrzis u originalnoj tabeli idu u jednu particiju. Izbrisi sve indekse i constrainte na originalnoj tabeli.

2. Izvrsi insert sa hintom appened i nologging svih slogova iz originalne tabele u novu tabelu.
Ako imas dovoljno resursa mozes da koristis parallel opciju.


3. Izvrsi exchange partiotion izmedju originalne tabele i particije u kojoj su slogovi koje hoces da zadrzis. Ova operacija trenutna,

4. Izbrisi particiju koja sada sadrzi slogove iz originalne tabele.

5. Ponovo kreiraj constrainte i indekse.




Ako iz nekog razloga ne zelis ovo da radis ili ti je komplikovano mozes da koristis funkciju percentile_disc na nekoj koloni koja je unique.


Funkcija ce ti vratiti vrednosti za kolonu koje mozes da koristis da prebacis odredjen procenat slogova.


[ dragancesu @ 17.02.2011. 07:50 ] @
Sad treba da razmisljanmo sta je pisac hteo da kaze/sta mu treba

Mislim da ti je najbolje da ubacis kolonu BROJ_STAVKE i tako regulises redosled. Tako ces izbeci velika prebacivanja podataka sa neizvesnim rezultatom

Varijanta sa BROJ_STAVKE se primenjuje na mnogo mesta i nije lose resenje, na vrlo jednostavan nacin ti regulise redosled sto mislim da ti treba
[ darkosos @ 25.02.2011. 07:49 ] @
Hteo sam da kazem:
Citat:
iz tabele S prebaciti odgovarajuce slogove u tabelu D (iste strukture kao S);
Posto je broj slogova poprilican, hteo sam da napravim porcije u kojima cu prvo da prebacim n slogova, a onda da ih izbrisem iz source tabele.


Probao sam vec sa varijantom BROJ_STAVKE, ali to je jos losijih performansi od navedenog BULK COLLECT-a, tako da to otpada.
Ok, hvala na odgovorima.