为什么 OpenCart 使用 Subquery 而不是 LEFT JOIN?

Why OpenCart uses Subquery instead of LEFT JOIN?

最近我在研究 opencart 源代码,我发现它使用子查询而不是 LEFT JOIN。

Opencart v3 在文件 admin/model/user/user.php

上查看
$query = "SELECT *, (
        SELECT ug.name 
        FROM `" . DB_PREFIX . "user_group` ug 
        WHERE ug.user_group_id = u.user_group_id
    ) AS user_group
    FROM `" . DB_PREFIX . "user` u
    WHERE u.user_id = '" . (int)$user_id . "'"; 

我会这样使用

$query = "SELECT u.*, ug.name AS user_group 
    FROM `" . DB_PREFIX . "user` u 
    LEFT JOIN `" . DB_PREFIX . "user_group` ug ON ug.user_group_id = u.user_group_id
    WHERE u.user_id = '" . (int)$user_id . "'";

我的问题是,在 Select 列中使用子查询是否有任何性能改进?如果是的话怎么办?如果不是,那么为什么这个主要社区使用这种方式? 我还发现他们没有使用外键,知道为什么吗?

当外部查询处理大量行时,相关子查询可能会成为性能问题;因为子查询会针对每一行执行。

看起来这个查询 return 最多一行,因为它看起来 user_id 是一个唯一键。由于外部查询 returns(最多)一行,子查询将只执行一次。

看起来 user_group_iduser_group table 中的唯一键,因此子查询最多 return 一行。 (在更一般的情况下,如果子查询 return 多于一行,我们会得到一个错误。使用 LEFT JOIN,我们会得到多行 returned。)


问:在Select列中使用子查询是否有任何性能改进?

A:这两种形式都不会影响性能。关联子查询的形式可能会更快,但差别不大。

问:如果是怎么回事?如果不是那么为什么这个主要社区使用这种方式?

答:有效SQL,有效,没有动力去改变。

问:另外我发现他们没有使用外键,知道为什么吗?

A:没有要求 RDBMS 强制参照完整性;如果应用程序正在处理它,那么我们可以避免数据库中的开销。

一些存储引擎(例如 MyISAM)不强制执行外键约束。

外键有时会干扰管理操作,例如清空和重新加载 table。


这都是设计决策;给猫剥皮有多种方法。 (我们在这里只是略过表面;更深入的研究将更多地基于意见,以争论哪种剥猫皮的方法更好。)