2012-02-07 36 views
7

que tiene un índice en una columna anulable y quiero seleccionar todos los valores es como esto:Índice de columna anulable

SELECT e.ename 
FROM emp e; 

En el plan explicar veo un FULL TABLE SCAN (incluso una pista no ayudó)

SELECT e.ename 
FROM emp e 
WHERE e.ename = 'gdoron'; 

usa el índice ...

Busqué en google y descubrí que no hay entradas nulas en los índices, por lo tanto la primera consulta no puede utilizar el índice.

Mi pregunta es simple: ¿por qué no hay entradas nulas en los índices?

+1

Como un lado, la lata de tabla completa se realizó en su primer ejemplo ya que estaba seleccionando un gran porcentaje de los registros de la tabla (en su caso, 100%). No importa si tenía un índice de valor nulo, el optimizador habría optado por un FTS para esta consulta. – Ollie

+0

@Ollie. Esta es la razón por la que escribí que lo intenté de nuevo con un 'hint' y no ayudó ... – gdoron

+1

, los índices típicos de b-tree no incluirán nulos. Los índices de mapa de bits indexarán nulos. – tbone

Respuesta

14

De forma predeterminada, las bases de datos relacionales ignoran los valores NULL (porque el modelo relacional dice que NULL significa "no presente"). Por lo tanto, Index no almacena el valor NULL, por lo tanto, si tiene una condición nula en la declaración de SQL, se ignora el índice relacionado (por defecto).

Pero puede solucionar este problema, consulte el artículo THIS o THIS.

+0

He leído este artículo, es por eso que estoy preguntando por qué esto está funcionando de esta manera. Es raro. – gdoron

+1

Bueno, piense en esto, en un índice ¿cómo pueden diferenciarse de todos los NULL? –

2

Si obtiene todas las filas de la tabla, ¿por qué cree que debería usar el índice? Una exploración de tabla completa es el medio más eficiente para devolver todos los valores. No tiene nada que ver con que los nulos no estén en el índice y que todo tenga que ver con que el optimizador elija los medios más eficientes para recuperar los datos.


@ A.B.Cade: Es posible que el optimizador pueda elegir usar el índice, pero no es probable. Supongamos que tiene una tabla con una tabla indexada con 100 filas, pero solo 10 valores. Si el optimizador usa el índice, tiene que obtener las 10 filas del índice, luego expandirlo a 100 filas, mientras que, con el escaneo de tabla completa, obtiene las 100 filas desde el principio. He aquí un ejemplo:

create table test1 (blarg varchar2(10)); 

create index ak_test1 on test1 (blarg); 

insert into test1 
select floor(level/10) from dual connect by level<=100; 

exec dbms_stats.gather_table_stats('testschema','test1'); 

exec dbms_stats.gather_index_stats('testschema','ak_test1'); 

EXPLAIN PLAN FOR 
select * from test1; 

Mi punto es en gran parte de que esta cuestión se basa en gran medida en una premisa errónea: que el índice-scans son intrínsecamente mejores que las exploraciones de tabla completa. Eso no siempre es cierto, como lo demuestra este escenario.

+0

vea el comentario de DaveCosta. Está consultando la columna de índice: si no fuera por los nulos, habría utilizado un INDEX FULL SCAN –

+0

Bueno, no podemos decir que definitivamente habría usado el índice, solo que podría haberlo hecho. –

+0

Estoy de acuerdo, pero lo dijo en la pregunta "(incluso una sugerencia no ayudó)" –

0

No estoy seguro de que la primera consulta sea pertinente en términos de uso del índice, al menos la segunda podría.

De todos modos, si bien es cierto que no se puede indexar una columna que contiene un valor nulo, hay maneras de hacerlo, como por ejemplo:

create index MY_INDEX on emp(ename, 1); 

notificación del , 1) al final lo que hace el truco.

+0

¿No quiere decir: 'crear índice MY_INDEX en emp (NVL (ename, 'null'));' – gdoron

+0

no. coma seguida por el dígito 1 es la forma correcta. sin la necesidad de usar nvl. nvl es otro truco para usarlo pero obliga al usuario a comparar con la cadena 'nulo' si se usa tal como lo escribió. – Farid

Cuestiones relacionadas