Pregunta

Supongamos que tengo una tabla de base de datos con dos campos, " foo " y " barra " ;. Ninguno de ellos es único, pero cada uno de ellos está indexado. Sin embargo, en lugar de estar indexados juntos, cada uno tiene un índice separado.

Ahora supongamos que realizo una consulta como SELECT * FROM sometable WHERE foo = 'hello' AND bar = 'world'; Mi tabla tiene un gran número de filas para las que foo es 'hello' y un pequeño número de filas para las que la barra es 'mundo'.

Así que lo más eficiente que puede hacer el servidor de base de datos bajo el capó es usar el índice de barras para encontrar todos los campos donde la barra es 'mundo', y luego devolver solo aquellas filas para las que 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 a la inversa, donde se usó 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, ¿es Oracle lo suficientemente inteligente como para buscar de manera eficiente aquí? ¿Qué pasa con otras bases de datos? ¿O hay alguna forma en que pueda indicarlo en mi consulta para buscar en el orden correcto? Quizás al poner bar = 'world' primero en la cláusula WHERE ?

¿Fue útil?

Solución

Es casi seguro que Oracle utilizará el índice más selectivo para dirigir 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 los índices de btree en mapas de bits y realizar una operación AND de mapa de bits, o puede realizar una combinación hash en el rowid devuelto por los 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%, entonces Oracle estimará que la consulta devolverá 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, según la correlación de los valores. Ahora, dependiendo de la distribución de esas filas en 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 la tabla para recuperar las filas requeridas (google para " factor de agrupación "), en cuyo caso Oracle realizará un escaneo completo de la tabla si la estimación es 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 haga esto:

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

Contraste eso con:

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

Otros consejos

Sí, puedes dar " sugerencias " Con la consulta a Oracle. Estas sugerencias se disfrazan como comentarios (" / * HINT * / ") a la base de datos y son principalmente específicas del proveedor. Por lo tanto, una sugerencia para una base de datos no funcionará en otra base de datos.

Aquí usaría sugerencias de índice, la primera sugerencia para la tabla pequeña. Consulte aquí .

Por otra parte, si busca a menudo en estos dos campos, ¿por qué no crear 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);

De esta manera, la recuperación de datos debería ser bastante rápida. Y en caso de que la concatenación sea única, simplemente cree un índice único que debería ser muy rápido.

Eli,

En un comentario que escribiste:

  

Desafortunadamente, 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 necesiten índices, estaría completamente de acuerdo con su sugerencia de usar dos índices. & # 8211; Eli Courtwright (29 de septiembre a las 15:51)

Esta es en realidad una información bastante crucial. A veces los programadores se burlan de sí mismos cuando hacen preguntas. Intentan destilar la pregunta a los puntos seminales, pero a menudo simplifican en exceso y obtienen la mejor respuesta.

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

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

  

Así es Oracle lo suficientemente inteligente como para buscar   eficientemente aquí?

La respuesta simple es " probablemente " ;. Hay muchas personas muy inteligentes 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 en las que ni siquiera ha pensado. Y si actualiza las estadísticas, es probable que haga aún más.

En primer lugar, asumiré que está hablando de índices b * -tree estándar, normales y agradables. 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 particular, usará el índice más selectivo (es decir, el índice en la barra). Pero si tiene datos sesgados (hay N valores en la barra de columnas, pero la selectividad de cualquier valor en particular es sustancialmente mayor o menor que 1 / N de los datos), debe tener un histograma en la columna para indicar El optimizador de qué valores son más o menos probables. Y si está utilizando variables de enlace (como deberían hacerlo todos los buenos desarrolladores de OLTP), dependiendo de la versión de Oracle, puede tener problemas con la búsqueda de variables de enlace.

Potencialmente, Oracle podría incluso hacer una conversión sobre la marcha de los dos índices b * -tree 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, especialmente si solo hay dos columnas donde una columna es altamente selectiva.

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.

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

El mejor enfoque sería agregar foo al índice de la barra, o agregar la barra al índice de foo (o ambos). 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 ningún uso actual de ese índice, ni afectará de manera apreciable el rendimiento del mantenimiento de ese índice, pero dará a la base de datos adicional información para trabajar en la optimización de consultas como en el ejemplo.

Es mejor que eso.

Las búsquedas de índice son siempre más rápidas que las exploraciones de tabla completa. Entonces, detrás de escena, Oracle (y el servidor SQL para esa materia) primero ubicarán el rango de filas en ambos índices. A continuación, observará qué rango es más corto (ya que es una combinación interna), y recorrerá el rango más corto para encontrar las coincidencias con la más grande de las dos.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top