我怀疑。假设R和S分别与属性A和B有2个关系。如果我有查询
Select *
From R, S
Where R.A = S.B
这是否像c或c ++中的双For循环一样工作
For( i=0; i<n; i++)
For( j=0; j<n; j++)
if (i == j)
//DO some work
答案 0 :(得分:2)
首先:不知道mysql如何在内部优化查询(不知道mysql的内部)。
在纯关系数据库中,这就是你正在做的事情:
SELECT * FROM R, S
- &gt;执行交叉连接,生成所有(r,s)元组。
WHERE R.A = S.B
- &gt;现在选择那些具有此行为的元组
所以它会遍历所有元组(或多或少像你的代码)。但是,完全有可能mysql会在内部将其减少为一个更有效的内连接,它永远不会创建所有元组,只有R.A=S.B
有效的元组。
答案 1 :(得分:2)
是的,至少在概念上。连接创建两个表中元素的笛卡尔交叉,这是您使用两个循环执行的操作,然后Where子句限制条件为true的笛卡尔十字的成员。当然,实现不会实际创建整个笛卡尔十字架;它将使用索引来识别匹配,而无需通过所有成对比较。
答案 2 :(得分:2)
如果这些属性中没有任何索引,那么这正是MySQL必须要做的,而且效率非常低。
尽管如此,拥有索引会让世界变得与众不同。例如,如果S.B上有索引,那么MySQL可以做更多这样的事情:
for (i=0; i<n_r; i++) { // loop over all rows in R
matching_rows = retrieve_from_index_s_b(i); // very fast operation, like direct array access
for (j=0; j<matching_rows.length(); j++)
// do some work
}
类似地,如果索引在R.A上,那么外部循环将在S中的行上,而内部循环将仅在R中的匹配行上。
如果两个属性都有索引,那么MySQL可以查看每个表中的数据量,并组织循环以便需要最少的工作量。这是MySQL查询优化器的工作,它可以做很多工作来确定查看表的正确顺序,以最小化所需的磁盘访问次数。
正如其他人已经提到的那样,SQL主要是一种声明性语言,您可以在其中说出您想要的结果,而无需指定数据库如何获得这些结果。您可以想象数据库总是在执行完整的嵌套循环集,如果这有助于您可视化结果,但只要您正确设置索引,它通常会做更聪明的事情。
答案 3 :(得分:1)
功能方面,是的。这就是它的工作原理。你可以想象它在嵌套for循环中循环遍历两个表中的所有行,并且只选择字段匹配的那些行。
实施方面,情况非常不同。数据库引擎使用多种优化来加速查询。数据库引擎如何实际执行查询取决于许多因素,例如数据库引擎的类型,(非常重要的)索引,数据量等。
答案 4 :(得分:1)
您所描述的是nested loops
加入策略。优化器可能会选择此策略或其他连接策略(可用选项将取决于RDBMS here is a summary of some common join algorithms)。
将选择哪个将取决于各种问题,包括JOIN条件(例如,一些仅适用于equijoins),数据是否已经排序,可用内存量,表的大小,索引的可用性等。