2008-09-29 24 views
14

Supongamos que tengo una tabla de base de datos con dos campos, "foo" y "bar". Ninguno de ellos es único, pero cada uno de ellos está indexado. Sin embargo, en lugar de indexarse ​​juntos, cada uno tiene un índice separado.¿Pueden trabajar juntos varios índices?

Ahora supongo que realizo una consulta como SELECT * FROM sometable WHERE foo='hello' AND bar='world'; en mi tabla un gran número de filas para las cuales foo es 'hola' y un pequeño número de filas para las cuales la barra es 'mundial'.

Por lo tanto, lo más eficiente para el servidor de base de datos es usar el índice de barras para encontrar todos los campos donde la barra es 'mundo', luego devolver solo aquellas filas para las cuales foo es 'hola'. Esto es O(n) donde n es el número de filas donde la barra es 'mundo'.

Sin embargo, me imagino que es posible que el proceso ocurra al revés, donde se utilizó el índice fo y se buscaron los resultados. Esto sería O(m) donde m es el número de filas donde foo es 'hola'.

Entonces, ¿Oracle es lo suficientemente inteligente como para buscar de manera eficiente aquí? ¿Qué pasa con otras bases de datos? ¿O hay alguna forma de que pueda decirlo en mi consulta para buscar en el orden correcto? ¿Quizás poniendo bar='world' primero en la cláusula WHERE?

Respuesta

11

Oracle seguramente usará el índice más selectivo para conducir la consulta, y puede verificarlo con el plan de explicación.

Además, Oracle puede combinar el uso de ambos índices de varias maneras: puede convertir btree índices en mapas de bits y realizar un mapa de bits y una operación en ellos, o puede realizar una combinación hash en el rowid devuelto por el dos índices.

Una consideración importante aquí podría ser cualquier correlación entre los valores que se consultan. Si foo = 'hello' representa el 80% de los valores en la tabla y bar = 'world' representa el 10%, Oracle estimará que la consulta arrojará 0.8 * 0.1 = 8% de las filas de la tabla. Sin embargo, esto puede no ser correcto: la consulta puede devolver el 10% de los rwos o incluso el 0% de las filas, dependiendo de qué tan correlacionados estén los valores. Ahora, dependiendo de la distribución de esas filas en toda la tabla, puede que no sea eficiente usar un índice para encontrarlas. Es posible que aún necesite acceder (digamos) al 70% o los bloques de tabla para recuperar las filas requeridas (google para "factor de agrupamiento"), en cuyo caso Oracle realizará una exploración completa de tabla si obtiene la estimación correcta.

En 11g puede recopilar estadísticas de varias columnas para ayudar con esta situación, creo. En 9i y 10g puede usar el muestreo dinámico para obtener una muy buena estimación del número de filas que se recuperarán.

Para obtener el plan de ejecución de hacer esto:

explain plan for 
SELECT * 
FROM sometable 
WHERE foo='hello' AND bar='world' 
/
select * from table(dbms_xplan.display) 
/

contraste que con:

explain plan for 
SELECT /*+ dynamic_sampling(4) */ 
     * 
FROM sometable 
WHERE foo='hello' AND bar='world' 
/
select * from table(dbms_xplan.display) 
/
+1

Con todo Respete a David, mirando los comentarios de Eli a continuación, la respuesta a su pregunta es "use bitmaps". –

+1

Los índices de bitmap son ciertos eficiente en este tipo de consulta, pero son muy hostiles en un entorno OLTP. También vale la pena saber que un par de índices btree se pueden combinar en una operación de mapa de bits, aunque hay una sobrecarga mucho mayor en esto. –

3

Sí, puede dar "consejos" con la consulta a Oracle. Estas sugerencias se disfrazan de comentarios ("/ * HINT * /") a la base de datos y son principalmente específicos del vendedor. Entonces, una sugerencia para una base de datos no funcionará en otra base de datos.

Me gustaría utilizar consejos de índice aquí, la primera pista para la pequeña mesa. Ver here.

Por otro lado, si a menudo busca en estos dos campos, ¿por qué no crea un índice en estos dos? No tengo la sintaxis correcta, pero sería algo así como

CREATE INDEX IX_BAR_AND_FOO on sometable(bar,foo); 

Esta forma de recuperación de datos debe ser bastante rápido. Y en caso de que la concatenación sea única, simplemente crea un índice único que debería ser muy rápido.

+0

Informix también tiene estas cláusulas indirectas. La mayoría de las veces no vas a ayudar al optimizador de esta manera, es bastante bueno en lo que hace. – hometoast

+0

Lamentablemente, tengo una tabla con muchas columnas, cada una con su propio índice. Los usuarios pueden consultar cualquier combinación de campos, por lo que no puedo crear índices de manera eficiente en cada combinación de campos. Pero si solo tuviera dos campos que necesitaran índices, estaría completamente de acuerdo con su sugerencia de usar dos índices. –

+0

Ni siquiera intentes disculparte:). Oracle probablemente usará el "más sensible" en su caso. De nuevo, no debe confiar únicamente en la optimización de Oracle. Pero, por un lado, actualizar el plan de explicación y tratar de mantenerlo actualizado es una buena idea, de todos modos. – Georgi

2

¿Es Oracle suficientemente inteligente para buscar de forma eficiente aquí?

La respuesta simple es "probablemente". Hay muchas personas muy brillantes en cada uno de los proveedores de bases de datos que trabajan en la optimización del optimizador de consultas, por lo que probablemente esté haciendo cosas que ni siquiera había pensado. Y si actualiza las estadísticas, probablemente lo haga aún más.

1

Estoy seguro de que también puede hacer que Oracle muestre un plan de consulta para que pueda ver exactamente qué índice se usa primero.

+0

El "Plan" es solo eso, lo que planea hacer primero. Hay momentos en que eso se desvía de lo que realmente sucede. Necesita generar un seguimiento para obtener exactamente lo que sucedió. –

1

Puede proporcionar sugerencias sobre qué índice usar. No estoy familiarizado con Oracle, pero en Mysql puede usar USE | IGNORE | FORCE_INDEX (consulte here para obtener más información). Para un mejor rendimiento, debe usar un índice combinado.

1

El mejor enfoque sería agregar foo al índice de barras, o agregar una barra al índice de foo (o ambas). Si el índice de foo también contiene un índice en la barra, ese nivel de indexación adicional no afectará la utilidad del índice de foo en ninguno de los usos actuales de ese índice, ni afectará de manera apreciable el rendimiento de mantener ese índice, pero le dará a la base de datos adicional información para trabajar en la optimización de consultas como en el ejemplo.

+0

Actualmente estoy de acuerdo con Jeffrey ... además de lo que dijo, tener dos índices diferentes afectará su velocidad de escritura (porque la base de datos tiene que actualizar dos índices en una escritura en lugar de uno. –

1

Es mejor que eso.

Las búsquedas de índice son siempre más rápidas que las exploraciones de tablas completas. Así que detrás de las escenas, Oracle (y el servidor SQL para el caso) primero localizarán el rango de filas en ambos índices. Luego verá qué rango es más corto (ya que es una unión interna), y repetirá el rango más corto para encontrar las coincidencias con el mayor de los dos.

+1

Primero, no es cierto que el índice las búsquedas son siempre más rápidas que las exploraciones de tablas completas. En Oracle, las lecturas de bloques múltiples para escaneos de tablas completas pueden ser más rápidas que las lecturas de índices de bloque único si se está recuperando más de una pequeña fracción de las filas –

+1

En segundo lugar, el optimizador de Oracle no escanee los dos índices para determinar cuál usar, usará estadísticas en el diccionario de datos para determinar qué índice se espera que sea más selectivo. Esas estadísticas estarán influenciadas por histogramas que definen la selectividad de diferentes valores. –

2

En primer lugar, voy a suponer que usted está hablando agradable, normal, b * estándar - índices de árbol. La respuesta para los índices de mapa de bits es radicalmente diferente. Y hay muchas opciones para varios tipos de índices en Oracle que pueden o no cambiar la respuesta.

Como mínimo, si el optimizador puede determinar la selectividad de una condición en particular, usará el índice más selectivo (es decir, el índice en la barra). Pero si tiene datos asimétricos (hay N valores en la barra de columnas pero la selectividad de cualquier valor particular es sustancialmente mayor o menor que 1/N de los datos), necesitaría tener un histograma en la columna para contar el optimizador cuyos valores son más o menos probables. Y si está utilizando variables de vinculación (como deberían hacerlo todos los buenos desarrolladores de OLTP), dependiendo de la versión de Oracle, puede tener problemas con el examen de variable de vinculación.

Potencialmente, Oracle podría incluso hacer una conversión sobre la marcha de los dos índices b * -árbol a mapas de bits y combinar los mapas de bits para usar ambos índices para encontrar las filas que necesita recuperar. Pero este es un plan de consulta bastante inusual, particularmente si solo hay dos columnas donde una columna es altamente selectiva.

+0

Puntos tomados. uno pensaría que el optimizador de la base de datos compararía el tamaño por defecto. –

3

Eli,

En un comentario que escribió:

Por desgracia, tengo una tabla con muchas columnas, cada una con su propio índice. Los usuarios pueden consultar cualquier combinación de campos, por lo que no puedo crear índices de manera eficiente en cada combinación de campos.Pero si solo tuviera dos campos que necesitaran índices, estaría completamente de acuerdo con su sugerencia de usar dos índices. - Eli Courtwright (29 de septiembre a las 15:51)

Esto es realmente bastante información crucial. A veces los programadores se burlan de sí mismos al hacer preguntas. Intentan destilar la pregunta hasta los puntos más importantes, pero a menudo simplifican y extrañan obtener la mejor respuesta.

Este escenario es precisamente el motivo por el que se inventaron los índices de mapas de bits: para manejar los tiempos en que se utilizarían grupos desconocidos de columnas en una cláusula where.

En caso de que alguien diga que los IMC son solo para columnas de baja cardinalidad y es posible que no se apliquen a su caso. Bajo probablemente no sea tan pequeño como piensas. El único problema real es la concurrencia de DML a la tabla. Debe ser de un solo hilo o raro para que esto funcione.

+1

Leí todos los comentarios y me pregunté por qué nadie estaba diciendo que esto es exactamente por qué se inventaron los bitmaps. +1 –

+0

Gracias por la información; Nunca antes había oído hablar de índices de mapa de bits, así que los investigaré. Puede que sea demasiado tarde para cambiar nuestro diseño de índice actual en este proyecto, pero si tenemos problemas de rendimiento, volveré a los IMC y definitivamente los usaré en futuros proyectos. –

Cuestiones relacionadas