0

我需要一个查询来快速显示用户尚未为其上传 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
4

2 回答 2

1

在优化查询时,我会检查以下几点:

首先:我会避免在 SELECT 子句中使用 *,而是命名您想要的不同字段。这极大地提高了速度(我有一个用 * 花了 7 秒,并且命名字段减少到 0.1 秒)。

第二:正如@Adder 所说,为您的表添加索引。

第三:尝试使用 INNER JOIN 而不是 WHERE amm.module = 2 AND a.id NOT IN ( ... )。我想我读过(我记不太清了,所以请仔细阅读)通常 MySQL 会优化 INNER JOINS,并且由于您的子查询是一个过滤器,也许使用三个 INNER JOINS 加上 WHERE 会更快地检索。

于 2012-10-25T08:36:22.913 回答
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.moduleand/or上添加索引article_file_map.organization怎么办?

于 2012-10-25T09:01:06.273 回答