jueves, febrero 20, 2014

La autoridad de ORDER BY

Para que el resultado de una consulta SQL esté ordenado, la única cláusula válida es ORDER BY.

Oracle únicamente garantiza la devolución ordenada de las filas cuando se establece ORDER BY como criterio de ordenación.

He repetido estas dos frases como un mantra miles de veces.

Cualquier otra forma de obtener los datos ordenados es:
  • Una casualidad.
  • Una ilusión.
  • Una circunstancia temporal.
  • Una combinación de las anteriores.
Los ejemplos que mostraré a continuación, de resultados ordenados sin cláusula ORDER BY en el comando SELECT, son fruto de su imaginación...


FALSO MITO #1 - Si las filas se insertaron de forma ordenada.

SQL> create table objetos as select object_id, object_name, object_type 
   2  from dba_objects order by object_id;

Table created.

SQL> select * from objetos where rownum<10 font="">

 OBJECT_ID OBJECT_NAME          OBJECT_TYPE
---------- -------------------- -------------------
         2 C_OBJ#               CLUSTER
         3 I_OBJ#               INDEX
         4 TAB$                 TABLE
         5 CLU$                 TABLE
         6 C_TS#                CLUSTER
         7 I_TS#                INDEX
         8 C_FILE#_BLOCK#       CLUSTER
         9 I_FILE#_BLOCK#       INDEX
        10 C_USER#              CLUSTER

9 rows selected.


FALSO MITO #2 - Si se accede a las filas mediante un índice.

SQL> create table objetos_indice as select object_id, object_name, object_type 
   2  from dba_objects;

Table created.

SQL> create index idx_object_id on objetos_indice (object_id);

Index created.

SQL> select * from objetos_indice where object_id between 11256 and 11260;

 OBJECT_ID OBJECT_NAME          OBJECT_TYPE
---------- -------------------- -------------------
     11256 ALL_APPLY            SYNONYM
     11257 DBA_APPLY_PARAMETERS VIEW
     11258 DBA_APPLY_PARAMETERS SYNONYM
     11259 ALL_APPLY_PARAMETERS VIEW
     11260 ALL_APPLY_PARAMETERS SYNONYM


FALSO MITO #3 - Si la tabla tiene estructura IOT.

SQL> create table objetos_iot
  2  (object_id, object_name, object_type,
  3   constraint pk_objetos_iot primary key (object_id))
  4  organization index
  5  as select object_id, object_name, object_type
  6  from dba_objects;

Table created.

SQL> select * from objetos_iot where object_id between 11256 and 11265;

 OBJECT_ID OBJECT_NAME                    OBJECT_TYPE
---------- ------------------------------ -------------------
     11256 ALL_APPLY                      SYNONYM
     11257 DBA_APPLY_PARAMETERS           VIEW
     11258 DBA_APPLY_PARAMETERS           SYNONYM
     11259 ALL_APPLY_PARAMETERS           VIEW
     11260 ALL_APPLY_PARAMETERS           SYNONYM
     11261 _DBA_APPLY_SOURCE_SCHEMA       VIEW
     11262 _DBA_APPLY_SOURCE_OBJ          VIEW
     11263 DBA_APPLY_INSTANTIATED_OBJECTS VIEW
     11264 DBA_APPLY_INSTANTIATED_OBJECTS SYNONYM
     11265 ALL_APPLY_INSTANTIATED_OBJECTS VIEW

10 rows selected.


FALSO MITO #4 - Si la tabla tiene estructura de cluster.

SQL> create cluster clu_objetos (object_id number) tablespace test;

Cluster created.


SQL> create index idx_cluster_objetos on cluster clu_objetos;

Index created.

SQL> create table padre_objeto (id number constraint pk_objeto primary key) cluster clu_objetos(id);

Table created.

SQL> insert into padre_objeto values (1);

1 row created.

SQL> insert into padre_objeto values (2);

1 row created.

SQL> insert into padre_objeto values (3);

1 row created.

SQL> insert into padre_objeto values (4);

1 row created.

SQL> insert into padre_objeto values (5);

1 row created.

SQL> insert into padre_objeto values (6);

1 row created.

SQL> create table hijo_objeto (id number constraint fk_objeto_padre references padre_objeto(id)) cluster clu_objetos(id);

Table created.

SQL> insert into hijo_objeto values (3);

1 row created.

SQL> insert into hijo_objeto values (6);

1 row created.

SQL> insert into hijo_objeto values (5);

1 row created.

SQL> insert into hijo_objeto values (2);

1 row created.

SQL> select * from hijo_objeto;

        ID
----------
         2
         3
         5
         6



FALSO MITO #5 - Si la sentencia utiliza DISTINCT.

SQL> create table test_orden (texto varchar2(50));

Table created.

SQL> insert into test_orden values ('PPPPP');

1 row created.

SQL> insert into test_orden values ('FFFFF');

1 row created.

SQL> insert into test_orden values ('ZZZZZ');

1 row created.

SQL> insert into test_orden values ('AAAAA');


1 row created.

SQL> select texto from test_orden;

TEXTO
--------------------------------------------------
PPPPP
FFFFF
ZZZZZ
AAAAA


SQL> select distinct texto from test_orden;

TEXTO
--------------------------------------------------
AAAAA
FFFFF
PPPPP
ZZZZZ



FALSO MITO #6 - Si la sentencia utiliza GROUP BY.

SQL> select texto from test_orden;

TEXTO
--------------------------------------------------
PPPPP
FFFFF
ZZZZZ
AAAAA

SQL> select texto from test_orden group by texto;

TEXTO
--------------------------------------------------
AAAAA
FFFFF
PPPPP

ZZZZZ


FALSO MITO #7 - Si la sentencia utiliza realiza una join de tipo MERGE JOIN.

SQL> create table test_orden2 as select * from test_orden;


Table created.

SQL> select /*+USE_MERGE(t,t2) */ t.texto
  2  from test_orden t, test_orden2 t2
  3  where t.texto=t2.texto;

TEXTO
--------------------------------------------------
AAAAA
FFFFF
PPPPP
ZZZZZ



OLVIDEN ESTOS EJEMPLOS!!!!
NO TRATEN DE IMPLEMENTARLOS EN PRODUCCIÓN!!!!

Todas estas ordenaciones casuales, sin uso de la cláusula ORDER BY, son sólo fruto de su imaginación...




¿Te ha parecido interesante esta entrada? 
Si es así, échale un ojo a mi libro sobre Optimización SQL en Oracle.

1 comentario:

Anibal dijo...

Javier Gracias por compartir, A traves del tiempo el optimizador de costos de oracle 7,8,9,10,11 y ahora 12 a cambiado. Un buen dba sabe que siempre confirma no asume , por tanto de incluir un order by para garantizar la salida.

Amazon