Está en la página 1de 8

Uso de IN y EXISTS.

EJERCICIO 5: Clientes de la misma ciudad que la agencia donde se realiz la reserva y el aeropuerto origen del trayecto.
Dada la siguiente consulta: select nif, apellidos, nombre, cn_sexo, cn_ec from clientes c, sexos s, estadosciviles e, reservas r where c.sex_id_sexo = s.id_sexo and c.ec_id_ec = e.id_ec and c.nif = r.cli_nif and exists (select null from agencias a where a.ciu_id_ciudad = c.ciu_id_ciudad and a.id_agencia = r.age_id_agencia) and exists (select null from vuelos v, aeropuertos ae where v.aer_id_aero = ae.id_aero and ae.ciu_id_ciudad = c.ciu_id_ciudad and r.vue_id_vuelo = v.id_vuelo)

Obtenemos los siguientes resultados: en devolver 211 filas 4162 lecturas fsicas 0 ordenacin en memria 0 ordenaciones en disco estimacin = 26054 Coste tiempo = 20 Segundo

Primer paso: Estudio de la ejecucin.


Execution Plan ---------------------------------------------------------0 SELECT STATEMENT Optimizer=CHOOSE (Cost=26054 Card=8556 Bytes=761484) 1 0 FILTER 2 1 HASH JOIN (Cost=386 Card=8556 Bytes=761484) 3 2 TABLE ACCESS (FULL) OF 'ESTADOSCIVILES' (Cost=2 Card=5 Bytes=50) 4 2 HASH JOIN (Cost=382 Card=8556 Bytes=675924) 5 4 TABLE ACCESS (FULL) OF 'SEXOS' (Cost=2 Card=2 Bytes=14) 6 4 HASH JOIN (SEMI) (Cost=378 Card=8556 Bytes=616032) 7 6 HASH JOIN (Cost=348 Card=8556 Bytes=573252) 8 7 TABLE ACCESS (FULL) OF 'CLIENTES' (Cost=11 Card=9999 Bytes=499950) 9 7 TABLE ACCESS (FULL) OF 'RESERVAS' (Cost=110 Card=171113 Bytes=2908921) 10 6 TABLE ACCESS (FULL) OF 'AGENCIAS' (Cost=2 Card=102 Bytes=510) 11 1 NESTED LOOPS (Cost=3 Card=1 Bytes=12) 12 11 TABLE ACCESS (BY INDEX ROWID) OF 'VUELOS' (Cost=2 Card=1 Bytes=7) 13 12 INDEX (UNIQUE SCAN) OF 'VUE_PK' (UNIQUE) (Cost=1 Card=57711) 14 11 TABLE ACCESS (BY INDEX ROWID) OF 'AEROPUERTOS' (Cost=1 Card=1 Bytes=5) 15 14 INDEX (UNIQUE SCAN) OF 'AER_PK' (UNIQUE)

EXISTS arrastra a la consulta principal la totalidad de los registros de la subconsulta. Esto incide en la alta cardinalidad que afecta directamente al procesamiento total de la ejecucin. En este caso, y dado que la ejecucin de IN se realiza desde la consulta principal hacia la subconsulta, con mucha seguridad se reducir la cardinalidad El siguiente cdigo podra optimizarse utilizando IN en lugar de EXISTS:
select nif, apellidos, nombre, cn_sexo, cn_ec from clientes c, sexos s, estadosciviles e, reservas r where c.sex_id_sexo = s.id_sexo and c.ec_id_ec = e.id_ec and c.nif = r.cli_nif and c.ciu_id_ciudad in (select ciu_id_ciudad from agencias a where a.id_agencia = r.age_id_agencia) and r.vue_id_vuelo in (select id_vuelo from vuelos v, aeropuertos ae where v.aer_id_aero = ae.id_aero and ae.ciu_id_ciudad = c.ciu_id_ciudad)

Execution Plan ---------------------------------------------------------0 SELECT STATEMENT Optimizer=CHOOSE (Cost=1213 Card=285 Bytes=25365) 1 0 FILTER 2 1 HASH JOIN (Cost=358 Card=285 Bytes=25365) 3 2 TABLE ACCESS (FULL) OF 'ESTADOSCIVILES' (Cost=2 Card=5 Bytes=50) 4 2 HASH JOIN (Cost=355 Card=285 Bytes=22515) 5 4 TABLE ACCESS (FULL) OF 'SEXOS' (Cost=2 Card=2 Bytes=14) 6 4 HASH JOIN (Cost=352 Card=285 Bytes=20520) 7 6 TABLE ACCESS (FULL) OF 'AGENCIAS' (Cost=2 Card=102 Bytes=510) 8 6 HASH JOIN (Cost=348 Card=8556 Bytes=573252) 9 8 TABLE ACCESS (FULL) OF 'CLIENTES' (Cost=11 Card=9999 Bytes=499950) 10 8 TABLE ACCESS (FULL) OF 'RESERVAS' (Cost=110 Card=171113 Bytes=2908921) 11 1 NESTED LOOPS (Cost=3 Card=1 Bytes=12) 12 11 TABLE ACCESS (BY INDEX ROWID) OF 'VUELOS' (Cost=2 Card=1 Bytes=7) 13 12 INDEX (UNIQUE SCAN) OF 'VUE_PK' (UNIQUE) (Cost=1 Card=57711) 14 11 TABLE ACCESS (BY INDEX ROWID) OF 'AEROPUERTOS' (Cost=1 Card=1 Bytes=5) 15 14 INDEX (UNIQUE SCAN) OF 'AER_PK' (UNIQUE)

IN
Rows ------211 5734 5 5734 2 5734 102 171113 9999 171113 211 5732 5732 211 5732 Row Source Operation --------------------------------------------------FILTER HASH JOIN TABLE ACCESS FULL ESTADOSCIVILES HASH JOIN TABLE ACCESS FULL SEXOS HASH JOIN TABLE ACCESS FULL AGENCIAS HASH JOIN TABLE ACCESS FULL CLIENTES TABLE ACCESS FULL RESERVAS NESTED LOOPS TABLE ACCESS BY INDEX ROWID VUELOS INDEX UNIQUE SCAN VUE_PK (object id 43588) TABLE ACCESS BY INDEX ROWID AEROPUERTOS INDEX UNIQUE SCAN AER_PK (object id 43584) Rows ------211 5734 5 5734 2 5734 171113 9999 171113 102 211 5731 5731 211 5731

EXISTS

Row Source Operation ------------------------------------------FILTER HASH JOIN TABLE ACCESS FULL ESTADOSCIVILES HASH JOIN TABLE ACCESS FULL SEXOS HASH JOIN SEMI HASH JOIN TABLE ACCESS FULL CLIENTES TABLE ACCESS FULL RESERVAS TABLE ACCESS FULL AGENCIAS NESTED LOOPS TABLE ACCESS BY INDEX ROWID VUELOS INDEX UNIQUE SCAN VUE_PK (object id 435 TABLE ACCESS BY INDEX ROWID AEROPUERTOS INDEX UNIQUE SCAN AER_PK (object id 435

IN realiza un HASH JOIN, es decir, busca en la subconsulta nicamente los registros que coincidan con la comparacin de llamada principal. Por tanto, la resolucin de la subconsulta est condicionada a los registros seleccionados por la consulta principal.

EXISTS realiza un HASH JOIN SEMI, es de aquellos registros de la subconsulta y los clusula de llamada principal.

En este caso, la resolucin de la subconsu TOTAL y se compara con los registros de l principal que cumplen la condicin.

Segundo paso: Comparativa de tiempos y costes.


Sentencia usando IN
select nif, apellidos, nombre, cn_sexo, cn_ec from clientes c, sexos s, estadosciviles e, reservas r where c.sex_id_sexo = s.id_sexo and c.ec_id_ec = e.id_ec and c.nif = r.cli_nif and c.ciu_id_ciudad in (select ciu_id_ciudad from agencias a where a.id_agencia = r.age_id_agencia) and r.vue_id_vuelo in (select id_vuelo from vuelos v, aeropuertos ae where v.aer_id_aero = ae.id_aero and ae.ciu_id_ciudad = c.ciu_id_ciudad)

call count ------- -----Parse 1 Execute 1 Fetch 16 ------- -----total 18

cpu elapsed disk query current -------- ---------- ---------- ---------- ---------0.01 0.01 0 0 0 0.00 0.00 0 0 0 0.39 4.65 1676 29917 0 -------- ---------- ---------- ---------- ---------0.40 4.67 1676 29917 0

rows ---------0 0 211 ---------211

Sentencia usando EXISTS


select nif, apellidos, nombre, cn_sexo, cn_ec from clientes c, sexos s, estadosciviles e, reservas r where c.sex_id_sexo = s.id_sexo and c.ec_id_ec = e.id_ec and c.nif = r.cli_nif and exists (select null from agencias a where a.ciu_id_ciudad = c.ciu_id_ciudad and a.id_agencia = r.age_id_agencia) and exists (select null from vuelos v, aeropuertos ae where v.aer_id_aero = ae.id_aero and ae.ciu_id_ciudad = c.ciu_id_ciudad and r.vue_id_vuelo = v.id_vuelo)

call count ------- -----Parse 1 Execute 1 Fetch 16 ------- -----total 18

cpu elapsed disk query current -------- ---------- ---------- ---------- ---------0.01 0.01 0 0 0 0.00 0.00 0 0 0 0.48 11.77 3552 29906 0 -------- ---------- ---------- ---------- ---------0.50 11.78 3552 29906 0

rows ---------0 0 211 ---------211

Uso de EXISTS respecto IN.

EJERCICIO 6: Ciudades origen y destino de vuelos con importes en reservas superiores a 150 euros.

Dada la siguiente consulta:


select cn_ciudad from ciudades where id_ciudad in (select ao.ciu_id_ciudad from aeropuertos ao, aeropuertos ad, vuelos v, reservas r where v.aer_id_aero=ao.id_aero and v.aer_id_aero_destino=ad.id_aero and r.vue_id_vuelo=v.id_vuelo and importe>150) and id_ciudad in (select ad.ciu_id_ciudad from aeropuertos ao, aeropuertos ad, vuelos v, reservas r where v.aer_id_aero=ao.id_aero and v.aer_id_aero_destino=ad.id_aero and r.vue_id_vuelo=v.id_vuelo and importe>150) ;

Obtenemos los siguientes resultados: en devolver 30 filas 0 ordenacin en memria 0 ordenaciones en disco estimacin = 556 Coste tiempo = 5 Segundos

Primer paso: Estudio de la ejecucin.


Execution Plan ---------------------------------------------------------0 SELECT STATEMENT Optimizer=CHOOSE (Cost=566 Card=30 Bytes=480) 1 0 HASH JOIN (SEMI) (Cost=566 Card=30 Bytes=480) 2 1 HASH JOIN (SEMI) (Cost=284 Card=30 Bytes=390) 3 2 TABLE ACCESS (FULL) OF 'CIUDADES' (Cost=2 Card=30 Bytes=300) 4 2 VIEW OF 'VW_NSO_2' (Cost=280 Card=85557 Bytes=256671) 5 4 HASH JOIN (Cost=280 Card=85557 Bytes=2224482) 6 5 TABLE ACCESS (FULL) OF 'AEROPUERTOS' (Cost=2 Card=34 Bytes=170) 7 5 NESTED LOOPS (Cost=274 Card=85557 Bytes=1796697) 8 7 HASH JOIN (Cost=274 Card=85557 Bytes=1540026) 9 8 TABLE ACCESS (FULL) OF 'VUELOS' (Cost=43 Card=57711 Bytes=577110) 10 8 TABLE ACCESS (FULL) OF 'RESERVAS' (Cost=110 Card=85557 Bytes=684456) 11 7 INDEX (UNIQUE SCAN) OF 'AER_PK' (UNIQUE) 12 1 VIEW OF 'VW_NSO_1' (Cost=280 Card=85557 Bytes=256671) 13 12 NESTED LOOPS (Cost=280 Card=85557 Bytes=2224482) 14 13 HASH JOIN (Cost=280 Card=85557 Bytes=1967811) 15 14 TABLE ACCESS (FULL) OF 'AEROPUERTOS' (Cost=2 Card=34 Bytes=170) 16 14 HASH JOIN (Cost=274 Card=85557 Bytes=1540026) 17 16 TABLE ACCESS (FULL) OF 'VUELOS' (Cost=43 Card=57711 Bytes=577110) 18 16 TABLE ACCESS (FULL) OF 'RESERVAS' (Cost=110 Card=85557 Bytes=684456) 19 13 INDEX (UNIQUE SCAN) OF 'AER_PK' (UNIQUE)

Anlisis de la ejecucin: Bsicamente en esta ejecucin hay dos invocaciones por cada fila a una subconsulta de una cardinalidad muy elevada respecto al total de ciudades (card=30). Dado que el acceso mas costoso se encuentra dentro de las subconsultas y que el acceso total a ciudades (nicamente 30 filas), el uso de EXISTS en lugar de IN mejorara los tiempos de acceso. De este modo, las subconsultas se leeran en su totalidad y, a partir de stas, filtraran los resultados sobre el total de ciudades, que resulta un acceso mucho ms rpido. La consulta, expresada con EXISTS, queda tal y como se muestra:
select cn_ciudad from ciudades where exists (select null from aeropuertos ao, aeropuertos ad, vuelos v, reservas r where v.aer_id_aero=ao.id_aero and v.aer_id_aero_destino=ad.id_aero and r.vue_id_vuelo=v.id_vuelo and importe>150) and exists (select null from aeropuertos ao, aeropuertos ad, vuelos v, reservas r where v.aer_id_aero=ao.id_aero and v.aer_id_aero_destino=ad.id_aero and r.vue_id_vuelo=v.id_vuelo and importe>150);

Obtenemos los siguientes resultados: en devolver 30 filas 0 ordenacin en memria 2 ordenaciones en disco estimacin = 2 Coste tiempo = 2 Segundos

Segundo paso: Comparativa de tiempos y costes.

Sentencia usando IN
select cn_ciudad from ciudades where id_ciudad in (select ao.ciu_id_ciudad from aeropuertos ao, aeropuertos ad, vuelos v, reservas r where v.aer_id_aero=ao.id_aero and v.aer_id_aero_destino=ad.id_aero and r.vue_id_vuelo=v.id_vuelo and importe>150) and id_ciudad in (select ad.ciu_id_ciudad from aeropuertos ao, aeropuertos ad, vuelos v, reservas r where v.aer_id_aero=ao.id_aero and v.aer_id_aero_destino=ad.id_aero and r.vue_id_vuelo=v.id_vuelo and importe>150) call count ------- -----Parse 1 Execute 1 Fetch 3 ------- -----total 5 cpu elapsed disk query current -------- ---------- ---------- ---------- ---------0.00 0.20 0 0 0 0.00 0.00 0 0 0 0.62 5.08 2381 3162 0 -------- ---------- ---------- ---------- ---------0.62 5.29 2381 3162 0 rows ---------0 0 30 ---------30

Sentencia usando EXISTS


select cn_ciudad from ciudades where exists (select null from aeropuertos ao, aeropuertos ad, vuelos v, reservas r where v.aer_id_aero=ao.id_aero and v.aer_id_aero_destino=ad.id_aero and r.vue_id_vuelo=v.id_vuelo and importe>150) and exists (select null from aeropuertos ao, aeropuertos ad, vuelos v, reservas r where v.aer_id_aero=ao.id_aero and v.aer_id_aero_destino=ad.id_aero and r.vue_id_vuelo=v.id_vuelo and importe>150) call count ------- -----Parse 1 Execute 1 Fetch 3 ------- -----total 5 cpu elapsed disk query current -------- ---------- ---------- ---------- ---------0.00 0.39 0 0 0 0.15 1.80 1359 2624 4 0.00 0.00 0 9 0 -------- ---------- ---------- ---------- ---------0.15 2.19 1359 2633 4 rows ---------0 0 30 ---------30

Resumen de la prctica.

IN y EXISTS son dos clusulas distintas, que devuelven resultados distintos. IN se basa en la consulta de un valor concreto en un subconjunto de registros. EXISTS se basa en la consulta de un subconjunto de registros respecto un valor concreto.

El uso apropiado de IN y EXISTS viene determinado en si la parte costosa de la ejecucin est en la resolucin de la consulta principal (IN), o si la carga pesada est en la resolucin de la subconsulta (EXISTS). No existe una clusula mejor que otra, slo ms o menos adecuada en funcin de la consulta.

También podría gustarte