JOIN如何在MySQL中运行?

时间:2011-11-11 12:11:05

标签: mysql sql database relational-database normalization

虽然问题标题与许多讨论重复,但我没有找到这个问题的答案:

考虑将标准化的标签表简单连接为

SELECT tags.tag
FROM tags
    INNER JOIN tag_map
    ON tags.tag_id=tag_map.tag_id
WHERE article_id=xx

JOIN是否适用于整个标记表和tag_map,然后过滤创建的(JOIN ed)表,以查找文章ID为WHERE子句的行

OR JOIN只会加入tag_map表的行,其中article_id = xx?

后一种方法应该更快!

5 个答案:

答案 0 :(得分:1)

您可以随时查看执行计划,了解您的查询是如何逐步执行的。在MySQL中,我不知道它是否可以使用任何第三方工具以图形方式呈现(正如您可以使用Management Studio开箱即用的MS SQL),但您仍然可以使用explain语言结构进行检查。检查文档。

不知道您的表架构

如果article_id属于表tags,那么除非FK表中的连接列可以为空,否则不会扫描tag_map表。

如果article_id已编入索引(即主键),则正在扫描索引......

等...

我想说的是,我们需要您的表架构定义来告诉您一些细节。我们无法知道您的架构是如何工作的。

答案 1 :(得分:1)

它将执行前者,据我所知,在生成的JOINed表上显式执行了WHERE。 (免责声明:在某些情况下,MySQL可能会对此进行优化,我不知道。)

要强制执行后一种行为并首先执行WHERE,可以在JOIN ON语句中添加额外的过滤器:

SELECT tags.tag 
    FROM tags 
    INNER JOIN tag_map 
        ON tags.article_id=xx
        AND tags.tag_id=tag_map.tag_id 
    WHERE article_id=xx

答案 2 :(得分:1)

Joins仅处理从第一个表的WHERE子句返回记录的那些记录。那就是说,你正在连接到tag_map,但你的where子句没有指定“Article_ID”与哪个别名相关联。通常最好总是使用来自的表名或别名限定字段。

因此,如果article_id来自TAGS,那么它将首先将该列表视为主要记录集,并使用索引进行优化(如果存在并返回一个小集)。从那里,连接将应用于tag_map,并将获取与连接“ON”条件匹配的所有记录。

只是澄清一些事情。如果在WHERE子句优化之前首先应用JOIN,则查询将永远进行。在记录选择实际发生之前,连接基本上是准备关系。因此,执行计划显示将使用的索引。

答案 3 :(得分:1)

假设它是简单的或内部联接:

答案是:在关系模型中,第一个答案是正确的,它会创建一个表,其中包含第一个与第二个表中的每一行交叉的每一行,所以如果你先有N行,第二个是M,那么用NxM创建一个表,然后消除条件不匹配的表。

现在,这是数学模型,但在实现中,取决于引擎,它将使用一些更智能的方式,通常选择一个似乎更快的表,并使用希望索引的连接字段从那里开始。但这取决于引擎之间:有很多文档(谷歌)和一些人,包括这个答案的海报,是为了优化连接查询...

对于MYSQL(只是注意到标记),您可以使用以下语法:

  EXPLAIN [EXTENDED] SELECT select_options

如解释here和MYSQL将告诉你它将如何执行这样的查询。它比阅读docuemtnation更快。

答案 4 :(得分:1)

这取决于引擎。许多数据库引擎的早期版本将首先生成连接结果,然后它将过滤。较新版本的引擎生成执行计划,以实现最快的结果。必须使用db引擎检查您的版本/数据库的执行计划来查找“什么是最好的”