我需要一个查询,可以快速显示用户未上传PDF的特定模块(文章的子集)中的文章。我在下面使用的查询大约需要37秒,因为文章表中有300,000篇文章,而模块中有6,000篇文章。
SELECT *
FROM article a
INNER JOIN article_module_map amm ON amm.article=a.id
WHERE amm.module = 2 AND
a.id NOT IN (
SELECT afm.article
FROM article_file_map afm
INNER JOIN article_module_map amm ON amm.article = afm.article
WHERE afm.organization = 4 AND
amm.module = 2
)
我在上面的查询中所做的是首先将文章列表截断到所选模块,然后进一步将该列表截断为不在子查询中的文章。子查询正在生成组织已为其上载PDF的文章列表。因此,最终结果是组织尚未上传PDF的文章列表。
非常感谢帮助,提前谢谢!
编辑2012/10/25
在@ fthiella的帮助下,以下查询以惊人的1.02秒运行,从37秒开始!
SELECT a.* FROM (
SELECT article.* FROM article
INNER JOIN article_module_map
ON article.id = article_module_map.article
WHERE article_module_map.module = 2
) AS a
LEFT JOIN article_file_map
ON a.id = article_file_map.article
AND article_file_map.organization=4
WHERE article_file_map.id IS NULL
答案 0 :(得分:1)
在优化查询时,我会用来检查以下几点:
首先:我会避免在SELECT子句中使用*,而是命名你想要的不同字段。这疯狂地增加了速度(我有一个用*花了7秒钟,并且命名场减少到0.1秒)。
第二:正如@Adder所说,为你的表添加索引。
第三:尝试使用INNER JOIN而不是WHERE amm.module = 2 AND a.id NOT IN(...)。我认为我读过(我不记得了,所以请小心)通常MySQL优化INNER JOINS,并且因为你的子查询是一个过滤器,也许使用三个INNER JOINS加上WHERE会更快检索。
答案 1 :(得分:1)
我不确定我是否能正确理解表格的逻辑和结构。这是我的问题:
SELECT
article.id
FROM
article
INNER JOIN
article_module_map
ON article.id = article_module_map.article
AND article_module_map.module=2
LEFT JOIN
article_file_map
ON article.id = article_file_map.article
AND article_file_map.organization=4
WHERE
article_file_map.id IS NULL
我提取所有具有模块2的文章。然后选择那些组织4没有提供文件的文章。
我使用LEFT JOIN而不是子查询。在某些情况下,这可能会更快。
编辑感谢您的评论。我不确定它会跑得更快,但令我惊讶的是它速度要慢得多!无论如何,值得一试!
现在,出于好奇,我想尝试LEFT / INNER JOIN和子查询的所有组合,看看哪一个运行得更快,例如:
SELECT *
FROM
(SELECT *
FROM
article INNER JOIN article_module_map
ON article.id = article_module_map.article
WHERE
article_module_map.module=2)
LEFT JOIN
etc.
也许删除*,我想看看WHERE子句和ON子句之间的条件有什么变化......无论如何我认为它没有多大帮助,你现在应该专注于索引。
键/外键上的索引应该已经可以了,但是如果在article_module_map.module
和/或article_file_map.organization
上添加索引怎么办?