Pergunta

Aqui está minha consulta:

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

O sentenceword tabela contém 3 campos, wordid, sentenceid e uma ID de chave primária. Ele tem 350k + linhas. Esta consulta leva uma gritante 85 segundos e eu estou querendo saber (esperando, rezando?) Há uma maneira mais rápida de encontrar todos os wordids que têm mais de 100 sentenceids.

Eu tentei tirar o seleto parte contagem, e apenas fazendo 'ter count (1)' mas nem acelera-lo.

Eu apreciaria qualquer ajuda que você pode dar. Obrigado!

Foi útil?

Solução

tendo count (sentence_id)> 100;

Há um problema com este ... Ou a tabela tem duplicados pares de palavra / frase, ou não.

Se ele tem duplicados pares de palavra / frase, você deve estar usando este código para obter a resposta correta:

HAVING COUNT(DISTINCT Sentence_ID) > 100

Se a tabela não tiver duplicados pares de palavra / frase ... então você não deve contar sentence_ids, você deve apenas contar linhas.

HAVING COUNT(*) > 100

Em que caso, você pode criar um índice em word_id única , para um melhor desempenho.

Outras dicas

Se você não tiver um, crie um índice composto em sentence_id, word_id.

Se essa consulta é muitas vezes realizada, ea mesa raramente atualizado, você pode manter uma tabela auxiliar com ids palavras e correspondentes contagem de frases - difícil pensar em qualquer outra otimização além disso

A sua consulta é bom, mas precisa de um pouco de ajuda (índices) para obter resultados mais rápidos.

Eu não tenho meus recursos à mão (ou o acesso ao SQL), mas eu vou tentar ajudá-lo da memória.

Conceitualmente, a única maneira de responder a essa consulta é contar todos os registros que compartilham o mesmo word_id. Isso significa que o mecanismo de consulta precisa de uma forma rápida para encontrar os registros. Sem um índice em word_id, a única coisa que o banco de dados pode fazer é ir através da tabela um registro de cada vez e continuar correndo totais de cada word_id distinta que encontra. Que normalmente requerem uma tabela temporária e não houve resultados podem ser despachadas até que a tabela completa é digitalizada. Não é bom.

Com um índice em word_id, ele ainda tem que passar pela mesa, então você pensaria não ajudaria muito. No entanto, o motor SQL podem agora calcular a contagem para cada word_id sem esperar até o final da tabela: ele pode despachar a linha e a contagem para esse valor de word_id (se ele passa sua cláusula where), ou descartar a linha (se não); que resultará em menor carga de memória no servidor, respostas possivelmente parciais, e a tabela temporária não é mais necessário. Um segundo aspecto é paralelismo; com um índice em word_id, SQL pode dividir o trabalho em pedaços e usar processadores separados para executar a consulta em paralelo (dependendo dos recursos de hardware e carga de trabalho existente).

Isso pode ser suficiente para ajudar a sua consulta; mas você terá que tentar ver:

CREATE INDEX someindexname ON sentence_word (word_id)

(sintaxe T-SQL, você não especificou qual o produto SQL que você está usando)

Se isso não é suficiente (ou não ajuda em tudo), há duas outras soluções.

Em primeiro lugar, SQL permite que você precompute a COUNT (*) usando exibições indexadas e outros mecanismos. Eu não tenho os detalhes em mãos (e eu não faço isso muitas vezes). Se os dados não muda frequentemente, que lhe daria resultados mais rápidos, mas com um custo em termos de complexidade e um pouco de armazenamento.

Além disso, você pode querer considerar armazenar os resultados da consulta em uma tabela separada. Que é prático apenas se os dados nunca muda, ou alterações em um cronograma preciso (por exemplo, durante uma atualização de dados às 2 da manhã), ou se ele muda muito pouco e você pode viver com resultados não perfeitos por algumas horas (você teria de marcar uma actualização de dados periódicos); Isso é o equivalente moral de data warehouse de um pobre homem.

A melhor maneira de saber ao certo o que funciona para você é para executar a consulta e olhar para o plano de consulta com e sem alguns índices candidatos como o descrito acima.

Não é, surpreendentemente, uma forma ainda mais rápida de conseguir isso em grandes conjuntos de dados:

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 em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top