MySQL基础

1.Mysql逻辑架构

在这里插入图片描述

简化为三层结构:

1. 连接层

客户端和服务器端建立连接,客户端发送 SQL 至服务器端;

2. SQL 层(服务层)

对 SQL 语句进行查询处理;与数据库文件的存储方式无关;

1.SQL Interface:SQL接口

接收用户的SQL命令,并且返回用户需要查询的结果。比如SELECT … FROM就是调用SQL Interface

2.Parser: 解析器

在解析器中对 SQL 语句进行语法分析、语义分析。将SQL语句分解成数据结构,并将这个结构 传递到后续步骤,以后SQL语句的传递和处理就是基于这个结构的。如果在分解构成中遇到错 误,那么就说明这个SQL语句是不合理的。

3.Optimizer: 查询优化器

SQL语句在语法解析之后、查询之前会使用查询优化器确定SQL 语句的执行路径,生成一个 执行计划
这个执行计划表明应该 使用哪些索引 进行查询(全表检索还是使用索引检索),表之间的连 接顺序如何,最后会按照执行计划中的步骤调用存储引擎提供的方法来真正的执行查询,并将 查询结果返回给用户。

4.缓存

3. 存储引擎层

与数据库文件打交道,负责数据的存储和读取。

2.SQL执行流程

在这里插入图片描述

1.查询(先查缓存,命中直接返回)

2.解析

3.查询优化

4.执行

SQL 语句在 MySQL 中的流程是: SQL语句→查询缓存→解析器→优化器→执行器 。

在这里插入图片描述3.SQL语句执行顺序

在这里插入图片描述

3.数据库缓冲池

在真正访问页面之前,需要把在磁盘上的页缓存到内存中的 Buffer Pool 之后才可以访问。
show variables like ‘innodb_buffer_pool_size’; 默认128M 最小为5M
show variables like ‘innodb_buffer_pool_instances’; 缓冲池数量 总大小为’128M’,不是每个都占128M
默认为1,也就是1个。最大64个。**而且当innodb_buffer_pool_size(默认128M)的值小于1G的时候设置多个实例是无效的,InnoDB会默认把innodb_buffer_pool_instances的值修改为1。按照官方的说明,最佳的innodb_buffer_pool_instances的数量是,innodb_buffer_pool_size除以innodb_buffer_pool_instances,可以让每个Buffer Pool实例达到1个G,这个公式在8.0和5.7中都适用。**也就是内存分配了8G,则innodb_buffer_pool_instances为8.
最佳大小:在专用数据库服务器中,BufferPool通常可以设置为物理内存的60%,这是比较稳妥的。
每个Buffer Pool实例实际占内存空间 = innodb_buffer_pool_size / innodb_buffer_pool_instances
在这里插入图片描述
在这里插入图片描述
注意:
1.如果这个值大于0 则需要扩大buffer_pool_size
在这里插入图片描述
2.show engine innodb status 如果Free buffers值为0,表示缓存池设置过小
3.show status like ‘innodb_buffer_pool%’;
innodb_buffer_pool_reads:表示InnoDB缓冲池无法满足的请求数。需要从磁盘中读取。
innodb_buffer_pool_read_requests:表示从内存中读取逻辑的请求数。
Innodb_buffer_pool_pages_data: 表示LRU链表中的页的数量,包含young和old两个区域的节点数量
Innodb_buffer_pool_pages_free(Free buffers)表示当前Buffer Pool还有多少空闲缓存页,也就是free链表中还有多少个节点.
Innodb_buffer_pool_pages_total:总页数 每页16K
在这里插入图片描述
4.show engine innodb status;
在这里插入图片描述
Total large memory allocated表示Buffer Pool向操作系统申请的连续内存空间大小,包括全部控制块、缓存页、以及碎片的字节大小
Dictionary memory allocated表示数据字典信息分配的内存空间的字节大小,注意这个内存空间和Buffer Pool没啥关系,不包括在Total memory allocated中
Buffer pool size 表示该Buffer Pool可以容纳多少缓存页,注意,单位是页!
Free buffers表示当前Buffer Pool还有多少空闲缓存页,也就是free链表中还有多少个节点
Database pages表示LRU链表中的页的数量,包含young和old两个区域的节点数量
Old database pages表示LRU链表old区域的节点数量
Modified db pages表示脏页数量,也就是flush链表中节点的数量。
Pending reads表示正在等待从磁盘上加载到Buffer Pool中的页面数量,需要注意的s当准备从磁盘中加载某个页面时,会先为这个页面在Buffer Pool中分配一个缓存页以及它对应的控制块,然后把这个控制块添加到LRU的old区域的头部,但是这个时候真正的磁盘页并没有被加载进来,Pending reads的值会跟着加1。
Pending writes表示即将从LRU、flush链表和单个页面刷新到磁盘中的页面数量
Pages made young表示LRU链表中曾经从old区域移动到young区域头部的节点数量
not young表示在将innodb_old_blocks_time设置的值大于0时,首次访问或者后续访问某个处在old区域的节点时由于不符合时间间隔的限制而不能将其移动到young区域头部时,Page made not young的值会加1。0.00 youngs/s, 0.00 non-youngs/s
youngs/s表示每秒从old区域被移动到young区域头部的节点数量
non-youngs/s表示每秒由于不满足时间限制而不能从old区域移动到young区域头部的节点数量Pages read 7056, created 29120, written 45996
0.00 reads/s, 0.00 creates/s, 0.00 writes/s
表示读取,创建,写入了多少页。后边跟着读取、创建、写入的速率Buffer pool hit rate 1000 / 1000, young-making rate 0 / 1000 not 0 / 1000
Buffer pool hit rate表示在过去某段时间,平均访问1000次页面,有多少次该页面已经被缓存到Buffer Pool了
young-making rate表示在过去某段时间,平均访问1000次页面,有多少次访问使页面移动到young区域的头部了
not (young-making rate)表示在过去某段时间,平均访问1000次页面,有多少次访问没有使页面移动到young区域的头部Pages read ahead 0.00/s, evicted without access 0.00/s, Random read ahead 0.00/s
Pages read ahead表示每秒读入的pages
evicted without access表示每秒读出的pages
Random read ahead表示随机读人的pagesLRU len: 7194, unzip_LRU len: 0
LRU len表示LRU链表中节点的数量I/O sum[5]:cur[0], unzip sum[0]:cur[0]
I/O sum表示最近50s读取磁盘页的总数
I/O cur表示现在正在读取的磁盘页数量
I/O unzip sum表示最近50s解压的页面数量
I/O unzip cur表示正在解压的页面数量

在 MySQL 启动的时候,InnoDB 会为 Buffer Pool 申请一片连续的内存空间,然后按照默认的16KB的大小划分出一个个的页, Buffer Pool 中的页就叫做缓存页。此时这些缓存页都是空闲的,之后随着执行增删改查操作时,才会有磁盘上的数据页被缓存到 Buffer Pool 中
在这里插入图片描述

参考链接:
参考
参考

4.InnoDB和MyISAM存储引擎的区别

InnoDB支持外键和事务,有行锁,缓存索引和数据。

5.索引

索引(Index)是帮助MySQL高效获取数据的数据结构。
优点:降低 数据库的IO成本,减少分组和排序时间,增加查询效率,子查询也会增加效率。
缺点:占磁盘空间,降低更新表的速度,创建索引和维护索引消耗时间。(空间和时间)

1.索引设计原则

1.适合创建索引

1.字段的数值有唯一性的限制
2.频繁作为 WHERE 查询条件的字段
3.经常 GROUP BY 和 ORDER BY 的列
4.UPDATE、DELETE 的 WHERE 条件列
5.DISTINCT 字段需要创建索引
6.多表 JOIN 连接操作时,不要超过3张表,对where条件创建索引,对用于连接的字段创建索引,且在两张表中的类型要一样。
7.字符串前缀索引
8.使用最频繁的列放在联合索引左侧,满足最左前缀原则

2.不适合创建索引

1.数据量小的表
2.大量重复数据的表
3.对经常更新的表不要建立太多索引
4.无序的值(UUID,身份证)最好不要加索引

2.聚簇索引

MySQL聚簇索引数据结构:B+树

在这里插入图片描述

1.聚簇索引概念

存放完整数据的record_type为0,最小最大分别为2和3,存放目录记录为1。目录页只存放目录数据(也就是页数据)和主键。数据页存放完整的数据(包括隐藏信息)。数据和页都是按照主键值进行排序,页内的记录是单向链表,数据页之间是双向链表。

2.数据查找

比如查询主键值为20的数据,先看到第一层目录页,也就是页33,可以锁定30页,因为32页的主键最小值为320。页33中,可以锁定页9,因为页9的主键最小值为12,页20的主键最小值为209,页9中,可直接找到主键为20的数据。

3.聚簇索引优点

1.数据访问更快 ,因为聚簇索引将索引和数据保存在同一个B+树中,因此从聚簇索引中获取数据比非聚簇索引更快
2.聚簇索引对于主键的排序查找和范围查找速度非常快
3.按照聚簇索引排列顺序,查询显示一定范围数据的时候,由于数据都是紧密相连,数据库不用从多个数据块中提取数据,所以节省了大量的io操作 。

4.聚簇索引缺点

1.插入速度严重依赖于插入顺序 ,按照主键的顺序插入是最快的方式,否则将会出现页分裂,严重影响性能。因此,对于InnoDB表,我们一般都会定义一个自增的ID列为主键
2.更新主键的代价很高,因为将会导致被更新的行移动。因此,对于InnoDB表,我们一般定义主键为不可更新
3.二级索引访问需要两次索引查找 ,第一次找到主键值,第二次根据主键值找到行数据

3.非聚簇索引(二级索引)

MySQL非聚簇索引数据结构:B+树

在这里插入图片描述

1.非聚簇索引概念

目录页和聚簇索引一样,存储主键和目录页号,数据页(叶子节点)只存储创建索引的列和主键(按照索引列进行排序,不再是主键)如果想找到完整的数据,需要根据索引列找到主键的值,然后根据主键的值在聚簇索引中继续查找一次,也称为回表(缺点)。

4.联合索引

本质也是非聚簇索引

5.B树和B+树的区别

在这里插入图片描述
1.B+树中有 k 个孩子的节点就有 k 个关键字。也就是孩子数量 = 关键字数,而 B 树中,孩子数量 = 关键字数 +1。(如上图,有8和12两个主键值,子节点有小于8、8-12之间、大于12三个子节点)
2.B+树中非叶子节点的关键字也会同时存在在子节点中,并且是在子节点中所有关键字的最大(或最小)。
3.B+树中非叶子节点仅用于索引,不保存数据记录,跟记录有关的信息都放在叶子节点中。而 B 树中, 非叶子节点既保存索引,也保存数据记录 。
4.B+树所有关键字都在叶子节点出现,叶子节点构成一个有序链表,而且叶子节点本身按照关键字的大
小从小到大顺序链接。

6.总结

由此可以看出,保证数据可以被完整查出,InnoDB必须保证有一个聚簇索引的结构,所以必须要有主键,如果没有显式指定,则MySQL系统会自动选择一个 可以非空且唯一标识数据记录的列作为主键。如果不存在这种列,则MySQL自动为InnoDB表生成一个隐含字段作为主键,这个字段长度为6个字节,类型为长整型。

6.InnoDB数据存储结构

1.页

1.文件头和文件尾
2.页目录和页头
3.用户记录、空闲空间和最大最小记录数

2.行

Compact格式:
1.变长字段长度列表
2.Null值列表
3.记录头信息
4.记录的真实数据(隐藏信息 DB_TRX_ID(事务ID)、DB_ROLL_PTR(回滚指针))

7.数据库设计规范

举例:
这里有两个表:
球员表(player) :球员编号 | 姓名 | 身份证号 | 年龄 | 球队编号
球队表(team) :球队编号 | 主教练 | 球队所在地
超键 :对于球员表来说,超键就是包括球员编号或者身份证号的任意组合,比如(球员编号)(球员编号,姓名)(身份证号,年龄)等。
候选键 :就是最小的超键,对于球员表来说,候选键就是(球员编号)或者(身份证号)。
主键 :我们自己选定,也就是从候选键中选择一个,比如(球员编号)。
外键 :球员表中的球队编号。
主属性 、 非主属性 :在球员表中,主属性是(球员编号)(身份证号),其他的属性(姓名)(年龄)(球队编号)都是非主属性。

第一范式:表的每个属性必须具有原子(单个)值
第二范式:对于非主属性来说,必须完全依赖候选键
第三范式: 每个非键属性依赖于键,依赖于整个键,并且除了键别无他物

反范式化
增加冗余字段提高查询效率
新问题:占用空间变大,改一个表的字段,另一个表冗余字段的值也要同步修改。

8.索引优化和查询优化

1.索引失效的情况

1.全值匹配和覆盖索引

全值匹配:where的条件全是=而且用and连接 建立一个所有条件的索引就是全值匹配
覆盖索引:查询的字段正好符合索引或者多了一个主键。

  • limit查询时可以查询索引字段+主键,保证走索引,提高查询效率。

2.最佳左前缀法则

where条件中要有索引的第一个字段,后边的索引才能用上。
CREATE INDEX idx_age_classid_name ON student(age,classId,NAME);
#这样就用不上索引
EXPLAIN SELECT SQL_NO_CACHE * FROM student WHERE student.classid=1 AND student.name = ‘abcd’;
#这样可以用上三个字段全索引
EXPLAIN SELECT SQL_NO_CACHE * FROM student
WHERE classid=4 AND student.age=30 AND student.name = ‘abcd’;
#这样索引只能用到age,因为classid跳过了,后边name索引是用不到的
EXPLAIN SELECT SQL_NO_CACHE * FROM student
WHERE student.age=30 AND student.name = ‘abcd’;

3.计算、函数、类型转换(自动或手动)导致索引失效。

4.范围条件右边的列索引失效

CREATE INDEX idx_age_classId_name ON student(age,classId,NAME);
#这样只能用到前两个索引
EXPLAIN SELECT SQL_NO_CACHE * FROM student
WHERE student.age=30 AND student.classId>20 AND student.name = ‘abc’ ;
#这样也不行!!!!
EXPLAIN SELECT SQL_NO_CACHE * FROM student
WHERE student.age=30 AND student.name = ‘abc’ AND student.classId>20;
#这样改索引的顺序是可以的 和sql语句and的顺序没关系,优化器可以识别
CREATE INDEX idx_age_name_cid ON student(age,NAME,classId);
#实际开发中 范围查询的应该放在where条件的最后(对于索引来说的)

5.不等于(!= 或者<>)索引失效

6.is null可以使用索引,is not null无法使用索引

优化:
题目:选择公司中有奖金的员工姓名,工资和奖金级别
SELECT salary ,last_name,commission_pct FROM employees WHERE commission_pct IS NOT NULL;
替换为:

SELECT salary ,last_name,commission_pct FROM employees WHERE IFNULL(commission_pct,‘comm’)!=‘comm’;
语法:IFNULL(字段,‘别名’ )!=‘别名’

7.like以通配符%开头索引失效

8.OR 前后存在非索引的列,索引失效

9.字符集不统一可能导致类型转换,导致索引失效

2.查询优化

1.关联查询优化

LEFT JOIN 左边的表一定会全查 所以右边的表一定要建索引。
对于内连接,优化器可以选择谁作为驱动表,只有一个表有索引,会选择这个表作为驱动表;两个表有索引会选择小表作为驱动表
join buffer默认256k 最大4g
#总结:

  • 1.保证被驱动表的JOIN字段已经创建了索引(减少内层循环次数)
  • 2.永远用小结果集驱动大结果集(减少外层循环的次数)
  • 3.增大join buffer size 的大小,(一次缓存的数据越多,内层的扫描次数越少)
  • 4.减少驱动表不必要的字段查询(字段越少,join buffer缓存的数据越多)
  • 5.需要JOIN 的字段,数据类型保持绝对一致。
  • 6.能够直接多表关联的尽量直接关联,不用子查询。(减少查询的趟数)
  • 7.不建议使用子查询,建议将子查询SQL拆开结合程序多次查询,或使用 JOIN 来代替子查询。

2.子查询优化

子查询时,mysql会为内层查询建立一个临时表,这个临时表无法使用索引,所以尽量不用子查询改用join代替。
#结论:尽量不要使用NOT IN 或者 NOT EXISTS,用LEFT JOIN xxx ON xx WHERE xx IS NULL替代

3.排序优化

  • 1.在 WHERE 子句中使用索引避免全表扫描 ,在 ORDER BY 子句中使用索引避免使用 FileSort 排序 。
  • 2.尽量使用 Index 完成 ORDER BY 排序。如果 WHERE 和 ORDER BY 后面是相同的列就使用单索引列;如果不同就使用联合索引。
  • 3.无法使用 Index 时,需要对 FileSort 方式进行调优。
  • 4.order by 时select*并且没有limit限制,索引会失效,因为需要全部回表查询,就不会走索引了。使用覆盖索引(查询的字段都有索引)不用limit限制也会走索引,因为不需要回表了。
  • 5.order by时顺序错误,索引会失效(也要满足最左前缀法则)。
  • 6.order by时规则不一致, 索引失效 (顺序错(不满足最左前缀),不索引;方向反(有升有降),不索引)。
  • 7.EXPLAIN SELECT * FROM student WHERE classid=45 ORDER BY age; 当前索引是index_age_classid_name, 这样where条件是用不到索引的,不满足最左前缀法则,order by虽然满足最左前缀,但是没有limit限制,也用不到索引,所以这条语句走全表扫描。需要给classid单独建立二级索引,保证where条件可以使用索引。而且当where条件过滤完数据剩余不多的话(1-2w条),就不会用order by字段的索引了。

4.优化filesort策略

  • 1.尝试提高 sort_buffer_size 2. 尝试提高 max_length_for_sort_data 3. Order by 时select * 是一个大忌。最好只Query需要的字段。

5.索引条件下推

索引条件下推 (ICP)默认是启用的 主要作用是减少回表的次数
#索引下推 key1大于z之后先不回表,先执行and后边的条件继续过滤。减少了回表的次数
EXPLAIN SELECT * FROM s1 WHERE key1 > ‘z’ AND key1 LIKE ‘%a’;

6.EXISTS和IN的区别

#原则是小表驱动大表
#SELECT * FROM A WHERE cc IN (select cc FROM B)
#SELECT * FROM A EXISTS (SELECT cc FROM B WHERE B.cc=A.cc)
#当A小于B时,用EXISTS 因为EXISTS 相当于外表循环 就是先循环A
#当B小于A时 用IN 因为IN相当于内表循环 就是先循环B
#那个表小就用哪个表来驱动,A表小就用EXISTS B表小就用IN

#COUNT(具体字段) 最好用二级索引 因为聚簇索引存储的信息比较多,此处只需要统计行数
#不要使用select *
#mysql在查询时会通过数据字典将’*‘按照顺序转换成所有列名,会大大耗费资源和时间
#无法使用覆盖索引

9.调优的维度和步骤

1.选择合适的DBMS

2.优化表设计

3.优化逻辑查询

4.优化物理查询(索引)

5.使用redis作为缓存

6.数据库及优化(读写分离和数据分片)

优化MYSQL服务器
硬件:增加内存、磁盘加速、多处理器
MySQL参数:
Innodb_buffer_pool_size mysql最重要的参数之一,表示InnoDB类型的 表 和索引的最大缓存 。它不仅仅缓存索引数据 ,还会缓存表的数据 。这个值越大,查询的速度就会越
快。但是这个值太大会影响操作系统的性能。默认值128M
垂直拆分和水平拆分
水平拆分:行级别的
垂直拆分:表级别的

10.性能分析工具使用

1.查看系统性能参数

SHOW [GLOBAL|SESSION] STATUS LIKE ‘参数’;
一些常用的性能参数如下: • Connections:连接MySQL服务器的次数。• Uptime:MySQL服务器的上线时间。• Slow_queries:慢查询的次数。• Innodb_rows_read:Select查询返回的行数• Innodb_rows_inserted:执行INSERT操作插入的行数 • Innodb_rows_updated:执行UPDATE操作更新的行数 • Innodb_rows_deleted:执行DELETE操作删除的行数 • Com_select:查询操作的次数。 • Com_insert:插入操作的次数。对于批量插入的 INSERT 操作,只累加一次。 • Com_update:更新操作的次数。 • Com_delete:删除操作的次数。

2.统计SQL的查询成本:last_query_cost

在这里插入图片描述
你能看到页的数量是刚才的 20 倍,但是查询的效率并没有明显的变化,实际上这两个 SQL 查询的时间基本上一样,就是因为采用了顺序读取的方式将页面一次性加载到缓冲池中,然后再进行查找。虽然页数量(last_query_cost)增加了不少 ,但是通过缓冲池的机制,并 没有增加多少查询时间 。
使用场景:它对于比较开销是非常有用的,特别是我们有好几种查询方式可选的时候。

3.慢查询日志(默认关闭状态)

set global slow_query_log=‘ON’;
在这里插入图片描述
阈值时间默认10s
在这里插入图片描述
改成1s
在这里插入图片描述
查看有多少条慢查询记录:SHOW GLOBAL STATUS LIKE ‘%Slow_queries%’;
在这里插入图片描述
我们想要按照查询时间排序,查看前五条 SQL 语句,这样写即可:
mysqldumpslow -s t -t 5 /var/lib/mysql/atguigu01-slow.log
在这里插入图片描述

4.查看 SQL 执行成本:SHOW PROFILE 默认是OFF

开启:set profiling = ‘ON’;
在这里插入图片描述
查看最近一次查询的开销:show profile;
show profile cpu,block io for query 2;
在这里插入图片描述
show profile的常用查询参数:

  • 1.ALL:显示所有的开销信息。
  • 2.BLOCK IO:显示块IO开销。
  • 3.CONTEXT SWITCHES:上下文切换开销。
  • 4.CPU:显示CPU开销信息。
  • 5.IPC:显示发送和接收开销信息。
  • 6.MEMORY:显示内存开销信息。
  • 7.PAGE FAULTS:显示页面错误开销信息。
  • 8.SOURCE:显示和Source_function,Source_file, Source_line相关的开销信息。
  • 9.SWAPS:显示交换次数开销信息。

11.查看执行计划:EXPLAIN

在这里插入图片描述

1.id

id 相同,执行顺序由上至下
id 不同,如果是子查询,id 号会递增,id 值越大优先级越高,越先被执行
关注点:id号每个号码,表示一趟独立的查询, 一个sql的查询趟数越少越好

2.Table

查询的每一行记录都对应着一个单表

3.select_type

SIMPLE:查询语句中不包含UNION或者子查询的查询都算作是SIMPLE类型
PRIMARY:对于包含UNION或者UNION ALL或者子查询的大查询来说,它是由几个小查询组成的,其中最左边的那个查询的select_type值就是PRIMARY,(外层的查询)
SUBQUERY:如果包含子查询的查询语句不能够转为对应的semi-join的形式,并且该子查询是不相关子查询。该子查询的第一个SELECT关键字代表的那个查询的select_type就是SUBQUERY
DERIVED:临时表的select_type

4. type

针对单表的访问方法

1)最高级 system 只有一条记录 且存储引擎为 myisam 时 会出现
2)主键或者唯一二级索引列与常数进行等值匹配时 const
3)普通二级索引时 ref
4)连接查询时,如果被驱动表是通过主键或者唯一二级索引列等值匹配的方式进行访问
的,eq_ref
5)如果使用索引获取某些范围区间的记录,那么就可能使用到range访问方法
6)当我们可以使用索引覆盖,但需要扫描全部的索引记录时,该表的访问方法就是indexEXPLAIN SELECT key_part2 FROM s1 WHERE key_part3 = ‘a’;(索引为 key_part1-2-3)
结论:
结 果 值 从 最 好 到 最 坏 依 次 是 : system > const > eq_ref > ref > fulltext > ref_or_null >
index_merge > unique_subquery > index_subquery > range > index > ALL 其中比较重要的几个
提取出来(见上图中的蓝色)。SQL 性能优化的目标:至少要达到 range 级别,要求是 ref
级别,最好是 consts 级别。(阿里巴巴开发手册要求)

5. possible_keys 和 key

可能用到的索引 和 实际上使用的索引

6. key_len

实际使用到的索引长度(即:字节数)

帮你检查是否充分的利用上了索引,值越大越好,主要针对于联合索引,有一定的参考意
义。
主键 int 型 索引长度 4 字节
EXPLAIN SELECT * FROM s1 WHERE id = 10005;
Key2 int 型 唯一约束 可能为空 索引长度 5 个字节
EXPLAIN SELECT * FROM s1 WHERE key2 = 10126;
Key1 varchar 长度 100 索引长度 300+null(1 字节)+长度(2 字节)=303 字节
EXPLAIN SELECT * FROM s1 WHERE key1 = ‘a’;
303 字节
EXPLAIN SELECT * FROM s1 WHERE key_part1 = ‘a’;
606 字节
EXPLAIN SELECT * FROM s1 WHERE key_part1 = ‘a’ AND key_part2 = ‘b’;
909 字节
EXPLAIN SELECT * FROM s1 WHERE key_part1 = ‘a’ AND key_part2 = ‘b’ AND key_part3 = ‘c’;
用不上索引
EXPLAIN SELECT * FROM s1 WHERE key_part3 = ‘a’;

7. ref

当使用索引列等值查询时,与索引列进行等值匹配的对象信息。

#比如只是一个常数或者是某个列。
Ref=Const
EXPLAIN SELECT * FROM s1 WHERE key1 = ‘a’;
Id
EXPLAIN SELECT * FROM s1 INNER JOIN s2 ON s1.id = s2.id;
Func(函数)
EXPLAIN SELECT * FROM s1 INNER JOIN s2 ON s2.key1 = UPPER(s1.key1);

8. rows

预估的需要读取的记录条数

值越小越好

9. filtered:

某个表经过搜索条件过滤后剩余记录条数的百分比

对于单表查询来说,这个 filtered 列的值没什么意义,我们更关注在连接查询中驱动表对应的执行计划记录的 filtered 值,它决定了被驱动表要执行的次数(即:rows * filtered)

10. Extra:一些额外的信息

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值