Pregunta

Aquí está mi consulta:

select word_id, count(sentence_id) 
from sentence_word 
group by word_id 
having count(sentence_id) > 100;

La palabra de oración de la tabla contiene 3 campos, ID de palabra, ID de sentencia y un ID de clave principal. Tiene 350k + filas. Esta consulta toma 85 segundos y me estoy preguntando (¿esperando, rezando?) Hay una forma más rápida de encontrar todos los wordids que tienen más de 100 sentencias.

He intentado sacar la parte de recuento selectivo y simplemente haciendo 'teniendo recuento (1)' pero ninguno lo acelera.

Apreciaría cualquier ayuda que puedas prestar. Gracias!

¿Fue útil?

Solución

  

teniendo cuenta (sentence_id) > 100;

Hay un problema con esto ... O la tabla tiene pares de palabras / oraciones duplicadas, o no.

Si tiene pares de palabras / oraciones duplicadas, debería usar este código para obtener la respuesta correcta:

HAVING COUNT(DISTINCT Sentence_ID) > 100

Si la tabla no tiene pares de palabras / oraciones duplicadas ... entonces no debe contar oraciones, solo debe contar las filas.

HAVING COUNT(*) > 100

En cuyo caso, puede crear un índice en solo word_id , para un rendimiento óptimo.

Otros consejos

Si aún no tiene uno, cree un índice compuesto en oracion_id, palabra_id.

Si la consulta se realiza con frecuencia y la tabla se actualiza rara vez, podría mantener una tabla auxiliar con los identificadores de palabras y el número de oraciones correspondientes. ¡Es difícil pensar en una optimización adicional más allá de eso!

Su consulta está bien, pero necesita un poco de ayuda (índices) para obtener resultados más rápidos.

No tengo mis recursos a mano (o acceso a SQL), pero intentaré ayudarte desde la memoria.

Conceptualmente, la única forma de responder a esa consulta es contar todos los registros que comparten el mismo word_id. Eso significa que el motor de consultas necesita una forma rápida de encontrar esos registros. Sin un índice en word_id, lo único que puede hacer la base de datos es recorrer la tabla un registro a la vez y mantener los totales acumulados de cada word_id distinto que encuentre. Eso normalmente requeriría una tabla temporal y no se pueden enviar resultados hasta que se escanee toda la tabla. No es bueno.

Con un índice en word_id, todavía tiene que pasar por la tabla, por lo que pensarías no ayudaría mucho. Sin embargo, el motor SQL ahora puede calcular el recuento para cada word_id sin esperar hasta el final de la tabla: puede enviar la fila y el recuento para ese valor de word_id (si pasa su cláusula where ) , o descartar la fila (si no es así); eso dará como resultado una menor carga de memoria en el servidor, posiblemente respuestas parciales, y la tabla temporal ya no es necesaria. Un segundo aspecto es el paralelismo; con un índice en word_id, SQL puede dividir el trabajo en fragmentos y usar núcleos de procesador separados para ejecutar la consulta en paralelo (dependiendo de las capacidades de hardware y la carga de trabajo existente).

Eso podría ser suficiente para ayudar a su consulta; pero tendrás que intentar ver:

CREATE INDEX someindexname ON sentence_word (word_id)

(sintaxis T-SQL; no especificó qué producto SQL está utilizando)

Si eso no es suficiente (o no ayuda en absoluto), hay otras dos soluciones.

Primero, SQL le permite calcular previamente COUNT (*) utilizando vistas indexadas y otros mecanismos. No tengo los detalles a la mano (y no hago esto a menudo). Si sus datos no cambian a menudo, eso le daría resultados más rápidos pero con un costo en complejidad y un poco de almacenamiento.

Además, es posible que desee considerar el almacenamiento de los resultados de la consulta en una tabla separada. Esto es práctico solo si los datos nunca cambian, o cambian en un horario preciso (por ejemplo, durante una actualización de datos a las 2 de la mañana), o si cambian muy poco y puede vivir con resultados no perfectos durante unas horas (usted tendría que programar una actualización periódica de datos); ese es el equivalente moral del almacén de datos de un hombre pobre.

La mejor manera de averiguar con certeza qué es lo que funciona para usted es ejecutar la consulta y mirar el plan de consulta con y sin algunos índices candidatos como el anterior.

Sorprendentemente, hay una forma aún más rápida de lograrlo en grandes conjuntos de datos:

SELECT totals.word_id, totals.num 
  FROM (SELECT word_id, COUNT(*) AS num FROM sentence_word GROUP BY word_id) AS totals
 WHERE num > 1000;
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top