viernes, 18 de septiembre de 2009

Eficiencia Vs Rapidez, no necesariamente el resultado buscado

La rapidez o velocidad es la relación entre la distancia recorrida y el tiempo empleado en recorrerlo. La eficiencia proviene del latín efficientia que en español quiere decir, acción, fuerza, producción. Se define a la eficiencia, como la capacidad de disponer de alguien o de algo para conseguir un efecto determinado y no debe confundirse con eficiencia, que hace relación a la capacidad de lograr el efecto que se desea o se espera.
En repetidas ocasiones, he hecho referencia a eficiencia en este blog, sin antes aclarar, que el resultado que obtendremos de una práctica o otra, dará como resultado, una forma más rápida de obtener o hacer las cosas.

Por tanto, puede prestarse a múltiples mal entendidos, sobre todo en aquellos lectores que recién inician en este mundo lleno de sorpresas, que se llama "Oracle".
La excasa o poca experiencia, puede ser un mal aliado en estos casos, porque nos llenamos de falsas expectativas al obtener como resultado de la puesta en práctica de algún consejo, un producto no esperado.

Días atrás en un post, hablé como borrar de manera eficiente, registros en una tabla. Posiblemente, alguién ya halla probado el procedimiento y halla sacado sus propias conclusiones, sobre el tema en discusión.

Para aquellos que no han tenido tiempo, les aportó mis propias pruebas, para que ustedes evalúen y saquen sus propias conclusiones, no sin antes evaluar cada una de las variables, que su propio entorno pueda presentar.

Como primer conclusión, Eficiencia no significa, que vamos a obtener mayor rapidez a la hora de obtener un resultado, para muestra, a continuación, podrán observar como un borrado con una declaración simple, sobre una tabla de un poco más de 6 millones de registros, puede ser casí un 40% más veloz - rápido, que utilizar el método del bloque PL/SQL reseñado días atrás.
Sin embargo, las diferencias si son notorias en cuanto a la utilización de recursos. La generación del explain plan de la la declaración SQL utilizada para borrar en la sesión de Oracle con SQL*Plus, guarda mucha distancia en relación a las dos consultas utilizadas en el bloque PL/SQL. El costo en CPU, utilizado por la declaración " delete pruebas_borrado where periodo='2002' ", de 1660 es significativamente muchas veces más alto que el costo de 16 de cada una de las dos instrucciones del bloque PL/SQL.

Aquí podemos afirmar, nuestra segunda conclusión, la forma de borrar registros del bloque PL/SQL es más eficiente que la instrucción utilizada a nivel del SQL.

Sin embargo, derivado de los resultados que obtuvimos del ejemplo mostrado abajo, se desprende la tercera conclusión, Eficiencia no es lo mismo que rapidez. El bloque PL/SQL emplea entre un 30% a un 40% más de tiempo en ejecutar el borrado de la tabla. La diferencia podría ser marcada, al ejecutar el "commit" ( fijación ) de los datos dentro del ciclo "LOOP" y así minimizar el bloqueo sobre el objeto y aumentar la disponibilidad del mismo.
Usted deberá evaluar, que es lo que más requiere o o se ajusta a sus necesidades en su instalación.
Con esto, espero haberles ayuda a diferenciar y ha emplear de una forma más correcta, la interpretación de estos dos conceptos.

SQL> set timing on
SQL> select count(*) from pruebas_borrado;

COUNT(*)
----------
6445961

Elapsed: 00:00:19.43
SQL> select count(*), periodo from pruebas_borrado group by periodo;

COUNT(*) PERI
---------- ----
326249 2009
785274 2006
537067 2001
739987 2008
801901 2004
754343 2005
861277 2002
857697 2003
782166 2007

9 rows selected.

Elapsed: 00:00:19.71


Elapsed: 00:00:00.02
SQL> delete pruebas_borrado where periodo='2002';

861277 rows deleted.

Elapsed: 00:01:00.37
SQL> commit;

Commit complete.

Elapsed: 00:00:00.01

SQL> DECLARE
2 CURSOR c1 IS SELECT rowid from pruebas_borrado where periodo in ('2004','2003');
3 emp_rec c1%ROWTYPE;
4 BEGIN
5 OPEN c1;
6 LOOP
7 FETCH c1 INTO emp_rec;
8 EXIT WHEN c1%NOTFOUND;
9 DELETE FROM pruebas_borrado WHERE rowid = emp_rec.rowid;
10 END LOOP;
11 commit;
12 CLOSE c1;
13 END;
14 /

PL/SQL procedure successfully completed.

Elapsed: 00:02:41.32
SQL> DECLARE
2 CURSOR c1 IS SELECT rowid from pruebas_borrado where periodo in ('2005');
3 emp_rec c1%ROWTYPE;
4 BEGIN
5 OPEN c1;
6 LOOP
7 FETCH c1 INTO emp_rec;
8 EXIT WHEN c1%NOTFOUND;
9 DELETE FROM pruebas_borrado WHERE rowid = emp_rec.rowid;
10 END LOOP;
11 commit;
12 CLOSE c1;
13 END;
14 /

PL/SQL procedure successfully completed.

Elapsed: 00:01:34.95
SQL> DECLARE
2 CURSOR c1 IS SELECT rowid from pruebas_borrado where periodo ='2007';
3 emp_rec c1%ROWTYPE;
4 BEGIN
5 OPEN c1;
6 LOOP
7 FETCH c1 INTO emp_rec;
8 EXIT WHEN c1%NOTFOUND;
9 DELETE FROM pruebas_borrado WHERE rowid = emp_rec.rowid;
10 END LOOP;
11 commit;
12 CLOSE c1;
13 END;
14 /

PL/SQL procedure successfully completed.

Elapsed: 00:01:29.66
SQL> select count(*), periodo from pruebas_borrado group by periodo;

COUNT(*) PERI
---------- ----
326249 2009
785274 2006
537067 2001
739987 2008

Elapsed: 00:00:22.40

Dueño de la tabla: T1
Nombre de la tabla: PRUEBAS_BORRADO

Información General de la tabla: T1.PRUEBAS_BORRADO

OWNER TABLE_NAME TABLESPACE_NAME PCT_FREE BLOCKS EMPTY_BLOCKS
--------------- ------------------------- ------------------
T1 PRUEBAS_BORRADO USERS 10

SQL> create index idx_pruebas_periodo on pruebas_borrado(periodo);
Elapsed: 00:00:39.12

SQL> select count(*), periodo from pruebas_borrado group by periodo;

Información de Dependencias en la tabla: T1.PRUEBAS_BORRADO

COUNT(*) PERI
---------- ----
326249 2009
785274 2006
537067 2001
739987 2008
Elapsed: 00:00:02.07

SQL> explain plan for
2 delete pruebas_borrado where periodo='2006';
Elapsed: 00:00:01.10

SQL> select * from table(dbms_xplan.display);

Información de Dependencias en la tabla: T1.PRUEBAS_BORRADO

PLAN_TABLE_OUTPUT
-------------------------------------------------------------------
Plan hash value: 3245470661

-------------------------------------------------------------------
Id Operation Name Rows Bytes Cost (%CPU) Time
-------------------------------------------------------------------
0 DELETE STATEMENT 733K 2866K 1660 (2) 00:00:20
1 DELETE PRUEBAS_BORRADO
* 2 INDEX RANGE SCAN IDX_PRUEBAS_PERIODO 733K 2866K 1660 (2) 00:00:20
-----------------------------------------------------------------------------------------

Información de Dependencias en la tabla: T1.PRUEBAS_BORRADO

PLAN_TABLE_OUTPUT
----------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

2 - access("PERIODO"='2006')

Note
-----
- dynamic sampling used for this statement
Elapsed: 00:00:01.55

SQL> delete pruebas_borrado where periodo='2006';
Elapsed: 00:00:51.10

SQL> rollback;
Elapsed: 00:01:00.69

SQL> DECLARE
2 CURSOR c1 IS SELECT rowid from pruebas_borrado where periodo ='2008';
3 emp_rec c1%ROWTYPE;
4 BEGIN
5 OPEN c1;
6 LOOP
7 FETCH c1 INTO emp_rec;
8 EXIT WHEN c1%NOTFOUND;
9 DELETE FROM pruebas_borrado WHERE rowid = emp_rec.rowid;
10 END LOOP;
11 commit;
12 CLOSE c1;
13 END;
14 /
Elapsed: 00:01:22.98

SQL> explain plan for
2 SELECT rowid from pruebas_borrado where periodo ='2008';
Elapsed: 00:00:02.01

SQL> select * from table(dbms_xplan.display);

Información de Dependencias en la tabla: T1.PRUEBAS_BORRADO

PLAN_TABLE_OUTPUT
------------------------------------------------------------------------------------
Plan hash value: 1733812795

----------------------------------------------------------------------------------------
Id Operation Name Rows Bytes Cost (%CPU) Time
----------------------------------------------------------------------------------------
0 SELECT STATEMENT 1 16 2 (0) 00:00:01
* 1 INDEX RANGE SCAN IDX_PRUEBAS_PERIODO 1 16 2 (0) 00:00:01
----------------------------------------------------------------------------------------


Información de Dependencias en la tabla: T1.PRUEBAS_BORRADO

PLAN_TABLE_OUTPUT
--------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------

1 - access("PERIODO"='2008')

Note
-----
- dynamic sampling used for this statement
Elapsed: 00:00:00.52

SQL> explain plan for
2 DELETE FROM pruebas_borrado WHERE rowid = 'EEIEIIEIEI';

Elapsed: 00:00:00.02
SQL> select * from table(dbms_xplan.display);

Información de Dependencias en la tabla: T1.PRUEBAS_BORRADO

PLAN_TABLE_OUTPUT
----------------------------------------------------
Plan hash value: 2017434225

-----------------------------------------------------------------------------------------------
Id Operation Name Rows Bytes Cost (%CPU) Time
-----------------------------------------------------------------------------------------------
0 DELETE STATEMENT 1 16 1 (0) 00:00:01
1 DELETE PRUEBAS_BORRADO
* 2 TABLE ACCESS BY USER ROWID PRUEBAS_BORRADO 1 16 1 (0) 00:00:01
-----------------------------------------------------------------------------------------------

Información de Dependencias en la tabla: T1.PRUEBAS_BORRADO

PLAN_TABLE_OUTPUT
------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

2 - access(CHARTOROWID('EEIEIIEIEI'))
Elapsed: 00:00:00.10



No hay comentarios:

Publicar un comentario

Te agradezco tus comentarios. Te esperamos de vuelta.

Todos los Sábados a las 8:00PM

Optimismo para una vida Mejor

Optimismo para una vida Mejor
Noticias buenas que comentar