首页 > 解决方案 > 为什么 OpenCart 使用子查询而不是 LEFT JOIN?

问题描述

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

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

标签: mysqlopencartopencart-3

解决方案


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

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

它也看起来像是表user_group_id中的唯一键user_group,因此子查询将最多返回一行。(在更一般的情况下,如果子查询返回多于一行,我们会得到一个错误。使用 LEFT JOIN,我们会返回多行。)


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

答:任何一种形式都不会造成性能损失。具有相关子查询的表单可能会更快,但差异并不显着。

问:如果是的话怎么办?如果不是,那么为什么这个主要社区使用这种方式?

A:它是有效的 SQL,它可以工作,并且没有任何改变的动力。

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

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

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

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


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


推荐阅读