繁体   English   中英

为什么使用 inner join 本身比 where 更快

[英]Why using inner join itself is more faster than where

这是我的桌子:

CREATE TABLE `cerp_oms_order` (
  `id` bigint NOT NULL,
  `company_id` bigint NOT NULL,
  `order_no` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,
  `source_type` int NOT NULL,
  `shop_id` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,
  `outer_shop` varchar(64) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,
  `origin_status` int NOT NULL,
  `system_status` int NOT NULL,
  `created_time` datetime DEFAULT NULL,
  `paid_time` datetime DEFAULT NULL,
  `sent_time` datetime DEFAULT NULL,
  `end_time` datetime DEFAULT NULL,
  `modify_time` datetime DEFAULT NULL,
  `delivery_deadline_time` datetime DEFAULT NULL,
  `amount` text CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL ,
  `spu_kind` int NOT NULL,
  `sku_kind` int NOT NULL,
  `total_quantity` decimal(16,4) NOT NULL,
  `buyer_id` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,
  `outer_buyer_identifier` varchar(64) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '',
  `tax_info` varchar(256) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL,
  `warehouse_owner` int DEFAULT NULL,
  `warehouse_id` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL,
  `logistics_type` int NOT NULL,
  `logistics_outer_info` varchar(256) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL,
  `delivery_id` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL,
  `delivery_no` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL,
  `wave_no` varchar(64) DEFAULT '',
  `is_deleted` tinyint NOT NULL DEFAULT '0',
  `backend_processing_type` tinyint NOT NULL,
  `create_type` tinyint NOT NULL,
  `is_hang_up` tinyint NOT NULL,
  `hang_up_case_type` smallint DEFAULT NULL,
  `hang_up_case_id` bigint DEFAULT NULL,
  `rc_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
  `rm_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  `vat` varchar(128) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL,
  `weight` decimal(16,4) NOT NULL DEFAULT '0.0000',
  `volume` decimal(16,4) NOT NULL DEFAULT '0.0000',
  `is_abnormal` tinyint NOT NULL DEFAULT '0',
  `estimate_profit` decimal(16,4) NOT NULL DEFAULT '0.0000',
  `business_man_id` varchar(256) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL,
  `business_man` varchar(256) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL,
  `currency` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL,
  `net_amount_summary` decimal(19,4) NOT NULL,
  `domestic_amount` decimal(19,4) NOT NULL,
  `secret_key` varchar(64) DEFAULT '',
  `secretKey` varchar(255) DEFAULT NULL,
  `sale_id` bigint DEFAULT NULL,
  `total_refund_include_tax` decimal(16,4) NOT NULL DEFAULT '0.0000',
  `total_refund_money` decimal(16,4) NOT NULL DEFAULT '0.0000',
  `total_refund_tax` decimal(16,4) NOT NULL DEFAULT '0.0000',
  `total_return_goods` decimal(16,2) NOT NULL DEFAULT '0.00',
  PRIMARY KEY (`id`),
  UNIQUE KEY `key_order_no` (`order_no`),
  KEY `idx_order_company_id` (`company_id`,`created_time`),
  KEY `IDX_RM_TIME` (`rm_time`),
  KEY `IDX_IS_ABNORMAL` (`is_abnormal`),
  KEY `cerp_oms_order_company_id_index` (`company_id`),
  KEY `idx_order_company_status_deleted` (`company_id`,`is_deleted`,`system_status`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='system order table'
explain select *
from cerp_oms_order
         inner join (select id
                     from cerp_oms_order
                     where source_type = 43
                     order by created_time) as tmp using (id);
ID 选择类型 桌子 分区 类型 可能的键 钥匙 密钥长度 参考 过滤 额外的
1个 简单的 cerp_oms_order null 全部 基本的 null null null 60787 10 在哪里使用
1个 简单的 cerp_oms_order null eq_ref 基本的 基本的 8个 cerp_oms_1.cerp_oms_order.id 1个 100 null

使用内部连接execution: 7 ms, fetching: 109 ms

VS

explain
select *
from cerp_oms_order
where source_type = 43
order by created_time;
ID 选择类型 桌子 分区 类型 可能的键 钥匙 密钥长度 参考 过滤 额外的
1个 简单的 cerp_oms_order null 全部 null null null null 60787 10 在哪里使用; 使用文件排序

使用简单的 where 子句execution: 80 ms, fetching: 138 ms

我不明白为什么使用inner join可以加速我的 sql?

如果你有

INDEX(source_type, created_time)

两种配方都会运行得更快。 而且,我认为,第二个会更快。

至于“为什么”。 看看第二个做了什么:

  1. 扫描整个表(“表扫描”)以查找source_type = 43的行。
  2. 对于每个匹配的行,将行中的所有列 ( * ) 收集到一个临时表中。
  3. 对该临时表进行排序。 请注意,这比仅包含id的子查询要庞大。
  4. 交付结果。

使用INDEX我建议:

  1. 在索引的 B+Tree 中查找source_type = 43的所有“行”。
  2. 由于这些行按created_time排序,现在或以后都不需要“排序”传递。
  3. 这些索引行中的每一个都将包含id (这就是 InnoDB 到达列的 rest 的方式),所以
  4. 在数据的 B+ 树中查找所需的行并拉出所有 ( * ) 列。
  5. 交付它们。

请注意, JOIN版本的工作原理基本相同,但从技术上讲, ORDER BY可能会丢失。 如果它确实丢失了,您将需要添加第二个ORDER BY ,从而强制进行排序。

(不相关)您的“KEY cerp_oms_order_company_id_index ( company_id )”可以删除,因为还有另外两个以company_id开头的索引。

有关优化索引的更多信息: Index Cookbook

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM