最近我研究的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列中使用子查询是否有任何性能改进?如果是的话怎么样?如果不是那么为什么这个主要社区正在使用这种方式?另外我发现他们没有使用外键,任何想法为什么?
当外部查询处理大量行时,相关子查询可能会成为性能问题;因为每个行都会执行子查询。
看起来这个查询最多返回一行,因为它看起来像user_id
是一个唯一的键。由于外部查询返回(最多)一行,因此子查询只会执行一次。
它看起来像user_group_id
是user_group
表中的唯一键,因此子查询最多只返回一行。 (在更一般的情况下,如果子查询返回的行多一行,我们就会收到错误。使用LEFT JOIN,我们会返回多行。)
问:使用Select列中的子查询是否有任何性能改进?
答:任何一种形式都不会有性能损失。具有相关子查询的表单可能更快,但差异不显着。
问:如果是的话怎么样?如果不是那么为什么这个主要社区正在使用这种方式?
答:这是有效的SQL,它有效,并且没有动力进行更改。
问:我还发现他们没有使用外键,不知道为什么?
答:没有要求RDBMS强制执行参照完整性;如果应用程序正在处理它,那么我们可以避免数据库中的开销。
某些存储引擎(例如MyISAM)不强制执行外键约束。
外键有时会干扰管理操作,例如清空和重新加载表。
这是所有设计决策;皮肤猫有多种方法。 (我们只是在这里略读表面;更深入的潜水将更多的基于意见,以争论哪种方式皮肤猫更好。)