dbms_random 10g vs dbms_random 11g

Como curiosidade de fim de semana, deixo-vos aqui umas considerações sobre o dbms_random do Oracle
e como se comporta de forma diferenciada entre as versões 10g e 11g.

Para a versão 10.2.0.1.0 (10g):

 

SQL>  select 'SLB' from dual where dbms_random.value = dbms_random.value;

no rows selected

O resultado é esperado, e a probabilidade de resultarem dois valores iguais é muito baixa, como tal,
assume-se de repente que a função dbms_random.value é executada duas vezes gerando valores “aleatórios”
distintos.

Vamos confirmar isto com recurso ao plano de execução da query:


SQL> explain plan for select 'SLB' from dual where dbms_random.value = dbms_random.value;

Explained.

PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------
Plan hash value: 4034615273

-----------------------------------------------------------------
| Id | Operation | Name | Rows | Cost (%CPU)| Time |
-----------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 2 (0)| 00:00:01 |
|* 1 | FILTER | | | | |
| 2 | FAST DUAL | | 1 | 2 (0)| 00:00:01 |
-----------------------------------------------------------------

Predicate Information (identified by operation id):

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

1 - filter("DBMS_RANDOM"."VALUE"()="DBMS_RANDOM"."VALUE"())

14 rows selected.

 

Como podem perceber pela execução, a função dbms_random.value é executada duas vezes o que permite um valor aleatório para as duas chamadas. É, parece-me a mim, e muita gente discorda, o comportamento correcto neste caso, mas parece que a Oracle não tem a mesma opinião e decidiu fazer uns ajustes ao CBO…

Para a versão 11.2.0.2.0 (XE Beta) 11g, as coisas mudam de figura. Vejamos a mesma query:


SQL> select 'SLB' from dual where dbms_random.value=dbms_random.value;

'SL
---
SLB

O registo é devolvido, garantindo assim que a condição é TRUE e como tal ambos os valoes
de random devem ser iguais. Confirmando isto com o plano:

 


PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------
Plan hash value: 4034615273

-----------------------------------------------------------------
| Id | Operation | Name | Rows | Cost (%CPU)| Time |
-----------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 2 (0)| 00:00:01 |
|* 1 | FILTER | | | | |
| 2 | FAST DUAL | | 1 | 2 (0)| 00:00:01 |
-----------------------------------------------------------------

Predicate Information (identified by operation id):

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

1 - filter("DBMS_RANDOM"."VALUE"() IS NOT NULL)

14 rows selected.

O predicado confirma, o CBO desta versão 11g, percebe que a função é exactamente a mesma, com os mesmo parâmetros (nenhum neste caso) e a execução é unica resultando o mesmo número.
Do ponto de vista de performance faz todo o sentido que assim seja, a função é exactamente a mesma (mesma hash/timestamp), e os parâmetros são os mesmos, o resultado deve ser em qualquer circunstância o mesmo…para uma função que não fosse para gerar números “aleatórios”.

Para finalizar veremos apenas que mudando os parâmetros da função, o CBO irá como esperado
executar duas chamadas:

 

SQL> select 'SLB' from dual where dbms_random.value(1,5) = dbms_random.value(1,6);

no rows selected


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

PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------
Plan hash value: 4034615273

-----------------------------------------------------------------
| Id | Operation | Name | Rows | Cost (%CPU)| Time |
-----------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 2 (0)| 00:00:01 |
|* 1 | FILTER | | | | |
| 2 | FAST DUAL | | 1 | 2 (0)| 00:00:01 |
-----------------------------------------------------------------

Predicate Information (identified by operation id):

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

1 - filter("DBMS_RANDOM"."VALUE"(1,5)="DBMS_RANDOM"."VALUE"(1,6))

14 rows selected.

Esta parte I está terminada, poderei em breve tecer algumas mais considerações sobre este assunto..ou não 😉

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s