He estado leyendo composite indexes
y estoy un poco confundido acerca de ordenar. Esta documentación (poco menos de la mitad) dice
En general, debe colocar la columna que se espera que se use con mayor frecuencia primero en el índice.
Sin embargo, poco después dice
cree un índice compuesto poniendo primero la columna más selectiva; es decir, la columna con más valores.
Oracle también lo dice aquí en otras palabras
Si todas las claves se usan en las cláusulas WHERE con la misma frecuencia, entonces ordenar estas claves de la más selectiva a la menos selectiva en la instrucción CREATE INDEX mejora el rendimiento de la consulta.
Sin embargo, he encontrado una respuesta SO que dice de manera diferente. Dice
Organice las columnas con la columna menos selectiva primero y la columna más selectiva al final. En el caso de un empate con la columna, es más probable que se use solo.
La primera documentación a la que me referí dice que primero debes usar el más utilizado, mientras que la respuesta SO dice que solo debe ser para romper el empate. Entonces también difieren en el pedido.
Esta documentación también habla skip scanning
y dice
El escaneo de omisión es ventajoso si hay pocos valores distintos en la columna inicial del índice compuesto y muchos valores distintos en la clave no líder del índice.
Otro artículo dice
La columna de prefijo debe ser la más exigente y la más utilizada en las consultas.
que creo que más discriminatorio significaría más distintivo.
Toda esta investigación todavía me lleva a la misma pregunta; ¿La columna más selectiva debe ser la primera o la última? ¿Debería ser la primera columna la más utilizada y la más selectiva en un desempate?
Estos artículos parecen estar contradiciéndose entre sí, pero ofrecen algunos ejemplos. Por lo que he reunido, parece ser más eficiente least selective column
que sea el primero en el pedido si está anticipando Index Skip Scans
. Pero no estoy realmente seguro de si eso es correcto.
fuente
Respuestas:
De AskTom
Uno de los argumentos para organizar columnas en el índice compuesto en orden desde el menos discriminatorio (valores menos distintos) hasta el más discriminatorio (valores más distintos) es para la compresión de clave de índice.
Según las estadísticas del índice, el primer índice es más compresible.
Otra es cómo se usa el índice en sus consultas. Si sus consultas usan principalmente
col1
,Por ejemplo, si tiene consultas como:
select * from t where col1 = :a and col2 = :b;
select * from t where col1 = :a;
-Entonces
index(col1,col2)
se desempeñaría mejor.Si sus consultas usan principalmente
col2
,select * from t where col1 = :a and col2 = :b;
select * from t where col2 = :b;
-luego
index(col2,col1)
se desempeñaría mejor. Si todas sus consultas siempre especifican ambas columnas, no importa qué columna aparezca primero en el índice compuesto.En conclusión, las consideraciones clave en el orden de las columnas del índice compuesto son la compresión de la clave del índice y cómo va a utilizar este índice en sus consultas.
Referencias
fuente
Lo más selectivo primero es útil solo cuando esta columna está en la cláusula WHERE real.
Cuando SELECT es por un grupo más grande (menos selectivo), y luego posiblemente por otros valores no indexados, un índice con columnas menos selectivas aún puede ser útil (si hay una razón para no crear otro).
Si hay una tabla DIRECCIÓN, con
COUNTRY CITY STREET, algo más ...
indexar STREET, CITY, COUNTRY generará las consultas más rápidas con el nombre de una calle. Pero al consultar todas las calles de una ciudad, el índice será inútil y la consulta probablemente hará un escaneo completo de la tabla.
La indexación de PAÍS, CIUDAD, CALLE puede ser un poco más lenta para calles individuales, pero el índice se puede usar para otras consultas, solo seleccionando por país y / o ciudad.
fuente
Al elegir el orden de la columna de índice, la preocupación principal es:
¿Hay predicados (de igualdad) en esta columna en mis consultas?
Si una columna nunca aparece en una cláusula where, no vale la pena indexarla (1)
OK, entonces tienes una tabla y consultas en cada columna. A veces más de uno.
¿Cómo decides qué indexar?
Veamos un ejemplo. Aquí hay una tabla con tres columnas. Uno tiene 10 valores, otros 1,000, los últimos 10,000:
Estos son números que quedan rellenados con ceros. Esto ayudará a aclarar más adelante la compresión.
Entonces tienes tres consultas comunes:
¿Qué indizas?
Un índice en solo unos pocos valores es solo marginalmente mejor que una exploración de tabla completa:
Por lo tanto, es poco probable que valga la pena indexarlo solo. Las consultas en lots_vals devuelven algunas filas (solo 1 en este caso). Así que definitivamente vale la pena indexarlo.
Pero, ¿qué pasa con las consultas en ambas columnas?
¿Debería indexar:
O
¡Pregunta capciosa!
La respuesta es ninguno.
Claro que few_vals es una cadena larga. Para que pueda obtener una buena compresión. Y (podría) obtener una exploración de omisión de índice para las consultas usando (few_vals, lots_vals) que solo tienen predicados en lots_vals. Pero no lo hago aquí, a pesar de que funciona notablemente mejor que un escaneo completo:
¿Te gustan los juegos de azar? (2)
Por lo tanto, aún necesita un índice con lots_vals como columna principal. Y al menos en este caso, el índice compuesto (pocos, lotes) realiza la misma cantidad de trabajo que uno solo (lotes)
Habrá casos en los que el índice compuesto le ahorrará 1-2 IO. ¿Pero vale la pena tener dos índices para este ahorro?
Y hay otro problema con el índice compuesto. Compare el factor de agrupación para los tres índices, incluidos LOTS_VALS:
¡Tenga en cuenta que el factor de agrupación para few_lots es 10 veces mayor que para lots y lots_few! Y esto está en una tabla de demostración con una agrupación perfecta para empezar. En las bases de datos del mundo real, es probable que el efecto sea peor.
Entonces, ¿qué tiene de malo eso?
El factor de agrupamiento es uno de los factores clave que determina cuán "atractivo" es un índice. Cuanto más alto sea, menos probable es que el optimizador lo elija. Particularmente si lots_vals no son realmente únicos, pero normalmente tienen pocas filas por valor. Si no tiene suerte, esto podría ser suficiente para hacer que el optimizador piense que un análisis completo es más barato ...
De acuerdo, los índices compuestos con pocos_valos y lotes_valor solo tienen ventajas de caso límite.
¿Qué pasa con las consultas que filtran unos pocos valores y muchos valores?
Los índices de columnas individuales solo ofrecen pequeños beneficios. Pero combinados devuelven pocos valores. Entonces, un índice compuesto es una buena idea. ¿Pero en qué sentido?
Si coloca unos pocos primero, al comprimir la columna principal se reducirá
Con menos valores diferentes en la columna inicial, se comprime mejor. Entonces, hay marginalmente menos trabajo para leer este índice. Pero solo un poco. Y ambos ya son una buena porción más pequeña que la original (disminución del tamaño del 25%).
¡Y puedes ir más allá y comprimir todo el índice!
Ahora ambos índices vuelven al mismo tamaño. Tenga en cuenta que esto aprovecha el hecho de que hay una relación entre pocos y muchos. De nuevo, es poco probable que veas este tipo de beneficio en el mundo real.
Hasta ahora solo hemos hablado de los controles de igualdad. A menudo, con índices compuestos, tendrá una desigualdad con respecto a una de las columnas. por ejemplo, consultas como "obtener los pedidos / envíos / facturas de un cliente en los últimos N días".
Si tiene este tipo de consultas, desea la igualdad con la primera columna del índice:
Observe que están usando el índice opuesto.
TL; DR
1: En algunos casos, puede valer la pena incluir una columna en un índice si esto significa que todas las columnas de su consulta están en el índice. Esto permite un escaneo de índice solamente, por lo que no necesita acceder a la tabla.
2: Si tiene licencia para Diagnóstico y Ajuste, puede forzar el plan a omitir el escaneo con SQL Plan Management
ADDEDNDA
PD: los documentos que ha citado son de 9i. Eso es realmente viejo. Me quedaría con algo más reciente
fuente
select count (distinct few_vals || ':' || many_vals || ':' || lots_vals )
realmente común? ¿Oracle no permite la sintaxisselect count (distinct few_vals, many_vals, lots_vals )
, que no hace ninguna concatenación de cadenas, no necesita que las columnas sean tipos de texto y no se basa en la ausencia de:
caracteres?count ( distinct x, y, z )
en Oracle. Por lo tanto, debe hacer una subconsulta distinta y contar los resultados o una concatenación como la anterior. Simplemente lo hice aquí para forzar un acceso a la tabla (en lugar de escanear solo el índice) y solo tengo una fila en el resultadoHay más elementos de consulta que contribuyen a la decisión final sobre con qué debe comenzar y / o contener un índice compuesto además de la selectividad de la columna.
por ejemplo:
">,> =, <, <="
aún para mantener la conversación relevante, mi respuesta a continuación se aplica a la siguiente situación:
cadena"
En mi experiencia, DBA debe tener en cuenta ambas cosas.
1) Si creo un índice con la columna más selectiva en primer lugar, pero esa columna no es realmente utilizada por la mayoría de las consultas en esa tabla, entonces no sirve para db engine.
2) Si creo un índice con la columna más utilizada en una consulta siendo la primera en el índice pero la columna tiene baja selectividad, entonces el rendimiento de mi consulta no será bueno.
Enumeraré las columnas que se usan principalmente en el 90% de las consultas de la tabla. Luego ponga esos solo en el orden de mayor cardinalidad a menor cardinalidad.
Usamos índices para mejorar el rendimiento de la consulta de lectura y ese flujo de trabajo (tipos de consulta de lectura) solo debería impulsar la creación del índice. De hecho, a medida que los datos crecen (miles de millones de filas), el índice comprimido puede ahorrar almacenamiento, pero seguro perjudica el rendimiento de la consulta de lectura.
fuente
En teoría, la columna más selectiva produce la búsqueda más rápida. Pero en el trabajo me topé con una situación en la que tenemos un índice compuesto de 3 partes con la parte más selectiva primero. (fecha, autor, compañía editorial, digamos, en ese orden, la tabla monitorea el pulgar hacia arriba en las publicaciones) y tengo una consulta que usa las 3 partes. Mysql usa de manera predeterminada el autor solo para omitir el índice compuesto que contiene la compañía y la fecha a pesar de estar presentes en mi consulta. Usé el índice de fuerza para usar el compuesto y la consulta en realidad fue más lenta. ¿Por qué sucedió eso? Te diré:
Estaba seleccionando un rango en la fecha, por lo que a pesar de que la fecha es muy selectiva, el hecho de que lo estemos usando para escaneos de rango (aunque el rango es relativamente corto, 6 meses de 6 años de datos) hizo que el compuesto fuera dañino para mysql. Para usar el compuesto en ese caso particular, mysql tiene que tomar todos los artículos escritos desde los nuevos años y luego sumergirse en quién es el autor, y dado que el autor no ha escrito tantos artículos en comparación con otros autores, mysql prefirió encontrarlo. .
En otro caso, la consulta se ejecutó mucho más rápido en el compuesto, el caso fue cuando un autor era muy popular y poseía la mayoría de los registros, la clasificación por fecha tenía sentido. Pero mysql no detectó automáticamente ese caso, tuve que forzar el índice ... Entonces, ya sabes, varía. Los escaneos de rango podrían inutilizar su columna selectiva. La distribución de los datos podría hacer que las columnas sean más selectivas para diferentes registros ...
Lo que haría de manera diferente es cambiar la fecha (que de nuevo, en teoría es la más selectiva) a la derecha, ya que sé que realizaré un escaneo de rango ahora y eso marca la diferencia.
fuente
WHERE (date BETWEEN @x AND @y) AND (author = @a) AND (publishing company = @p)
, un índice activado(author, publishing_company, date)
o(publishing_company, author, date)
activado sería mejor y se utilizaría, sin forzarlo.Diferentes casos para diferentes situaciones. Conoce tu objetivo; luego cree sus índices y ejecute planes de explicación para cada uno y tendrá la mejor respuesta para su situación.
fuente
Del orden de las columnas en el índice en Ask Tom:
De acuerdo, que tenemos que ordenar las columnas en función de la cláusula where, pero la afirmación "(la selectividad de aob no cuenta en absoluto)" no es correcta. "". ("dónde cláusula")
fuente