Вы находитесь на странице: 1из 11

eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee

Por:Serglo Rufuel Clunuzzu en:vle z de Lne, zoo, o,:oi LS1 (6iioi LecLurus)
eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee
LL slgulenLe urLiculo es unu Lruducclon uproxlmudu de un urLiculo publlcudo en el numero de SepLlembrelOcLubre
del zoo6 de lu revlsLu Orucle.
eeEEEEeeEeeEEeeeeeeeeEeeeeeeeEEeeeeEEE
eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee LL slgulenLe urLlculo es unu Lruducclon uproxlmudu de un urLlculo publlcudo en el numero
de SepLlembrelOcLubre del zoo6 de lu revlsLu Orucle.
Eeeeeeeeeeeeeeeeeeeeee
ROWNUM es unu columnu muglcu oue exlsLe en Orucle oue generu clerLu confuslon enLre los desurrolludores. Sln emburgo, cuundo
uno uprende oue es v como funclonu, puede ser exLremudumenLe uLll. Se usu prlnclpulmenLe puru dos cosus: . Puru obLener los
prlmeros N reglsLros. LsLo es slmllur u uLlllzur lu cluusulu LlMl1, dlsponlble en oLrus buse de duLos. z. Puru puglnur ouerles, Liplco en
umblenLes sLuLeless como lu Web. veremos cudu unu de esLus uLllldudes luego de expllcur como funclonu ROWNUM.
EeeeeMeeeeeeeeeeeeee
ROWNUM es unu pseudocolumnu (no unu columnu reul) oue esLu dlsponlble en los resulLudos de los ouerles. ROWNUM Lendru
uslgnudos los numero ,z,,...,N donde N es el numero de fllus en el resulLudo. Un vulor ROWNUM no es uslgnudo permunenLemenLe u
unu fllu (esLe es un error de concepLo comun). Unu fllu en lu Lublu NO Llene nlngun numero uslgnudo, no se puede pedlr oue Le devuelvu
lu fllu de unu Lublu, no exlsLe Lul cosu.
OLru cosu oue suele confundlr mucho es suber cuundo se uslgnu el ROWNUM. Ll vulor de ROWNUM es uslgnudo u unu fllu luego de oue
puso lu fuse de predlcudo del ouerv pero unLes oue el ouerv puse por ulgun ordenumlenLo o ugreguclon. Ademus, un vulor ROWNUM es
lncremenLudo solumenLe luego de ser usglnudo, lo oue expllcu por oue el slgulenLe ouerv no devuelve nlngunu fllu:
~np~
select * from t where ROWNUM > 1
~/np~
Lebldo u oue ROWNUM > no es verdudero puru lu prlmer columnu, ROWNUM nuncu uvunzu u z. Por ello, nlngun vulor de ROWNUM
es muvor oue . Consldere un ouerv con lu slgulenLe esLrucLuru:
~np~
select ...,ROWNUM from t where group by having order by ;
~/np~
2+/05/2011 : Utilizando ROWNUN en motores Oracle
epidataconsulting.com/./tiki-print_arti. 1/11
Lo unLerlor es procesudo de lu slgulenLe muneru:
. Lu cluusulu lROMlWHLRL vu prlmero.
z. ROWNUM es uslgnudo e lncremenLudo puru cudu fllu obLenldu en el lROMlWHLRL.
. Ll SLLLC1 es upllcudo.
i. Ll CROUP 8Y es upllcudo.
. Ll HAvlNC es upllcudo.
6. Ll ORLLR 8Y es upllcudo.
Ls por eso oue el ouerv expresudo de lu slgulenLe muneru es cusl un error:
~np~
select *
from emp
where ROWNUM <= 5
order by sal desc;
~/np~
Lu lnLenclon eru prlnclpulmenLe obLener lus clnco personus me|or pugus en unu Lop-N ouerv. Lo oue el ouerv vu u reLornur
verduderumenLe son los prlmeros clnco reglsLros uleuLorlos ( Los prlmeros clnco oue encuenLre ) ordenudos por sulurlo. Ll
pseudocodlgo procedlmenLul puru esLu ouerv seriu el slgulenLe:
~np~
ROWNUM = 1
for x in
( select * from emp )
loop
exit when NOT(ROWNUM <= 5)
OUTPUT record to temp
ROWNUM = ROWNUM+1
end loop
SORT TEMP
~/np~
LsLe codlgo obLlene los clnco prlmeros reglsLros v los ordenu. Un ouerv con WHLRL ROWNUM = o WHLRL ROWNUM > no Llene
senLldo. LsLo es poroue un vulor ROWNUM se uslgnu u unu fllu durunLe lu evuluuclon del predlcudo v se lncremenLe solo despues de
oue unu fllu es obLenldu por lu cluusulu WHLRL. Aoui Lenemos lu verslon correcLu del ouerv:
~np~
select *
from
( select *
from emp
order by sal desc )
where ROWNUM <= 5;
~/np~
2+/05/2011 : Utilizando ROWNUN en motores Oracle
epidataconsulting.com/./tiki-print_arti. 2/11
LsLu verslon ordenuru lu Lublu LMP por sulurlo de muneru descendenLe v reLornuru los clnco prlmeros reglsLros oue encuenLre. Lu buse
de duLos es lo suflclenLemenLe lnLellgenLe como puru no ordenur reulmenLe el con|unLo enLero de resulLudos, pero concepLuulmenLe es
lo oue sucede.
MeeeeeeeeeeeeeeeeeeMMeeMeeeeeeeeeeeeeeeee
Un Lop-N ouerv, generulmenLe se reullzu pensundo en ulgunu consulLu comple|u, ordenundolu v posLerlormenLe recuperundo lus
prlmerus N fllus (Lop N). ROWNUM Llene unu opLlmlzuclon Lop-N oue fuclllLu esLe Llpo de consulLu. Puede usur ROWNUM puru evlLur
un ordenumlenLo muslvo de un con|unLo muv grunde de reglsLros.Prlmero se mosLruru esLu ldeu concepLuulmenLe v despues u Lruves
de un e|emplo. Supongu oue Llene unu consulLu de esLu formu:
~np~
select ...
from ...
where ...
order by columns;
~/np~
Asumu oue esLe ouerv reLornu muchos duLos: mlles, clenLos de mlles, o mus fllus. Sln emburgo, usLed esLu lnLeresudo solumenLe en los
Lop-N, por e|emplo, los o o oo prlmeros. Huv dos formus de hucerlo:
. Hucer oue lu upllcuclon cllenLe corru dlcho ouerv v exLrulgu solo lus prlmerus N fllus.
z. Usur el ouerv como unu vlsLu lnllne, v usur ROWNUM puru llmlLur los resulLudos, como en SLLLC1 * lROM (su_consulLu_uoul)
WHLRL ROWNUM <= N.
Lu segundu uproxlmuclon es por mucho superlor u lu prlmeru debldo u dos ruzones. Lu prlmeru es oue reoulere menos Lrubu|o de purLe
del cllenLe, poroue lu buse de duLos se ocupun de llmlLur el resulLseL. Lu mus lmporLunLe es el procesumlenLo especlul oue puede hucer
lu buse de duLos puru durle solo lus N prlmerus fllus. Al usur el Lop-N ouerv, se du u lu buse de duLos unu lnformuclon exLru. UsLed le hu
dlcho: LsLov lnLeresudo solumenLe en obLener N fllus, no me lmporLu el resLo. Ahoru, eso no suenu nudu del oLro mundo husLu oue se
plensu en el Lrubu|o oue lmpllcu puru el servldor hucer el Lrubu|o de ordenumlenLo. Lemos un recorrldo u lus dos uproxlmuclones con un
ouerv de muesLru:
~np~
select *
from t
order by unindexed_column;
~/np~
Ahoru usumu oue 1 es unu Lublu grunde, con mus de un mlllon de reglsLros, v cudu reglsLro es gordo, dlgumos, oo o mus bvLes.
1umblen usumu oue UNlNLLXLL_COLUMN es, como su nombre lo lmpllcu, unu columnu oue no esLu lndexudu v usumu oue usLed
esLu lnLeresudo en obLener solumenLe lus o prlmerus fllus. Lu buse de duLos Orucle reullzuriu lo slgulenLe:
. Un full scun sobre lu Lublu 1. z. Ordenur 1 por UNlNLLXLL_COLUMN. LsLo es un ordenumlenLo compleLo. . PoslblemenLe
sobrepuse el ureu de memorlu v neceslLe hucer swupplngs de duLos LemporulmenLe u dlsco. i. Huce un merge con los duLos
LemporulmenLe bu|udos u dlsco puru obLener los o prlmeros reglsLros cuundo seun sollclLudos. . Llmplu los duLos Lemporules cuundo
se de|un de uLlllzur.
2+/05/2011 : Utilizando ROWNUN en motores Oracle
epidataconsulting.com/./tiki-print_arti. 3/11
se de|un de uLlllzur.
Ahoru, esLo es mucho Lrubu|o de LlS. Lu buse de duLos Orucle muv probublemenLe hu copludo Lodu lu Lublu en 1LMP v lu hu borrudo,
solo puru obLener lus o prlmerus fllus.
PosLerlormenLe, veumos concepLuulmenLe lo oue Orucle puede hucer con un Lop-N ouerv:
~np~
select *
from
(select *
from t
order by unindexed_column)
where ROWNUM < :N;
~/np~
Ln esLe cuso, Orucle huru los slgulenLes pusos: . Un burrldo compleLo sobre 1, como en el unLerlor cuso (esLe puso no se puede omlLlr).
z. Ln un urreglo de :N elemenLos (se presume oue esLun curgudos en memorlu esLu vez), ordene solo :N fllus. Lus prlmerus N fllus
poblurun esLe urreglo de fllus de muneru ordenudu. Cuundo lus prlmerus N fllus son Lruidus, se compururun con lu ulLlmu fllu en el
urreglo. Sl llegu husLu lu poslclon N en el urreglo, esLu se descurLu. Le oLru formu, se udlclonu ul urreglo v se ordenu v unu de lus fllus
oue esLubu en el urreglo se descurLu. Ll ureu ordenudu ulmucenu N fllus muxlmo, usi, en vez de ordenur un mlllon, se ordenun N fllus.
LsLe upurenLemenLe lnslgnlflcunLe deLulle de usur el concepLo de urreglo v ordenur solo N fllus puede llevur u grundes gununclus en
performunce v uso de recursos. Reoulere muchu menos RAM ordenur o fllus oue lo oue Lomu ordenur un mlllon de fllus ( sln menclonur
el uso de espuclo en 1LMP ).
Usundo lu slgulenLe Lublu 1, puede ver oue uunoue umbus uproxlmuclones obLlenen los mlsmos resulLudos, usun cunLldudes
rudlculmenLe dlferenLes de recursos:
~np~
create table t
as
select dbms_random.value(1,1000000)
id, rpad('*',40,'*' ) data from dual
connect by level <= 100000;
begin
dbms_stats.gather_table_stats
( user, 'T');
end;
/
~/np~
Ahoru, hublllLundo Lruclng u Lruves de:
2+/05/2011 : Utilizando ROWNUN en motores Oracle
epidataconsulting.com/./tiki-print_arti. +/11
~np~
exec
dbms_monitor.session_trace_enable
(waits=>true);
~/np~
L|ecuLe su Lop-N ouerv con ROWNUM:
~np~
select *
from
(select *
from t
order by id)
where rownum <= 10;
~/np~
Y flnulmenLe e|ecuLe unu consulLu do-lL-vourself oue exLrulgu solo los o prlmeros reglsLros:
~np~
declare
cursor c is
select *
from t
order by id;
l_rec c%rowtype;
begin
open c;
for i in 1 .. 10
loop
fetch c into l_rec;
exit when c%notfound;
end loop;
close c;
end;
/
~/np~
Lespues de e|ecuLur esLu consulLu, puede usur 1KPROl puru formuLeur el urchlve de Lruce resulLunLe v verlflcur lo oue sucedlo.
Prlmero, exumlne el Lop-N ouerv, como se muesLru en el LlsLudo de codlgo .
2+/05/2011 : Utilizando ROWNUN en motores Oracle
epidataconsulting.com/./tiki-print_arti. 5/11
~np~
Listado de cdigo 1: Top-N query usando ROWNUM
select *
from
(select *
from t
order by id)
where rownum <= 10
~/np~
~np~
call count cpu elapsed disk query current rows
-------- -------- ------- ------- ------- -------- -------- ------
Parse 1 0.00 0.00 0 0 0 0
Execute 1 0.00 0.00 0 0 0 0
Fetch 2 0.04 0.04 0 949 0 10
-------- -------- ------- ------- ------- -------- -------- ------
total 4 0.04 0.04 0 949 0 10
Rows Row Source Operation
----------------- ---------------------------------------------------
10 COUNT STOPKEY (cr=949 pr=0 pw=0 time=46997 us)
10 VIEW (cr=949 pr=0 pw=0 time=46979 us)
10 SORT ORDER BY STOPKEY (cr=949 pr=0 pw=0 time=46961 us)
100000 TABLE ACCESS FULL T (cr=949 pr=0 pw=0 time=400066 us)
~/np~
Ll ouerv levo Lodu lu Lublu ( poroue debiu hucerlo ), pero usundo el puso SOR1 ORLLR 8Y S1OPKLY, pudo llmlLur el uso de espuclo
Lemporul u solumenLe o fllus. NoLe oue lu lineu flnul del resulLudo en Row Source OperuLlon muesLru oue lu consulLu hlzo oio llOs
loglcos, en LoLul (cr=oio), no hlzo lecLurus o escrlLurus fislcus (pr=o und pw=o), v Lomo iooo66 mllloneslmus de segundo (o.oi
segundos). Compure eso conLru lu ulLernuLlvu do-lL-vourself mosLrudu en el LlsLudo de Codlgo z.
~np~
Listado de Cdigo 2: Consulta Do-it-yourself con ROWNUM
SELECT * FROM T ORDER BY ID
~/np~
2+/05/2011 : Utilizando ROWNUN en motores Oracle
epidataconsulting.com/./tiki-print_arti. 6/11
~np~
call count cpu elapsed disk query current rows
-------- -------- ------- ------- ------- -------- -------- ------
Parse 1 0.00 0.00 0 0 0 0
Execute 2 0.00 0.00 0 0 0 0
Fetch 10 0.35 0.40 155 949 6 10
-------- -------- ------- ------- ------- -------- -------- ------
total 13 0.36 0.40 155 949 6 10
Rows Row Source Operation
----------------- ---------------------------------------------------
10 SORT ORDER BY (cr=949 pr=155 pw=891 time=401610 us)
100000 TABLE ACCESS FULL T (cr=949 pr=0 pw=0 time=400060 us)
~/np~
Los Llempos Lrunscurrldos lncluven esperur por los slgulenLes evenLos:
~np~
Event waited on Times
------------------------------ ------------
direct path write temp 33
direct path read temp 5
~/np~
Como podemos ver, esLe resulLudo es muv dlferenLe. Los Llempos de CPU son slgnlflcuLlvumenLe muvores, v lus lineus resulLunLes del
Row Source OperuLlon dun unu muesLru de ello. Acu se hu reullzudo un ordenumlenLo en dlsco, el cuul se puede ver con el purumeLro
pw=8o (phvslcul wrlLes). Su consulLu reullzo ulgunus lecLurus v escrlLurus dlrecLus el ordenumlenLo de los oo,ooo reglsLros (en vez
de hucer los o oue flnulmenLe son los oue nos lnLeresun) se reullzo en dlsco udlclonundo un uso conslderuble u recursos de e|ecuclon
de su consulLu.
MeeeeeeeMeeeeeeeeeeeeeeeeeee
OLro uso de ROWNUM es lu puglnuclon. Ln esLe cuso, se usu ROWNUM puru obLener N fllus u Lruves de M en un resulL seL. Lu
esLrucLuru generul es lu slgulenLe:
~np~
select *
from ( select /*+ FIRST_ROWS(n) */
a.*, ROWNUM rnum
from ( your_query_goes_here,
with order by ) a
where ROWNUM <=
:MAX_ROW_TO_FETCH )
where rnum >= :MIN_ROW_TO_FETCH;
~/np~
donde:
2+/05/2011 : Utilizando ROWNUN en motores Oracle
epidataconsulting.com/./tiki-print_arti. //11
llRS1_ROWS(N) le dlce ul opLlmlzudor, Che, esLov lnLeresudo en obLener lus prlmerus fllus, v obLendre N de ellus Lun rupldo
como seu poslble.
:MAX_ROW_1O_lL1CH se colocu puru lndlcur lu ulLlmu fllu del resulL seL u Lruer sl usLed oueriu Lruer o u 6o fllus del resulL
seL, debe ponerlo en 6o.
:MlN_ROW_1O_lL1CH se colocu puru lndlcur lu prlmeru fllu del resulL seL u Lruer, usi, puru obLener lus fllus o u 6o, debe
ponerlo en o.
Ll concepLo deLrus de esLe escenurlo es oue un usuurlo con un browser hu hecho unu busouedu v esLu esperundo por los resulLudos. Ls
lmperuLlvo reLornur lu prlmeru puglnu resulLunLe ( v lu segundu, v usi suceslvumenLe ) Lun rupldo como seu poslble. Sl se fl|u mus
deLenldumenLe en lu consulLu, noLuru oue lncorporu un Lop-N ouerv (obLlene lus prlmerus :MAX_ROW_1O_lL1CH fllus de su consulLu
) v en consecuenclu se beneflclu de lu opLlmlzuclon Lop-N. Yendo mus ullu, reLornu ul cllenLe, solo los resulLudos especiflcos de lnLeres
remueve cuulouler fllu unLerlor oue no seu de lnLeres. Un deLulle lmporLunLe sobre el uso de consulLus puglnudus es oue lu cluusulu
ORLLR 8Y debe ordenur por ulgun elemenLo unlco. Sl lo oue esLu ordenundo no es unlco, debe udlclonur ulgo ul flnul del ORLLR 8Y
puru hucerlo usi. Sl ordenu oo reglsLros oo por lu columnu SALARY, por e|emplo, v Lodos ellos Llenen el mlsmo vulor de SALARY,
enLonces, pedlr lus fllus de lu zo u z reulmenLe no Llene nlngun senLldo. Puru ver esLo, use unu peouenu Lublu con muchos vulores de lL
dupllcudos:
~np~
SQL> create table t
2 as
3 select mod(level,5) id, trunc(dbms_random.value(1,100)) data
4 from dual
5 connect by level <= 10000;
Table created.
~/np~
Lespues, consulLe fllus de lu i8 u lu o v despues de ordenur por lu columnu lL:
~np~
SQL> select *
2 from
3 (select a.*, rownum rnum
4 from
5 (select id, data
6 from t
7 order by id) a
8 where rownum <= 150
9 )
10 where rnum >= 148;
~/np~
2+/05/2011 : Utilizando ROWNUN en motores Oracle
epidataconsulting.com/./tiki-print_arti. 8/11
~np~
ID DATA RNUM
------- ---------- -----------
0 38 148
0 64 149
0 53 150
~/np~
~np~
SQL>
SQL> select *
2 from
3 (select a.*, rownum rnum
4 from
5 (select id, data
6 from t
7 order by id) a
8 where rownum <= 151
9 )
10 where rnum >= 148;
~/np~
~np~
ID DATA RNUM
------- ---------- -----------
0 59 148
0 38 149
0 64 150
0 53 151
~/np~
NoLe oue en esLe cuso, oue unu vez puru lu fllu i8, el resulLudo reLorno LA1A=8, v oue lu proxlmu vez, el resulLudo reLorno LA1A=o.
Ambus consulLus esLun reLornundo exucLumenLe lu respuesLu correcLu, dudo oue hu pedldo: Ordene los duLos por lL, lunce lus prlmerus
i, fllus, v reLorne lus slgulenLes u i fllus. Ambos lo hucen, pero como el lL Llene LunLos vulores dupllcudos, lu consulLu no puede
hucerlo deLermlnisLlcumenLe el mlsmo ordenumlenLo no se useguru de e|ecuclon en e|ecuclon puru lu consulLu. Con el proposlLo de
correglr esLo, neceslLu udlclonur ulgo unlco ul ORLLR 8Y. Ln esLe cuso, use ROWlL:
2+/05/2011 : Utilizando ROWNUN en motores Oracle
epidataconsulting.com/./tiki-print_arti. 9/11
~np~
SQL> select *
2 from
3 (select a.*, rownum rnum
4 from
5 (select id, data
6 from t
7 order by id, rowid) a
8 where rownum <= 150
9 )
10 where rnum >= 148;
~/np~
~np~
ID DATA RNUM
------- ---------- -----------
0 45 148
0 99 149
0 41 150
~/np~
~np~
SQL>
SQL> select *
2 from
3 (select a.*, rownum rnum
4 from
5 (select id, data
6 from t
7 order by id, rowid) a
8 where rownum <= 151
9 )
10 where rnum >= 148;
~/np~
~np~
ID DATA RNUM
------- ---------- -----------
0 45 148
0 99 149
0 41 150
0 45 151
~/np~
Ahoru el ouerv es deLermlnlsLlco. ROWlL es unlco denLro de lu Lublu, por lo oue sl se usu ORLLR 8Y lL v luego denLro de lL se usu
ORLLR 8Y ROWlL, lus fllus Lendrun un orden deLermlnlsLlco v el ouerv de puglnuclon devolveru deLermlnlsLlcumenLe lus fllus como se
2+/05/2011 : Utilizando ROWNUN en motores Oracle
epidataconsulting.com/./tiki-print_arti. 10/11
ORLLR 8Y ROWlL, lus fllus Lendrun un orden deLermlnlsLlco v el ouerv de puglnuclon devolveru deLermlnlsLlcumenLe lus fllus como se
esperu.
EeeEEeEEeeEEeEeMeEeeeeeee
Con lo unLerlor, podemos deduclr lo slgulenLe de ROWNUM:
Como ROWNUM es uslgnudo, puru oue puedun escrlblrse ouerles llbre de errores.
Como ufecLu el procesumlenLo de un ouerv, puru oue puedun puglnur los resulLudos en lus upllcuclones.
Como puede reduclr el Llempo de e|ecuclon de un ouerv, puru oue los ouerles Lop-N no consumun demusludo recursos v puedun
e|ecuLur mucho mus rupldo.
2+/05/2011 : Utilizando ROWNUN en motores Oracle
epidataconsulting.com/./tiki-print_arti. 11/11

Вам также может понравиться