2009-12-03 17 views
25

me encontré con esta pregunta en una entrevista y no tenía ni idea de cómo responder:Fuerza utiliza en el índice de Oracle

hay una tabla que tiene un índice en una columna, y su búsqueda:

select * from table_name where column_having_index="some value"; 

La consulta lleva demasiado tiempo y descubre que el índice no se está utilizando. Si cree que el rendimiento de la consulta será mejor utilizando el índice, ¿cómo podría obligar a la consulta a utilizar el índice?

Respuesta

37

Puede utilizar el optimizador insinúa

select /*+ INDEX(table_name index_name) */ from table etc ...

más sobre el uso sugerencias del optimizador: http://download.oracle.com/docs/cd/B19306_01/server.102/b14211/hintsref.htm

+1

Además, en las versiones más recientes de Oracle (10g + creo) puede especificar el nombre de la columna en lugar del nombre del índice, p. Ej. '/ * + INDEX (table_name column_having_index) * /' –

+1

/* + INDEX (table_name (column_having_index)) */... opr ver mi respuesta para una sintaxis más compleja –

+1

La sintaxis correcta es (¡tienes que usar alias de tabla!): select/* + INDEX (xxxTABLExxx index_name) */from table_name xxxTABLExxx – xnagyg

-4

que puede utilizar:

WITH index = ... 

more info

+0

ohh ... pensaste que te refieres a MS-Sql ... pero te da la idea :) – Leon

2

Hay un índice apropiado en column_having_index, y su uso en realidad aumenta el rendimiento, pero Oracle no lo usó ...
Debe recopilar las estadísticas en su tabla para que el optimizador vea que el acceso al índice puede ayudar. Usar una indirecta directa no es una buena práctica.

+1

Indicaciones de indización sin duda se deben utilizar con moderación pero hay un montón de legitimidad situaciones para usarlos. Un ejemplo es cuando las estadísticas no están disponibles para demostrar que los valores de columna están fuertemente correlacionados, y la CBO infiere una cardinalidad incorrecta para los predicados en columnas múltiples. –

+1

David, en cuanto a la pregunta, el ejemplo es tan simple que no veo ningún motivo para que CBO no use el índice para guardar las estadísticas incorrectas. Pero, en general, tienes razón, por supuesto. –

13

Podría haber muchas razones para índice que no se utiliza. Incluso después de specify hints, existen posibilidades de que el optimizador de Oracle piense lo contrario y decidan no usar el índice. Debe revisar la parte del PLAN DE EXPLICACIÓN y ver cuál es el costo de la declaración con INDICE y sin ÍNDICE.

Asumiendo el Oracle uses CBO. Muy a menudo, si el optimizador cree que el costo es alto con INDEX, aunque lo especifique en sugerencias, el optimizador lo ignorará y continuará para el escaneo completo de la tabla. Su primera acción debería ser verificar DBA_INDEXES para saber cuándo las estadísticas están LAST_ANALYZED. Si no se analiza, puede set table, index for analyze.

begin 
    DBMS_STATS.GATHER_INDEX_STATS (OWNNAME=>user 
           , INDNAME=>IndexName); 
end; 

Para la mesa.

begin 
    DBMS_STATS.GATHER_TABLE_STATS (OWNNAME=>user 
           , TABNAME=>TableName); 
end; 

En casos extremos, puede intentar setting up the statistics por su cuenta.

+0

La CBO "siempre" respetará todas las * indicaciones correctamente especificadas *; no tiene libertad para "elegir" arbitrariamente para no respetar una pista. –

+4

Recientemente hemos actualizado ORA 9208 de ORA 9205, después de eso, experimentamos esto, hubo una consulta compleja, no se utilizó INDEX. Lo forcé con la SUGERENCIA. Aunque EXPLAIN_PLAN mostró que usaba INDEX, cuando se ejecutó tomó la ruta diferente. Fue entonces cuando DBA nos sugirió volver a escribir el SQL. Y lo hicimos, funcionó. – Guru

9

Si cree que el rendimiento de la consulta será mejor con el índice, ¿cómo podría obligar a la consulta a usar el índice?

Primero, por supuesto, verificar que el índice dio un mejor resultado para devolver el conjunto completo de datos, ¿verdad?

La sugerencia de índice es la clave aquí, pero la manera más actualizada de especificarlo es con el método de denominación de columna en lugar del método de denominación de índice. En su caso, usted usaría:

select /*+ index(table_name (column_having_index)) */ * 
from table_name 
where column_having_index="some value"; 

En casos más complejos podría ...

select /*+ index(t (t.column_having_index)) */ * 
from my_owner.table_name t, 
     ... 
where t.column_having_index="some value"; 

Con respecto a los índices compuestos, no estoy seguro de que necesidad de especificar todas las columnas, pero parece una buena idea. Vea los documentos aquí http://docs.oracle.com/cd/E11882_01/server.112/e26088/sql_elements006.htm#autoId18 en multiple index_specs y use index_combine para múltiples índices, y aquí http://docs.oracle.com/cd/E11882_01/server.112/e26088/sql_elements006.htm#BABGFHCH para la especificación de múltiples columnas en index_spec.

+0

¿Qué tal si el índice involucra múltiples columnas? ¿Debo especificarlos todos? – shindigo

+0

Se mejoró la respuesta para varias columnas, @shindigo –

Cuestiones relacionadas