2009-05-04 35 views
3

这里是我的查询:是否有比“大数表”更快的东西?

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

表sentenceword包含3个字段,的wordID,sentenceid以及一个主键ID。 它有350k +行。 这个查询需要高达85秒,我想知道(希望,祈祷?)有一个更快的方式来找到所有的wordids有超过100个罪犯。

我试过拿出select count部分,只是做'有数(1)',但都没有加速。

我很感激任何帮助,你可以借。谢谢!

+1

哪些DBMS您使用的? – 2009-05-04 05:56:04

+0

这是与MySQL(并使用HeidiSQL作为客户端访问它) – Jeff 2009-05-04 21:30:53

+0

另一个恼人的澄清...(对不起):数据不断变化。约10k插入行/天和〜5k删除行。所以我认为这使得存储或缓存结果不可能 – Jeff 2009-05-04 21:47:38

回答

3

having count(sentence_id)> 100;

这有一个问题......这个表有两个重复的单词/句子对,或者它没有。

如果它确实有重复的单词/句子对,你应该使用这个代码来得到正确的答案:

HAVING COUNT(DISTINCT Sentence_ID) > 100 

如果表中没有重复的单词/句子对...那么你不应该计算sentence_ids,你应该只计数行。

HAVING COUNT(*) > 100 

在这种情况下,你可以创建一个索引上word_id只有,以获得最佳性能。

1

如果经常执行该查询,并且表格很少更新,则可以使用单词ID和相应的句子计数来保留一个辅助表格 - 难以想到除此之外的任何进一步优化!

+4

你的意思是,像一个索引? :-) – bignose 2009-05-04 05:40:05

6

如果还没有,请在sentence_id,word_id上创建一个复合索引。

+0

我相信这个索引的列的正确顺序是(word_id,sentence_id)。 – 2009-05-04 07:19:47

1

你的查询很好,但它需要一些帮助(索引)来获得更快的结果。

我没有手头资源(或访问SQL),但我会尝试从内存中为您提供帮助。

从概念上讲,回答该查询的唯一方法是计算共享相同word_id的所有记录。这意味着查询引擎需要快速查找这些记录。没有word_id上的索引,数据库唯一能做的就是一次遍历表中的一条记录,并继续运行找到的每个单独的word_id的总计。这通常需要临时表,并且在扫描整个表之前不会派发任何结果。不好。

随着word_id上的索引,它仍然需要通过表,所以你会认为它没有什么帮助。但是,SQL引擎现在可以计算每个word_id的计数,而不必等到表的结尾:它可以分派行和word_id的值的计数(如果它通过您的where子句),或者放弃该行(如果它不);这将导致服务器上的内存负载较低,可能部分响应,并且临时表不再需要。第二个方面是并行性;通过word_id上的索引,SQL可以将作业分成块,并使用不同的处理器核并行运行查询(取决于硬件功能和现有工作负载)。

这可能足以帮助您查询;但你必须尝试看看:

CREATE INDEX someindexname ON sentence_word (word_id) 

(T-SQL语法;其中SQL产品使用的是没有指定)。如果这还不够

(或不利于在所有),还有其他两种解决方案。

首先,SQL允许您使用索引视图和其他机制预先计算COUNT(*)。我手边没有细节(我不经常这样做)。如果您的数据不会经常更改,那么这会给您更快的结果,但复杂性和存储空间有限。

此外,您可能需要考虑将查询的结果存储在单独的表中。只有数据不会改变,或者按照精确的时间表(例如,在早上2点的数据刷新期间),或者如果数据变化很小,并且几个小时内您可以忍受非完美的结果(您将不得不安排定期数据刷新);这就是穷人数据仓库的道德等价物。

确定什么适合您的最好方法是运行查询并查看带有和不带有一些候选索引的查询计划。

0

还有的竟然是实现这一大型数据集的更快的方法:

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; 
相关问题