Oracle 11g - Exists ou IN

Pessoal,

O que é mais rápido, utilizar Exists ou IN em consultas SQL no Oracle? A resposta é: depende!

No exemplo abaixo crio uma tabela TB_IMPORTACAO e alimento esta tabela com: Objetos e seus respectivos tipos que foram criados no banco Oracle. Realizo o insert de uma massa de dados na mesma tabela de importação para teste.



Connected to Oracle Database 11g Enterprise Edition Release 11.2.0.4.0 

SQL> 
SQL> create table tb_importacao as
2  select a.object_name,
3         a.object_type
4    from all_objects a;

Table created

SQL> 
SQL> begin
2    for x in 1..20
3    loop
4      insert into tb_importacao
5      select a.object_name, a.object_type from all_objects a;
6    end loop;
7  
8  commit;
9  end;
10  /

PL/SQL procedure successfully completed

Crio a tabela TB_CONTROLE com os objetos que já foram importados, tabela essa que será utilizada em nossa subconsulta. Esta tabela contem apenas os tipos dos objetos criados no banco, como: TABLE, VIEW, INDEX etc.

Em seguida realizo uma contagem nas duas tabelas para termos em mente a massa de dados que estamos trabalhando, temos:

TB_MPORTACAO com 4 milhões de registros
TB_CONTROLE com 236 mil registros. (Estes valores estão duplicados na base).

SQL> create table tb_controle as
2  select a.object_type
3    from all_objects a;

Table created

SQL> select count(*) from tb_importacao;

COUNT(*)
----------
4970931

SQL> select count(*) from tb_controle;

COUNT(*)
----------
236712

Realizamos agora o comparativo entre duas consultas, utilizando o IN e o EXISTS.
Identificamos neste primeiro caso que com a utilização do exists foi 25% mais rápido!

SQL> select count(*)
2    from tb_importacao a
3   where a.object_type in (select b.object_type
4                             from tb_controle b);

COUNT(*)
----------
4970931

Executed in 1,218 seconds

SQL> 
SQL> select count(*)
2    from tb_importacao a
3   where exists (select 1
4                   from tb_controle b
5                   where b.object_type = a.object_type);

COUNT(*)
----------
4970931

Executed in 0,968 seconds

Agora em outro teste, criamos a tabela TB_CONTROLE_32 que contem valores únicos dos tipos de objetos criados no banco onde utilizaremos em nossa subconsulta! Esta tabela tem apenas 32 registros e são distintos.

SQL> create table tb_controle_32 as
2  select distinct a.object_type
3    from all_objects a;

Table created

SQL> select count(*) from tb_controle_32;

COUNT(*)
----------
32 

Realizamos agora o mesmo comparativo utilizando IN e EXISTS, porem, em nossa subconsulta a tabela de controle com 32 registros distintos.

SQL> select count(*)
2    from tb_importacao a
3   where a.object_type in (select b.object_type
4                             from tb_controle_32 b);

COUNT(*)
----------
4970931

Executed in 1,015 seconds

SQL> 
SQL> select count(*)
2    from tb_importacao a
3   where exists (select 1
4                   from tb_controle_32 b
5                  where b.object_type = a.object_type);

COUNT(*)
----------
4970931

Executed in 1,156 seconds

Neste ultimo caso com a utilização do IN foi mais rápido!

Em resumo sobre Exists X IN, podemos dizer:

Baixa quantidade registros na subconsulta ou listas de valores pequenas, o IN tende a ser melhor.
Valores(lista) únicos na subconsulta, o IN tende a ser melhor.
Alta quantidade de registros na subconsulta, o Exists tende a ser melhor.
Valores duplicados na subconsulta, o Exists tende a ser melhor.

O melhor sempre, TESTE!

Abraço,

Ronaldo

Nenhum comentário:

Postar um comentário