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 秒,我想知道(希望,祈祷?)有一种更快的方法可以找到所有超过 100 个句子的 wordid。

我试过取出选择计数部分,只是做'有计数(1)',但都没有加快速度。

我将不胜感激您可以提供的任何帮助。谢谢!

4

5 回答 5

6

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

于 2009-05-04T05:36:20.357 回答
3

计数(sentence_id)> 100;

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

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

HAVING COUNT(DISTINCT Sentence_ID) > 100

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

HAVING COUNT(*) > 100

在这种情况下,您可以仅在 word_id上创建索引,以获得最佳性能。

于 2009-05-04T14:57:44.110 回答
1

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

于 2009-05-04T05:34:09.690 回答
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 点刷新数据期间),或者如果更改很少并且您可以在几个小时内忍受不完美的结果(您必须安排定期数据刷新);这在道德上相当于穷人的数据仓库。

确定什么对您有用的最佳方法是运行查询并查看带有和不带有上述候选索引的查询计划。

于 2009-05-04T06:06:10.020 回答
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;
于 2010-10-05T01:02:38.917 回答