¿Los mejores índices para esta tabla y consulta?
Frecuentes
Visto 122 veces
2
Tengo una consulta sqlite que debe ejecutarse lo más rápido posible. La consulta es bastante simple, pero no sé cuál es la mejor manera de indexar la tabla para obtener el máximo rendimiento.
La tabla se llama "léxico". La definición es:
_id integer primary key
word text
frequency integer
lset integer
rset integer
La consulta es:
SELECT word,frequency FROM lexicon WHERE lset>? AND rset<? ORDER BY frequency DESC LIMIT ?
He indexado todas las columnas individuales, pero sospecho que los índices compuestos pueden ser mejores, pero ¿qué combinación? ¿Y los índices en lset y rset deberían ser ascendentes o descendentes?
EDITAR: lset y rset son valores establecidos anidados que representan una estructura de árbol. Por lo tanto, todos los valores de lset y rset son mutuamente únicos y están perfectamente distribuidos. Además, en cualquier fila dada, lset < rset.
Gracias por adelantado ...
3 Respuestas
3
Va a depender de las estadísticas de tus datos.
Podría intentar crear índices en cada combinación de lset
, rset
y frequency
para encontrar el mejor de los casos, pero usted debe: luego tenga datos reales en su tabla.
- (lset
, rset
, frequency
)
- (rset
, lset
, frequency
)
- (lset
, frequency
, rset
)
- (rset
, frequency
, lset
)
- (frequency
, lset
, rset
)
- (frequency
, rset
, lset
)
La ventaja de tener frequency
primero es que ya está preparado para su ORDER BY
y LIMIT
cláusulas.
Pero si cada palabra en su léxico tiene una frecuencia diferente, el segundo y tercer campo en el índice perderán su valor. (Un ejemplo de por qué las estadísticas de sus datos son importantes).
También importa qué campo limitará sus registros más rápido. Si el lset < x
El filtro reduce el conjunto a 0.01%
del tamaño original, coloque ese filtro primero en su índice.
Pero con toda probabilidad, filtrar lset < X and rset > y
será imposible indexar muy bien en absoluto.
contestado el 22 de mayo de 12 a las 17:05
Puede valer la pena señalar que, si Sqlite se comporta como otros DBMS, agregar word
ya que la columna final en el índice haría que el índice cubriera todos los campos obligatorios y evitaría la necesidad de buscar esa columna en otro lugar. Esto no ayudaría si este índice agrupa la tabla. - daniel renshaw
@DanielRenshaw - De acuerdo. Encontrar un campo de datos que no está en un índice es similar a agregar una combinación adicional... JOIN theIndex On blah JOIN theTable ON theIndex.PK = theTable.PK
. Por lo tanto, incluir los campos necesarios en el índice elimina esta sobrecarga. (Excepto en índices agrupados donde la tabla ES el índice). - MatBailie
@Dems No estoy seguro de si SQLite admite eso, pero en DBMS "grandes" puede mezclar la "orientación" de los componentes del índice, por lo que lset>? AND rset<?
puede en realidad ser indexado de manera eficiente. - branco dimitrijevic
@BrankoDimitrijevic - Eso es correcto. Pero todavía no ayudará tanto como uno esperaría. Por ejemplo, pretender ambos lset
y rset
se puntúan como números enteros de 0
a 99
. La entrada de índice para lset = 0
entonces tendrá cien rset
entradas debajo de ella. Para cada lset
que pasa la condición de búsqueda (en promedio 50%, ingenuamente?), es necesario que haya otra búsqueda de índice para verificar el rset
predicado (1 búsqueda lset, 50 búsquedas rset). No es tan efectivo como lset > x AND lset < y
. Sobre todo si se considera que lset
y rset
probablemente tendrá un enorme gama de valores legítimos. - MatBailie
Muchas gracias por sus respuestas. Acabo de agregar información adicional a mi pregunta que debería haber incluido originalmente (lo siento). La tabla representa una estructura de árbol y lset/rset son pares de conjuntos anidados, por lo que: 1. en cualquier fila dada lset barry fruitman
2
Si SQLite se comporta de manera similar a otros DBMS en este sentido, necesitará un índice compuesto en...
{lset, rset DESC, frequency DESC}
...en este orden específico y con estos específicos DESC
cláusulas.
Echa un vistazo a este artículo para más información sobre índices ascendentes/descendentes.
Y sí, como mencionó @DanielRenshaw, podría incluir word
al final del índice, simplemente para permitir escaneo de solo índice. Esto se conoce como índice de "cobertura".
(Dado que el índice de agrupamiento ya cubre todos los campos, no tiene sentido hacerlo para dicho índice).
contestado el 22 de mayo de 12 a las 17:05
1
Su consulta (con ligeros cambios en los nombres):
SELECT word,frequency
FROM lexicon
WHERE lset > @LeftSide
AND rset < @RightSide
ORDER BY frequency DESC
LIMIT @Num
Está utilizando el modelo de conjunto anidado, por lo que podría reescribirse como:
SELECT word,frequency
FROM lexicon
WHERE lset > @LeftSide --- both `lset` here
AND lset < @RightSide --- and here
ORDER BY frequency DESC
LIMIT @Num
tambien pueden ser los dos rset
. Siempre que sus datos no violen el modelo de conjunto anidado, ambos funcionarán y darán los mismos resultados. Entonces, su consulta puede necesitar un índice de cobertura en las 3 columnas:
(lset, frequency, word)
Utilizará el índice para identificar las filas (posiblemente miles) que caen en el (@LeftSide,@RightSide)
rango y luego use una ordenación de archivos para encontrar las palabras (@Num) con mayor frecuencia.
Un índice sobre (frequency DESC, lset, word)
puede ser mejor en algunos casos (realmente depende de los valores de los parámetros), por lo que es bueno si también tiene ese índice. Pero no puedo responder si SQLite alcanzará el mejor índice en cada instancia.
Dependiendo de cuántas filas caigan en ese rango, puede funcionar bien o no tan bien. Pero no veo una manera fácil de optimizar aún más este tipo de consulta.
contestado el 22 de mayo de 12 a las 21:05
Gracias por la optimización de la consulta. Ahora veo que rset no es realmente necesario. Actualicé la consulta e indexé la tabla como sugirió, pero aún no es lo suficientemente rápido. Sospecho, como usted, que no se puede optimizar más. - barry fruitman
Buenas noticias: estaba usando el índice incorrecto (las columnas estaban en el orden incorrecto) y después de organizarlas correctamente, la consulta es de 5 a 10 veces más rápida. Creo que ahora es lo suficientemente rápido para mis propósitos. :) :) :) - barry fruitman
@Barry: publiqué una pregunta relacionada en dba.se: Ejecución de consulta con condición de rango y orden por. Siéntase libre de seguir eso y hacer comentarios allí. - ypercubeᵀᴹ
No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas sql sqlite or haz tu propia pregunta.
Como siempre, ¡depende! En este caso, la selectividad de la
lset
yrset
los predicados serán críticos. haríalset>?
solo probablemente devuelva un mayor o menor número de registros querset<?
¿solo? - Daniel RenshawGran pregunta. Debería haber mencionado que lset y rset son valores establecidos anidados que representan una estructura de árbol. Por lo tanto, todos los valores de lset y rset son mutuamente únicos y están perfectamente distribuidos con un rango de 1- 2*N (donde N es el número de filas en la tabla). - Barry Fruitman
@Barry: ¿Quiere decir (también) que lo siguiente siempre es cierto?:
lset <= rset
- ypercubeᵀᴹ@ypercube: En cualquier fila, sí. En realidad, lset < rset porque ningún valor aparece dos veces (en ambas columnas). - Barry Fruitman
En los
(lset, rset)
combinación esUNIQUE
? - ypercubeᵀᴹ