¿Los mejores índices para esta tabla y consulta?

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 ...

preguntado el 22 de mayo de 12 a las 16:05

Como siempre, ¡depende! En este caso, la selectividad de la lset y rset los predicados serán críticos. haría lset>? solo probablemente devuelva un mayor o menor número de registros que rset<? ¿solo? -

Gran 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: ¿Quiere decir (también) que lo siguiente siempre es cierto?: lset <= rset -

@ypercube: En cualquier fila, sí. En realidad, lset < rset porque ningún valor aparece dos veces (en ambas columnas). -

En los (lset, rset) combinación es UNIQUE? -

3 Respuestas

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

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

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 or haz tu propia pregunta.