嵌套查询比连接查询快吗? [复制]
Posted
技术标签:
【中文标题】嵌套查询比连接查询快吗? [复制]【英文标题】:Is nested query faster than join query? [duplicate] 【发布时间】:2018-10-14 03:40:35 【问题描述】:每张表数据有1万多条记录。列出此数据时,什么查询结果更快。嵌套查询比连接查询快吗?
嵌套查询:
$query = $baglanti->prepare("Select * from table_1");
$query->execute();
if($query->rowCount() > 0)
while($query_data=$query->fetch(PDO::FETCH_ASSOC))
$query_2 = $baglanti->prepare("Select * from table_2 where table_1_id = :id");
$query_2->bindParam(":id", $query_data["id"], PDO::PARAM_INT);
$query_2->execute();
if($query_2->rowCount() > 0)
while($query_2_data=$query_2->fetch(PDO::FETCH_ASSOC))
$query_3 = $baglanti->prepare("Select * from table_3 where table_2_id = :id");
$query_3->bindParam(":id", $query_2_data["id"], PDO::PARAM_INT);
$query_3->execute();
if($query_3->rowCount() > 0)
while($query_3_data=$query_3->fetch(PDO::FETCH_ASSOC))
table_4
table_5
...
内连接查询:
$query = $baglanti->prepare("Select * from table_1
INNER join table_2
on table_1.id=table_2.table_1_id
INNER join table_3
on table_2.id=table_3.table_2_id
INNER join table_4
on table_3.id=table_4.table_3_id
INNER join table_5
on table_4.id=table_5.table_4_id
...
");
$query->execute();
if($query->rowCount() > 0)
while($query_data=$query->fetch(PDO::FETCH_ASSOC))
哪个结果更快? (我已经索引了所有的表)
【问题讨论】:
内连接应该工作得更快。嵌套查询几乎总是运行较慢 我无法想象嵌套查询会运行得更快的场景。每个人都必须打开一个会话,发送 sql,解析 sql,优化/确定执行路径,运行执行路径,通过管道将数据推送回应用程序。使用 JOIN 是一次访问数据库,然后数据库一次获取所有数据并加入它(它专门编程为有效地执行 CRAZY),然后返回一个结果集。JOIN
可以让数据库优化器更好地构建检索数据的方式,并过滤不需要的数据。
@JNevill 如果“父数据”包含大量数据,这些数据将乘以大量的小“子数据”,嵌套可能会更好......但即便如此,也有更好的非嵌套选项。
【参考方案1】:
与大多数事物数据库一样,答案是视情况而定。
首先,请注意,两种查询模式的结果存在显着差异。
例如,考虑当table_3
为空(不包含行)时会发生什么。使用 JOIN 查询模式,我们不会得到任何返回...结果集将包含零行。
另一个查询,对每个表运行单独的查询,将从table_1
和table_2
返回行。
此外,使用 JOIN 模式,我们将从 table_1、table_2... 返回数据的冗余副本...
但就“更快”而言,通常 JOIN 模式会更快,因为它消除了很多到数据库的往返。发送SQL,解析token,语义检查,制定执行计划,执行计划,准备resultset,将resultset返回给客户端,等待客户端进行fetch,然后清理(关闭语句句柄和丢弃结果集。)
当数据库往返次数急剧增加时,每条语句执行的小额开销开始显着累积。
好处是,对于一个简单的查询,需要考虑的执行路径数量往往较少,而且我们通常会为每个查询制定一个相当有效的计划(假设有合适的索引可用。
JOIN 模式的风险在于我们可以生成一个非常大的集合,其中每行包含大量冗余数据。
让我们考虑一个场景:
如果我们在 table_1 中有 1000 行。
如果我们在 table_2 中为 table_1 中的每一行有 1,000 行。
如果我们在 table_3 中为 table_2 中的每一行有 100 行。
如果我们在 table_4 中有 10 行对应 table_3 中的每一行。
如果我们在 table_5 中有 1 行对应 table_4 中的每一行。
这里有一些快速的数学运算... 10^3 ^ 10^3 * 10^2 * 10^1 * 10^0 = 10^9
这将导致结果集中有 10 亿行。 table_1 中每一行的数据将重复 10^6 次。这是相同 table_1 值的一百万个副本。
我们有可能获得“非常大”的结果集,并相应增加资源需求,这可能会导致性能损失。
所以我们倾向于中间立场。我们更喜欢处理集合而不是处理 RBAR(逐行处理),但我们也希望避免使用 Hugh Jass 结果集。
在这两种方法之间可能会获得最佳性能。例如,通过在循环中处理 table_1 中的各个行,并且对于检索到的每一行,我们对 JOIN 中的其余四个表运行查询以获取组合结果。
【讨论】:
以上是关于嵌套查询比连接查询快吗? [复制]的主要内容,如果未能解决你的问题,请参考以下文章
数据库的SQL语句中,嵌套查询和连接查询有啥区别,说的详细的
MySQL 基础 -- 多表关系(一对一1对多(多对一)多对多)多表查询(内连接外连接自连接子查询(嵌套查询)联合查询 union)笛卡儿积