MySQL派生表(derived)优化一例
1、什么是派生表derived
关键字:子查询-->在From后where前的子查询
例子:
mysql> explain select * from (select * from t) a where id=2;
+----+-------------+------------+------+---------------+-------------+---------+-------+------+-------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+------------+------+---------------+-------------+---------+-------+------+-------+
| 1 | PRIMARY | <derived2> | ref | <auto_key0> | <auto_key0> | 4 | const | 0 | NULL |
| 2 | DERIVED | t | ALL | NULL | NULL | NULL | NULL | 4 | NULL |
+----+-------------+------------+------+---------------+-------------+---------+-------+------+-------+
主要经历以下三步:
1、执行子查询,select * from t
2、把子查询的结果写到临时表 A表
3、回读,应用上层SELECT的WHERE条件 id=2。
执行这样的子查询是非常低效的,因为扫描基表 t 时没有使用父选择(id=2)的高选择性条件。 我们从t表中读取太多记录,然后我们必须将它们写入一个临时表并再次读取,然后才能过滤掉它们。
Oracle DBA一定觉得它很傻,不错贼J儿啥,这尼玛都不能子查询展开。
MySQL 5.7开始优化器引入derived_merge,可以理解为Oracle的子查询展开,有优化器参数optimizer_switch='derived_merge=ON’来控制,默认为打开。
但是仍然有很多限制,当派生子查询存在以下操作时该特性无法生效:UNION 、GROUP BY、DISTINCT、LIMIT/OFFSET以及聚合操作
2、派生表SQL优化一例
mysql> select @@version;
+------------+
| @@version |
+------------+
| 5.6.16-log |
+------------+
SELECT A.*, b.vendor_name, c.chinese_name, c.english_name, d.name AS category_name, e.value, a.season_codeFROM PR_XXX ALEFT JOIN VXX BON A.VENDOR_ID = B.VENDOR_IDLEFT JOIN BXX CON A.BRAND_ID = C.BRAND_IDLEFT JOIN CXX DON A.CATEGORY_ID = D.CATEGORY_IDLEFT JOIN PXX EON A.PRODUCT_ID = E.PRODUCT_IDINNER JOIN (SELECT SS.PRODUCT_IDFROM SKU_XXX SSWHERE SS.ENABLED = 1GROUP BY SS.PRODUCT_IDHAVING SUM(SS.STORE) >= 1) STON ST.PRODUCT_ID = A.PRODUCT_IDWHERE A.vendor_id = 91011AND A.enabled = 1AND A.status = '1'AND a.season_code = '5678'AND 1 = 1AND a.brand_id = '1234'AND E.KEY_NAME = 'XXX'ORDER BY product_id LIMIT 0, 10
执行计划如下:
+----+-------------+------------+-------------+----------------------------------------------------------------+-----------------------------------+---------+--------------------------+---------+---------------------------------------------------------------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+------------+-------------+----------------------------------------------------------------+-----------------------------------+---------+--------------------------+---------+---------------------------------------------------------------------------------+
| 1 | PRIMARY | A | index_merge | PRIMARY,vendor_id,IDX_VENDOR_ID_STATUS,IDX_BRAND_ID,IDX_STATUS | IDX_VENDOR_ID_STATUS,IDX_BRAND_ID | 9,8 | NULL | 5 | Using intersect(IDX_VENDOR_ID_STATUS,IDX_BRAND_ID); Using where; Using filesort |
| 1 | PRIMARY | B | const | PRIMARY | PRIMARY | 8 | const | 1 | NULL |
| 1 | PRIMARY | C | const | PRIMARY | PRIMARY | 8 | const | 1 | Using where |
| 1 | PRIMARY | D | eq_ref | PRIMARY | PRIMARY | 8 | ger-prd-db.A.category_id | 1 | NULL |
| 1 | PRIMARY | E | ref | IDX_PRODUCT_PROPERTY_PRODUCT_ID | IDX_PRODUCT_PROPERTY_PRODUCT_ID | 8 | ger-prd-db.A.product_id | 3 | Using where |
| 1 | PRIMARY | <derived2> | ref | <auto_key0> | <auto_key0> | 9 | ger-prd-db.A.product_id | 10 | Using index |
| 2 | DERIVED | SS | index | IDX_PRODUCT_ID | IDX_PRODUCT_ID | 9 | NULL | 1715829 | Using where |
+----+-------------+------------+-------------+----------------------------------------------------------------+-----------------------------------+---------+--------------------------+---------+---------------------------------------------------------------------------------+
关键表索引信息
mysql> show index from PR_XXX ;
+---------+------------+-------------------------+--------------+--------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment |
+---------+------------+-------------------------+--------------+--------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| PR_XXX | 0 | PRIMARY | 1 | product_id | A | 283783 | NULL | NULL | | BTREE | | |
| PR_XXX | 0 | vendor_id | 1 | vendor_id | A | 92 | NULL | NULL | | BTREE | | |
| PR_XXX | 0 | vendor_id | 2 | product_code | A | 283783 | NULL | NULL | | BTREE | | |
| PR_XXX | 1 | IDX_VENDOR_ID_STATUS | 1 | vendor_id | A | 82 | NULL | NULL | | BTREE | | |
| PR_XXX | 1 | IDX_VENDOR_ID_STATUS | 2 | status | A | 392 | NULL | NULL | | BTREE | | |
| PR_XXX | 1 | IDX_BRAND_ID | 1 | brand_id | A | 2866 | NULL | NULL | | BTREE | | |
| PR_XXX | 1 | IDX_STATUS | 1 | status | A | 10 | NULL | NULL | | BTREE | | |
| PR_XXX | 1 | IDX_PRODUCT_CATEGORY_ID | 1 | category_id | A | 276 | NULL | NULL | | BTREE | | |
| PR_XXX | 1 | IDX_SPU_ID | 1 | spu_id | A | 283783 | NULL | NULL | YES | BTREE | | |
+---------+------------+-------------------------+--------------+--------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
9 rows in set (0.00 sec)mysql> show index from SKU_XXX;
+-----------+------------+----------------+--------------+--------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment |
+-----------+------------+----------------+--------------+--------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| SKU_XXX | 0 | PRIMARY | 1 | sku_store_id | A | 1715829 | NULL | NULL | | BTREE | | |
| SKU_XXX | 1 | IDX_SKU_ID | 1 | sku_id | A | 1715829 | NULL | NULL | YES | BTREE | | |
| SKU_XXX | 1 | IDX_PRODUCT_ID | 1 | product_id | A | 857914 | NULL | NULL | YES | BTREE | | |
+-----------+------------+----------------+--------------+--------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
建议进行SQL改写:
SELECT A.*, b.vendor_name, c.chinese_name, c.english_name, d.name as category_name, e.value, a.season_codeFROM PR_XXX ALEFT JOIN VXX BON A.VENDOR_ID = B.VENDOR_IDLEFT JOIN BXX CON A.BRAND_ID = C.BRAND_IDLEFT JOIN CXX DON A.CATEGORY_ID = D.CATEGORY_IDLEFT JOIN PXX EON A.PRODUCT_ID = E.PRODUCT_IDINNER JOIN SKU_XXX SSON SS.ENABLED = 1and SS.PRODUCT_ID = A.PRODUCT_IDwhere A.vendor_id = 20AND A.enabled = 1AND A.status = '1'AND a.season_code = '18SS'AND 1 = 1AND a.brand_id = '247'AND E.KEY_NAME = 'BrandID'and SS.ENABLED = 1GROUP BY a.PRODUCT_IDhaving SUM(SS.STORE) >= 1ORDER BY a.product_id limit 0, 10;
改写后的执行计划
+----+-------------+-------+-------------+---------------------------------------------------------------------------------------------------+-----------------------------------+---------+--------------------------+------+--------------------------------------------------------------------------------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+-------------+---------------------------------------------------------------------------------------------------+-----------------------------------+---------+--------------------------+------+--------------------------------------------------------------------------------------------------+
| 1 | SIMPLE | A | index_merge | PRIMARY,vendor_id,IDX_VENDOR_ID_STATUS,IDX_BRAND_ID,IDX_STATUS,IDX_PRODUCT_CATEGORY_ID,IDX_SPU_ID | IDX_VENDOR_ID_STATUS,IDX_BRAND_ID | 9,8 | NULL | 5 | Using intersect(IDX_VENDOR_ID_STATUS,IDX_BRAND_ID); Using where; Using temporary; Using filesort |
| 1 | SIMPLE | B | const | PRIMARY | PRIMARY | 8 | const | 1 | NULL |
| 1 | SIMPLE | C | const | PRIMARY | PRIMARY | 8 | const | 1 | Using where |
| 1 | SIMPLE | D | eq_ref | PRIMARY | PRIMARY | 8 | ger-prd-db.A.category_id | 1 | NULL |
| 1 | SIMPLE | SS | ref | IDX_PRODUCT_ID | IDX_PRODUCT_ID | 9 | ger-prd-db.A.product_id | 2 | Using where |
| 1 | SIMPLE | E | ref | IDX_PRODUCT_PROPERTY_PRODUCT_ID | IDX_PRODUCT_PROPERTY_PRODUCT_ID | 8 | ger-prd-db.A.product_id | 3 | Using where |
+----+-------------+-------+-------------+---------------------------------------------------------------------------------------------------+-----------------------------------+---------+--------------------------+------+--------------------------------------------------------------------------------------------------+
优化前:2 rows in set (2.12 sec)
优化后:2 rows in set (0.00 sec)
MySQL派生表(derived)优化一例相关推荐
- MySQL数据表设计优化
MySQL数据表设计优化 一.选择优化的数据类型 二.范式和反范式 2.1 范式 2.2 范式优缺点 2.3 反范式 2.3 反范式优缺点 2.4 混用范式化和反范式化 三.使用缓存表和汇总表 一.选 ...
- MySQL 派生表(Derived Table)是什么
本文将通过演示告诉你:MySQL 中派生表(Derived Table)是什么?以及 MySQL 对它的优化. Background 有如下一张表: mysql> desc city; +--- ...
- mysql派生表(Derived Table)简单解析使用的小例子
关于这个派生表啊,我们首先得知道,派生表是从select语句返回的虚拟表.派生表类似于临时表,但是在SELECT语句中使用派生表比临时表简单得多,因为它不需要创建临时表的步骤.所以当SELEC ...
- mysql 派生表 索引_MySQL 索引初探
MYSQL索引 什么是索引 为什么要建立索引 索引的优缺点和使用原则 索引的分类 单列索引:一个索引只包含单个列,但一个表中可以有多个单列索引. 普通索引:MySQL中基本索引类型,没有什么限制,允许 ...
- MySQL派生表联表查询记录
前情提要:公司运营的一个商城系统,忽然发现订单提现功能有问题,有大量的商户体现金额和订单金额不一致.于是产生了需求,需要把提现表和供应商表作为一个结果集,连接上订单表中的订单金额,通过计算订单表的金额 ...
- Mysql大表的优化
当MySQL单表记录数过大时,增删改查性能都会急剧下降,可以参考以下步骤来优化: 单表优化 除非单表数据未来会一直不断上涨,否则不要一开始就考虑拆分,拆分会带来逻辑.部署.运维的各种复杂度,一般以整型 ...
- MySQL单表膨胀优化之MyCat分库分表
MySQL的单表达到多少量级时性能会下降?宽表在千万量级,窄表要好一点在1200W左右.但是MySQL单表达到1500W时性能开始急剧下降! 事实上MySQL单表可以存储10亿级数据,只是这时候性能比 ...
- MySQL 大表性能优化
单表优化 除非单表数据未来会一直不断上涨,否则不要一开始就考虑拆分,拆分会带来逻辑.部署.运维的各种复杂度,一般以整型值为主的表在千万级以下,字符串为主的表在五百万以下是没有太大问题的.而事实上很多时 ...
- mysql myisam表_mysql优化之MyISAM表锁
概述 MyISAM存储引擎只支持表锁,mysql的表锁有两种模式:读锁和写锁. 他们的兼容关系是(对myisam的读操作,不会阻塞其他用户对同一表的读请求,但会阻塞对同一表的写操作*)和(对myisa ...
最新文章
- Ubuntu最简单的方式安装NVIDIA显卡驱动和cuda工具
- Spring的常用注解,SpringMVC常用注解
- 浅谈 Spring 框架注解的用法分析
- activiti 变量_如何在Activiti中使用瞬态变量
- 前端学习(1990)vue之电商管理系统电商系统之自定义时间过滤器
- STM32的ADC通道间干扰的问题
- Redis官网——如何利用Redis做服务器集群的分布式锁
- 博途中用的是c吗_博图WINCC里如何添加c脚本
- int是终结符还是非终结符_什么是自动化的终结?
- Linux网络属性及其配置
- 实现人脸手动祛痘效果---OpenCV-Python开发指南(60)
- WordPiece、BPE详解及代码
- 人工智能和算法,有望帮助欧洲解决头大的难民问题
- 关于“TCP segment of a reassembled PDU”
- STM32单片机的PSAM卡驱动模块设计
- 串口COM线转USB的console线无法更新驱动
- Invalid bound statement (not found)错误的几种解决方法
- 王左中右致出版商的信件稿
- Error running ‘JeeplusWebApplication‘: Command line is too long. Shorten command line for JeeplusWeb
- 51c语言字符,51单片机C语言教程(九) 语句应用