内部连接的性能与交叉连接相比

发出内部连接的效果与在WHERE子句中声明连接条件的交叉连接相同。 我注意到我公司的很多人使用交叉连接,我将使用内部连接。 在改变这些查询之后,我没有注意到任何显着的性能增益,并且想知道是否只是巧合,或者DBMS是否透明地优化了这些问题(在我们的例子中是MySql)。 这里有一个讨论的具体例子:

SELECT User.* FROM User, Address WHERE User.addressId = Address.id; SELECT User.* FROM User INNER JOIN Address ON (User.addressId = Address.id); 

交叉连接生成的结果由两个或多个表中各行的组合组成。 这意味着,如果表A有6行,而表B有3行,交叉连接将导致18行。 这两张表之间并没有build立任何关系 – 你简直就是生产出所有可能的组合。

使用内部联接时,表中一行的列值与另一个(或相同)表的另一行中的列值组合,形成一行数据。

如果将一个WHERE子句添加到交叉联接中,那么它将作为内部联接行为,因为WHERE强加了一个限制因素。

只要您的查询遵守常识和供应商特定的性能指导方针 ,我就会考虑决定使用哪种types的联接是一个简单的问题。

除了内部连接之外没有任何区别,因为它定义了连接,而使where子句成为实际的限制条件。

使用EXPLAIN查看这两个查询的查询计划,并查看是否有任何区别。 在这两种情况下,很可能MySQL都将使用相同的执行计划。 我使用INNER JOIN语法主要是因为它更清晰。

我发现,允许第一个语法(逗号分隔的表格)的工作场所往往会花费大量的时间来debugging返回比预期多的行的情况。 无意的交叉连接是一个系统的祸根,甚至可以把最好的数据库引入它的膝盖。 去年至less有两次把我们的产前系统吓了一跳。

第二种语法(连接语法)强制编写者考虑如何将表先连接在一起,然后只返回有趣的行。 使用这种语法意外地进行交叉连接是不可能的,因此减less了意外执行不佳的查询的危险。

不过,除了这个问题之外,我从来没有注意到任何系统中两种语法之间的速度差异。

第一个例子在function上与第二个例子相同。 但是,出于以下原因,应避免使用该语法。 首先,当使用这种语法时,意外得到交叉连接要容易得多,特别是当表中有多个连接时。 如果您看到很多关键字为distinct的此类查询,您可能有人正试图修复交叉连接。

接下来,不赞成使用旧式的左右连接语法,不再支持。 此外,无论如何,它现在不能正常工作。 有时它会误解外连接并发回错误的结果集。 因此,在where子句中使用=或=的任何查询都应该立即被replace。

第三,ANSI标准连接更容易理解和维护。 理解联接是任何查询任何关系数据库都需要的最重要的基本技能之一。 根据我的经验,一些使用旧式风格的人并不真正理解联结以及如何工作,从而编写实际上并不按照他们的意图完成的查询。

你连接表的顺序或者你把ON / WHERE条件都不重要。

查询优化器应该优化和使用最好的顺序(并select如何最好地过滤数据,从哪里开始等)

与其他许多人一样,我build议使用INNER JOIN语法,因为它使事情变得更加可读,使用LEFT或FULL连接的语法也更加透明。

这里有一些更详细的文字: http : //linus.brimstedt.se/?/article/articleview/ SQL语法

/ B

第一种语法的另外一个好处是在限制条件下可以更一般化。 不仅仅是平等。

但是如果你使用平等,为什么信任优化器? 确保它不会首先生成交叉连接,然后消除行。 使用第二个。

SQL Server表示“当一个WHERE变成一个交叉连接到一个内部连接”,所以没有区别。 http://msdn.microsoft.com/en-us/library/ms190690.aspx

我做了SQL服务器的“执行计划”,性能是一样的。

解释这两个查询给出相同的输出

 mysql> explain select * from t T1, t T2 where T1.ID=T2.ID; +----+-------------+-------+------+---------------+------+---------+------+------+--------------------------------+ | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | +----+-------------+-------+------+---------------+------+---------+------+------+--------------------------------+ | 1 | SIMPLE | T1 | ALL | PRIMARY | NULL | NULL | NULL | 3 | | | 1 | SIMPLE | T2 | ALL | PRIMARY | NULL | NULL | NULL | 3 | Using where; Using join buffer | +----+-------------+-------+------+---------------+------+---------+------+------+--------------------------------+ 2 rows in set (0.00 sec) mysql> explain select * from t T1 join t T2 on T1.ID=T2.ID; +----+-------------+-------+------+---------------+------+---------+------+------+--------------------------------+ | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | +----+-------------+-------+------+---------------+------+---------+------+------+--------------------------------+ | 1 | SIMPLE | T1 | ALL | PRIMARY | NULL | NULL | NULL | 3 | | | 1 | SIMPLE | T2 | ALL | PRIMARY | NULL | NULL | NULL | 3 | Using where; Using join buffer | +----+-------------+-------+------+---------------+------+---------+------+------+--------------------------------+ 2 rows in set (0.00 sec) 

但是使用内部连接语法更好,因为它更清晰,更精确。 与Cross Join相比,Mysql可以在内部调整Left和Right join查询来select更less的数据。

从一开始,优化器就围绕着经典的限制项目 – 笛卡尔产品语法而build立。 几乎所有的供应商都复制了System R开创的devise。然后,供应商不情愿地采用了“最新最好”的ANSI语法,并对其SQL执行引擎进行了改进。 与营销手册可以告诉你什么(“使用最新的语法”)相反,在物理实现层面没有太多改变:它仍然是[索引]嵌套循环,或散列或sorting合并连接。 因此,没有任何一种语法优于另一种语法的基础。

就我个人的口味而言,新的语法是多余的 ,嘈杂的和不一致的 。 至于委员会的批准,“走进每个城市的任何一个公园,你都不会find委员会的雕像”。