You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

同表Insert Select语句优化:子查询与JOIN方案对比分析

问题描述

我需要从同一张表的现有记录插入新租户数据,新租户要继承父租户0904ba44-9d41-418a-bbd8-2c70506c3432的域名。我感觉用JOIN的方案更好,想确认这个判断对不对,以此提升自己的SQL优化能力。下面是两个可行的INSERT语句和对应的执行计划:


子查询方案

INSERT INTO tenant (tenant_uuid, secondary_domain)
VALUES (
  UUID_TO_BIN(UUID()),
  (SELECT secondary_domain FROM (SELECT top_level_domain FROM tenant WHERE tenant_uuid = UUID_to_bin('0904ba44-9d41-418a-bbd8-2c70506c3432')) as b ));

执行计划:

+-----+--------------+---------------+-------------+-----------+------------------------+------------+----------+----------+-------+-----------+--------+
| id  |  select_type |     table     |  partitions |    type   |      possible_keys     |     key    |  key_len |    ref   |  rows |  filtered |  Extra |
+-----+--------------+---------------+-------------+-----------+------------------------+------------+----------+----------+-------+-----------+--------+
| '1' |  'INSERT'    |  'tenant'     |  NULL       |  'ALL'    |  NULL                  |  NULL      |  NULL    |  NULL    |  NULL |  NULL     |  NULL  |
| '2' |  'SUBQUERY'  |  '<derived3>' |  NULL       |  'system' |  NULL                  |  NULL      |  NULL    |  NULL    |  '1'  |  '100.00' |  NULL  |
| '3' |  'DERIVED'   |  'tenant'     |  NULL       |  'const'  |  'PRIMARY tenant_uuid' |  'PRIMARY' |  '16'    |  'const' |  '1'  |  '100.00' |  NULL  |
+-----+--------------+---------------+-------------+-----------+------------------------+------------+----------+----------+-------+-----------+--------+

JOIN方案

INSERT INTO tenant (tenant_uuid, secondary_domain)
VALUES (
  UUID_TO_BIN(UUID()),
  (SELECT b.secondary_domain FROM tenant a INNER JOIN tenant b on a.tenant_uuid = b.tenant_uuid WHERE b.tenant_uuid = UUID_to_bin('0904ba44-9d41-418a-bbd8-2c70506c3432'));

执行计划:

+------+--------------+-----------+-------------+----------+------------------------+------------+----------+----------+-------+-----------+----------------+
| # id |  select_type |   table   |  partitions |   type   |      possible_keys     |     key    |  key_len |    ref   |  rows |  filtered |      Extra     |
+------+--------------+-----------+-------------+----------+------------------------+------------+----------+----------+-------+-----------+----------------+
| '1'  |  'INSERT'    |  'tenant' |  NULL       |  'ALL'   |  NULL                  |  NULL      |  NULL    |  NULL    |  NULL |  NULL     |  NULL          |
| '2'  |  'SUBQUERY'  |  'a'      |  NULL       |  'const' |  'PRIMARY tenant_uuid' |  'PRIMARY' |  '16'    |  'const' |  '1'  |  '100.00' |  'Using index' |
| '2'  |  'SUBQUERY'  |  'b'      |  NULL       |  'const' |  'PRIMARY tenant_uuid' |  'PRIMARY' |  '16'    |  'const' |  '1'  |  '100.00' |  NULL          |
+------+--------------+-----------+-------------+----------+------------------------+------------+----------+----------+-------+-----------+----------------+

方案对比与结论

你的直觉不正确,子查询方案的效率反而略优,原因如下:

  • 执行开销:子查询仅对tenant表做了一次主键查询(id=3的DERIVED查询,type为const,直接命中主键),后续派生表的处理几乎无开销;而JOIN方案做了两次主键查询(表a和表b各一次),额外的自关联逻辑会产生不必要的微小开销。
  • 逻辑合理性:这个场景只需要获取单个租户的域名,完全不需要自关联JOIN,子查询的写法更贴合需求逻辑,也更简洁。

另外,你的子查询写法可以进一步简化,去掉多余的嵌套:

INSERT INTO tenant (tenant_uuid, secondary_domain)
VALUES (
  UUID_TO_BIN(UUID()),
  (SELECT secondary_domain FROM tenant WHERE tenant_uuid = UUID_to_bin('0904ba44-9d41-418a-bbd8-2c70506c3432'))
);

简化后的版本执行计划会更高效,直接通过一次const主键查询就能拿到结果,省去了派生表的额外处理步骤。

内容的提问来源于stack exchange,提问作者williamohara

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.18 19:55:18