虽然问题标题与许多讨论重复,但我没有找到这个问题的答案:
考虑将标准化的标签表简单连接为
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?
后一种方法应该更快!
答案 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引擎检查您的版本/数据库的执行计划来查找“什么是最好的”