嵌套查询比连接查询快吗?

Is nested query faster than join query?

每个table数据中有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)){

    }
}

哪个结果更快? (我已经索引了所有 tables)

答案与大多数数据库一样,视情况而定。


首先,请注意两种查询模式的结果有很大不同。

例如,考虑当 table_3 为空(不包含任何行)时会发生什么。使用 JOIN 查询模式,我们不会得到任何返回...结果集将包含零行。

另一个查询,运行对每个 table、 return 行 table_1table_2.

此外,使用 JOIN 模式,我们将从 table_1、table_2...

获取数据的冗余副本 return

但就 "faster" 而言,通常 JOIN 模式会更快,因为它消除了很多与数据库的往返。发送 SQL、解析标记、语义检查、制定执行计划、执行计划、准备结果集、return 将结果集发送给客户端、等待客户端进行提取,以及然后清理(关闭语句句柄并丢弃结果集。)

当数据库往返次数急剧增加时,每个语句执行的小开销开始累积起来。

好处是对于一个简单的查询,往往需要考虑的执行路径数量较少,而且我们通常会为每个查询获得一个相当有效的计划(假设 suitable 索引可用。


JOIN 模式的风险在于我们可以生成一个非常大的集合,其中每行包含大量冗余数据。


让我们考虑一个场景:

如果我们在 table_1 中有 1,000 行。

如果我们在 table_2 中有 1,000 行,对于 table_1 中的每一行。

如果 table_2 中的每一行在 table_3 中有 100 行。

如果 table_4 中的每一行在 table_3 中有 10 行。

如果 table_4 中的每一行我们在 table_5 中得到 1 行。

这里有一些快速数学... 10^3 ^ 10^3 * 10^2 * 10^1 * 10^0 = 10^9

这将导致结果集中有 10 亿行。 table_1 中每一行的数据将重复 10^6 次。那是一百万份相同的 table_1 值。

我们有可能获得 "very large" 个结果集,并相应增加资源需求,这可能会导致性能下降。

所以我们倾向于中间立场。我们更喜欢处理集而不是处理 RBAR(逐行处理),但我们也想避免 Hugh Jass 结果集。

最佳性能可能介于这两种方法之间。例如,通过在循环中处理来自 table_1 的单独行,并且对于检索到的每一行,我们 运行 对 JOIN 中剩余的四个 table 进行查询以获取组合结果.