这个问题对我来说有点复杂,我不能用一句话来解释,所以题目可能显得很模棱两可。
我的mysql数据库中有3个表,它们的结构如下:
单词列表(500万行)
+-----+--------+
| wid | word |
+-----+--------+
| 1 | foo |
| 2 | bar |
| 3 | hello |
+-----+--------+
纸字关系(1000万行)
+-----+-------+
| pid | word |
+-----+-------+
| 1 | 1 |
| 1 | 2 |
| 1 | 3 |
| 2 | 1 |
| 2 | 3 |
+-----+-------+
论文引用关系(8万行)
+----------+--------+
| pid_from | pid_to |
+----------+--------+
| 1 | 2 |
| 1 | 3 |
| 1 | 4 |
| 2 | 1 |
| 2 | 3 |
+----------+--------+
我想找出有多少篇论文包含w这个词,并引用这些论文中也包含w这个词
我使用两个内部连接来完成这项工作,但是当这个词很流行的时候,它看起来非常慢——超过50秒(如果这个词很少使用的话,它会非常快——低于0.1秒),下面是我的代码
SELECT COUNT(*) FROM (
SELECT a.pid_from, a.pid_to, b.word FROM paper_citation_relation AS a
INNER JOIN paper_word_relation AS b ON a.pid_from = b.pid
INNER JOIN paper_word_relation AS c ON a.pid_to = c.pid
WHERE b.word = 2 AND c.word = 2) AS d
我怎样才能做得更快?是我的查询效率不够还是数据量的问题?
我只能想出一个解决办法,我删除的话,出现在不到2个 paper_word_relation
table(大约400万字(只出现一次)
谢谢!
2条答案
按热度按时间jhdbpxl91#
如果您只关心获取计数,则不应首先将结果获取到派生表中,然后再将行计数出去。这可能会创建不必要的临时表,在内存中存储大量数据。您可以直接计算行数。
我还认为你需要计算论文的独特数量。因为很多人之间的关系
paper_citation_relation
表中,一张纸可能会出现重复的行。为了提高性能,您需要以下索引:
综合指数
(pid_from, pid_to)
在paper_citation_relation
table。综合指数
(pid, word)
在paper_word_relation
table。我们还可以通过减少一个连接和使用条件连接来进一步优化查询
AND/OR
基于过滤的HAVING
. 不过,您需要对其进行基准测试。toiithl62#
第一次之后
1:n
加入你也一样pid_to
多次,你的下一次加入不再是1:n
但是n:m
,在决赛前创造了一个巨大的中间结果DISTINCT
. 它类似于交叉连接,对于流行词来说情况越来越糟,例如1010对10001000行。必须在连接之前删除重复项,这将返回与@madhurbhaiya的答案相同的数字
如果你想计算被引用的论文的数量,你需要得到一个不同的列表
pid
(或者pid_from
或者pid_to
)从paper_citation_relation
先连接到特定的单词。这个返回的数字可能略高一些(不管引用的是什么论文,它都会计算在内)。