ToB企服应用市场:ToB评测及商务社交产业平台

标题: Mysql系列-索引优化 [打印本页]

作者: 立聪堂德州十三局店    时间: 2024-9-20 06:56
标题: Mysql系列-索引优化
1 Explain工具先容

使用Explain关键字可以模仿优化器执行SQL语句,分析查询语句或结构的性能瓶颈,在select语句之前增长explain关键字,mysql会在查询上设置一个标志,执行查询会返回执行计划的信息,而不是执行当前SQL;
其中:如果from中包含子查询,仍会执行该子查询,将结果放入临时表中;
2 Explain示例分析

2.1 预备表

  1. CREATE TABLE `mall_order` (
  2.   `id` bigint NOT NULL AUTO_INCREMENT COMMENT '自增id',
  3.   `shop_id` bigint NOT NULL DEFAULT '0' COMMENT '店铺id',
  4.   `memeber_id` bigint NOT NULL DEFAULT '0' COMMENT '卖家id',
  5.   `order_no` varchar(32) NOT NULL DEFAULT '' COMMENT '订单号',
  6.   `order_amount` bigint NOT NULL DEFAULT '0' COMMENT '订单金额',
  7.   `pay_money` bigint NOT NULL DEFAULT '0' COMMENT '支付金额',
  8.   `order_state` int NOT NULL DEFAULT '0' COMMENT '订单状态',
  9.   `address` varchar(512) NOT NULL DEFAULT '' COMMENT '地址',
  10.   `soure` varchar(5) NOT NULL DEFAULT '' COMMENT '订单来源',
  11.   `create_time` timestamp NOT NULL DEFAULT '2000-01-01 00:00:00',
  12.   PRIMARY KEY (`id`),
  13.   KEY `idx_m_s_id` (`shop_id`,`memeber_id`,`address`) USING BTREE
  14. ) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8mb4 COMMENT='订单表';
  15. CREATE TABLE `mall_order_item` (
  16.   `id` bigint NOT NULL AUTO_INCREMENT COMMENT '自增id',
  17.   `order_id` bigint NOT NULL DEFAULT '0' COMMENT '订单id',
  18.   `item_id` bigint NOT NULL DEFAULT '0' COMMENT '卖家id',
  19.   `item_name` varchar(512) NOT NULL DEFAULT '' COMMENT '商品名称',
  20.   `item_amount` bigint NOT NULL DEFAULT '0' COMMENT '商品金额',
  21.   `item_count` bigint NOT NULL DEFAULT '0' COMMENT '商品数量',
  22.   `pay_money` bigint NOT NULL DEFAULT '0' COMMENT '支付金额',
  23.   `create_time` timestamp NOT NULL DEFAULT '2000-01-01 00:00:00',
  24.   PRIMARY KEY (`id`),
  25.   KEY `idx_o_itemn_id` (`order_id`,`item_name`) USING BTREE
  26. ) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8mb4 COMMENT='订单明细';
  27. CREATE TABLE `member_address` (
  28.   `id` bigint NOT NULL AUTO_INCREMENT COMMENT '自增id',
  29.   `memeber_id` bigint NOT NULL DEFAULT '0' COMMENT '买家id',
  30.   `address` varchar(255) NOT NULL DEFAULT '' COMMENT '地址',
  31.   `create_time` timestamp NOT NULL DEFAULT '2000-01-01 00:00:00',
  32.   PRIMARY KEY (`id`)
  33. ) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8mb4 COMMENT='买家收货地址';
复制代码
2.2 explain常用语法

  1. explain select * from mall_order where memeber_id = 2;
复制代码
  1. explain select * from mall_order where memeber_id = 2;
  2. show WARNINGS;
复制代码



2.3 explain中的列 

2.3.1 id


2.3.2 select_type

   select_type表现对应行是简单查询还是复杂查询
  1)simple:简单查询,查询不包含子查询和union

2)primary:复杂查询中最外层的select
3)subquery:包含在select中的子查询(不是在from中的子句中)
4)derived:包含在from字句中的子查询。mysql会将查询结果存放在一个临时表中,也称为派生(衍生表)表
  1. set session optimizer_switch='derived_merge=off'; -- 5.7起mysql对衍生表进行了合并优化,此处临时关闭
  2. explain select (select 1 from mall_order_item where id = 1) from (select * from mall_order where memeber_id = 2)tt ;
复制代码

5)union:在union中的第二个和随后的select 
  1. explain select * from mall_order where id = 1 union select * from mall_order where id = 2;
复制代码

2.3.3 table

   table列表现正在访问哪个表。
  

2.3.4 type 

   type列表现关联类型或访问类型,即mysql决定如何查询表中的行,查找数据行记录的大概范围。 
  依次从最优到最差:system>const>eq_ref>ref>range>index>ALL
  优化结果:一样平常来说,至少保证查询达到range级别,最好达到ref;
常见的取值说明:
1)NULL:mysql在优化阶段分解查询语句,在执行阶段不需要访问表或索引。比方在所以列中选择最小值,可以单独查找索引来完成,不需要再执行时访问表;
  1. explain select min(id) from mall_order;
复制代码

2)const,system:mysql会对查询的某部分进行优化并将其转化成一个常量(可以通过show warning查看结果)。比方使用primary key或unique key的全部列与常数比较时,由于表中最多匹配到一行记录,所以读取速度回比较快。system是const的特例,表中只有一条元组匹配时为system
  1. set session optimizer_switch='derived_merge=off'; -- 5.7起mysql对衍生表进行了合并优化,此处临时关闭
  2. explain select * from (select * from mall_order where id = 1)t;
复制代码

  1. set session optimizer_switch='derived_merge=off'; -- 5.7起mysql对衍生表进行了合并优化,此处临时关闭
  2. explain select * from (select * from mall_order where id = 1)t;show WARNINGS;
复制代码

3)eq_ref:primary keyunique key索引的全部部分被关联使用,最多只会返回一条符合条件的记录。这种类型可能是除const之外最好的关联类型了,简单的select不会出现这种type;
  1. explain select * from mall_order_item oi left join mall_order mo on mo.id = oi.order_id
复制代码

4)ref:不使用唯一索引,而是使用平常索引大概唯一索引的部分前缀,即索引要和某个值相比较,可能会找到多个符合条件的行;
4.1)简单select查询,name是平常索引(非唯一索引)
  1. explain select * from mall_order where shop_id = 1;
复制代码

4.2)关联表查询
  1. explain select * from mall_order mo left join mall_order_item oi on mo.id = oi.order_id
复制代码

 5)range
   range是范围扫描,通常出现在in、between、>、<、>=等操作中,使用一个索引来检索给定范围的行;
  1. explain select * from mall_order where shop_id >2;
复制代码

6)index
   
  7)ALL
   ALL即全表扫描,扫描聚簇索引的全部叶子节点,通常这种情况需要增长索引来优化;
  1. explain select * from member_address;
复制代码

2.3.5 possible key 

   
   2.3.6 key

   key列显示mysql执行sql过程中实际接纳哪个索引来优化该表访问;
  如果没有使用索引,则该列值为NULL;
  如果想强制mysql使用索引大概忽略possible key列中的索引,可在查询时使用force index或ignore index;
  2.3.7 key_len

   key_len显示了mysql在索引里使用的字节数,通过这个值可以算出具体使用了索引的哪些列;
  key_len的盘算规则:


note:索引最大长度是768字节,当字符串过长时,mysql会做一个雷同左前缀索引的处理,将前半部分的字符提取出来做索引;
2.3.8 ref

   显示在key列记录的索引中,表查所用到的列或常量,常见的有:const(常量)、字段名;
  2.3.9 rows

   mysql预估要读取并检查的行数,留意这个不是结果会合的行数;
  2.3.10 Extra

   展示额外信息
  1)Using Index

   使用覆盖索引,explain执行计划结果里的key有使用索引;
  
  1. explain select id,shop_id from mall_order;
复制代码

2)Using where

   使用where语句来处理结果,而且查询的列没有被索引覆盖;
  1. explain select * from mall_order where order_no = '0000';
复制代码

3)Using index condition

   查询的列不完全被索引覆盖,where条件中是一个前导列的范围; 
  1. explain select * from mall_order where shop_id >20;
复制代码

4)Using temporary

   mysql需要创建一张临时表来处理查询。出现这种情况一样平常是需要要进行优化的,首先想到需要用索引来优化;
  1. explain select distinct order_no from mall_order;
复制代码

5)Using filesort

   使用外部排序而不会使用内存排序;
  
  1. explain select * from mall_order order by order_no;
复制代码
6)Select tables optimized away


    使用聚合(比方min() max())函数访问索引中的某个字段
  1. explain select min(shop_id) from mall_order;
复制代码





免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。




欢迎光临 ToB企服应用市场:ToB评测及商务社交产业平台 (https://dis.qidao123.com/) Powered by Discuz! X3.4