第一句子大全,网罗天下好句子,好文章尽在本站!

好文推荐:Mysql基础复习

时间:2013-05-31

2 服务层:提供核心的服务功能,如果sql接口,完成缓存的查询,sql的分析和优化部分及内置函数的执行 所有跨存储引擎的功能都在这一层实现 服务器会解析查

友情提示:本文共有 9186 个字,阅读大概需要 19 分钟。

mysql基础

mysql逻辑架构

1.连接层:与客户端进行连接的服务,主要完成一些类似连接处理,授权认证 及相关的安全方案. 在该层上引入了连接池的概念。 2.服务层:提供核心的服务功能,如果sql接口,完成缓存的查询,sql的分析和优化部分及内置函数的执行.所有跨存储引擎的功能都在这一层实现.服务器会解析查询并创建相应的内部 解析 权,并对其完成相应的 优化 ,生成相应的 执行 操作,服务器还会查询内部的缓存,如果缓存空间足够大,这样可以解决大量读操作的环境中,能够很好的提升系统性能 3.引擎层:存储引擎是真正 负责MYSQL中数据的存储和提取 ,服务器通过API与存储引擎进行通信,不同的存储引擎提供的功能不同,可以根据自己的实际需求来进行选取 4.存储层:主要是将数据存储在运行的计算机文件系统之上,并完成与存储引擎的交互。

架构图

查看存储引擎

show engines;

查看当前使用的存储引擎:

show variables like "%storage_engine%";

MyISAM和InnoDB区别

1、InnoDB 支持事务,MyISAM 不支持事务。这是 MySQL 将默认存储引擎从 MyISAM 变成 InnoDB 的重要原因之一;

2、 InnoDB 支持外键,而 MyISAM 不支持。对一个包含外键的 InnoDB 表转为 MYISAM 会失败;

3、InnoDB 是聚集索引,MyISAM 是非聚集索引。聚簇索引的文件存放在主键索引的叶子节点上,因此 InnoDB 必须要有主键,通过主键索引效率很高。但是辅助索引需要两次查询,先查询到主键,然后再通过主键查询到数据。因此,主键不应该过大,因为主键太大,其他索引也都会很大。而 MyISAM 是非聚集索引,数据文件是分离的,索引保存的是数据文件的指针。主键索引和辅助索引是独立的。

4、 InnoDB 不保存表的具体行数,执行 select count(*) from table 时需要全表扫描。而MyISAM 用一个变量保存了整个表的行数,执行上述语句时只需要读出该变量即可,速度很快;

5、InnoDB 最小的锁粒度是行锁,MyISAM 最小的锁粒度是表锁。一个更新语句会锁住整张表,导致其他查询和更新都会被阻塞,因此并发访问受限。这也是 MySQL 将默认存储引擎从 MyISAM 变成 InnoDB 的重要原因之一;

注意:目前 MySQL 将默认存储引擎 InnoDB,支持事务,支持行锁支持外键

事务的基本要素(ACID)

1、原子性(Atomicity):事务开始后所有操作,要么全部做完,要么全部不做,不可能停滞在中间环节。事务执行过程中出错,会回滚到事务开始前的状态,所有的操作就像没有发生一样。也就是说事务是一个不可分割的整体,就像化学中学过的原子,是物质构成的基本单位。 2、一致性(Consistency):事务开始前和结束后,数据库的完整性约束没有被破坏 。比如A向B转账,不可能A扣了钱,B却没收到。 3、隔离性(Isolation):同一时间,只允许一个事务请求同一数据,不同的事务之间彼此没有任何干扰。比如A正在从一张银行卡中取钱,在A取钱的过程结束前,B不能向这张卡转账。 4、持久性(Durability):事务完成后,事务对数据库的所有更新将被保存到数据库,不能回滚。

事务的并发问题

1、脏读:事务A读取了事务B更新的数据,然后B回滚操作,那么A读取到的数据是脏数据

2、不可重复读:事务 A 多次读取同一数据,事务 B 在事务A多次读取的过程中,对数据作了更新并提交,导致事务A多次读取同一数据时,结果 不一致。

3、幻读:系统管理员A将数据库中所有学生的成绩从具体分数改为ABCDE等级,但是系统管理员B就在这个时候插入了一条具体分数的记录,当系统管理员A改结束后发现还有一条记录没有改过来,就好像发生了幻觉一样,这就叫幻读。

小结:不可重复读的和幻读很容易混淆,不可重复读侧重于修改,幻读侧重于新增或删除。解决不可重复读的问题只需锁住满足条件的行,解决幻读需要锁表

事务隔离级别

mysql默认的事务隔离级别为repeatable-read

MVCC

什么是mvcc

MVCC(Multi-Version Concurrency Control)多版本并发控制,是用来在数据库中控制并发的方法,实现对数据库的并发访问用的。在MySQL中,MVCC只在读取已提交(Read Committed RC)和可重复读(Repeatable Read RR)两个事务级别下有效。其是通过Undo日志中的版本链和ReadView一致性视图来实现的。MVCC就是在多个事务同时存在时,SELECT语句找寻到具体是版本链上的哪个版本,然后在找到的版本上返回其中所记录的数据的过程。

概念补充

首先需要知道的是,在MySQL中,会默认为我们的表后面添加三个隐藏字段:

DB_ROW_ID:行ID,MySQL的B+树索引特性要求每个表必须要有一个主键。如果没有设置的话,会自动寻找第一个不包含NULL的唯一索引列作为主键。如果还是找不到,就会在这个DB_ROW_ID上自动生成一个唯一值,以此来当作主键(该列和MVCC的关系不大);

DB_TRX_ID:事务ID,记录的是当前事务在做INSERT或UPDATE语句操作时的事务ID(DELETE语句被当做是UPDATE语句的特殊情况,后面会进行说明);

DB_ROLL_PTR:回滚指针,通过它可以将不同的版本串联起来,形成版本链。相当于链表的next指针。

ReadView

ReadView一致性视图主要是由两部分组成:所有未提交事务的ID数组和已经创建的最大事务ID组成(实际上ReadView还有其他的字段,但不影响这里对MVCC的讲解)。比如:[100,200],300。事务100和200是当前未提交的事务,而事务300是当前创建的最大事务(已经提交了)。当执行SELECT语句的时候会创建ReadView,但是在读取已提交和可重复读两个事务级别下,生成ReadView的策略是不一样的:读取已提交级别是每执行一次SELECT语句就会重新生成一份ReadView(当前读),而可重复读级别是只会在第一次SELECT语句执行的时候会生成一份(快照读),后续的SELECT语句会沿用之前生成的ReadView(即使后面有更新语句的话,也会继续沿用)。

版本链

所有版本的数据都只会存一份,然后通过回滚指针连接起来,之后就是通过一定的规则找到具体是哪个版本上的数据就行了。假设现在有一张account表,其中有id和name两个字段,那么版本链的示意图如下:

(其中min_id指向ReadView中未提交事务数组中的最小事务ID,而max_id指向ReadView中的已经创建的最大事务ID)

如果落在绿色区间(DB_TRX_ID < min_id):这个版本比min_id还小(事务ID是从小往大顺序生成的),说明这个版本在SELECT之前就已经提交了,所以这个数据是可见的。或者(这里是短路或,前面条件不满足才会判断后面这个条件)这个版本的事务本身就是当前SELECT语句所在事务的话,也是一样可见的;

如果落在红色区间(DB_TRX_ID > max_id):表示这个版本是由将来启动的事务来生成的,当前还未开始,那么是不可见的; 如果落在黄色区间(min_id <= DB_TRX_ID <= max_id):这个时候就需要再判断两种情况: 如果这个版本的事务ID在ReadView的未提交事务数组中,表示这个版本是由还未提交的事务生成的,那么就是不可见的;

如果这个版本的事务ID不在ReadView的未提交事务数组中,表示这个版本是已经提交了的事务生成的,那么是可见的。

如果在上述的判断中发现当前版本是不可见的,那么就继续从版本链中通过回滚指针拿取下一个版本来进行上述的判断。

sql的执行顺序

from, on ,join, where, group by, having, select distinct, order by ,limit

mysql中的on和where的区别

1.on是在生成临时表的时候使用的条件,不管是否为真,返回驱动表的所有数据。 2.where则是在生成临时表之后使用的条件,此时已经不管是否使用了left join了,只要条件不为真的行,全部过滤掉。

UNION和UNION ALL

在数据库中,UNION和UNION ALL关键字都是将两个结果集合并为一个,但这两者从使用和效率上来说都有所不同。

MySQL中的UNION

UNION在进行表链接后会筛选掉重复的记录,所以在表链接后会对所产生的结果集进行排序运算,删除重复的记录再返回结果。实际大部分应用中是不会产生重复的记录,最常见的是过程表与历史表UNION。如:

select * from gc_dfys union select * from ls_jg_dfys

这个SQL在运行时先取出两个表的结果,再用排序空间进行排序删除重复的记录,最后返回结果集,如果表数据量大的话可能会导致用磁盘进行排序。

MySQL中的UNION ALL

而UNION ALL只是简单的将两个结果合并后就返回。这样,如果返回的两个结果集中有重复的数据,那么返回的结果集就会包含重复的数据了。

从效率上说,UNION ALL 要比UNION快很多,所以,如果可以确认合并的两个结果集中不包含重复的数据的话,那么就使用UNION ALL,如下:

select * from gc_dfys union all select * from ls_jg_dfys

使用Union,则所有返回的行都是唯一的,如同您已经对整个结果集合使用了DISTINCT 使用Union all,则不会排重,返回所有的行

如果您想使用ORDER BY或LIMIT子句来对全部UNION结果进行分类或限制,则应对单个地SELECT语句加圆括号,并把ORDER BY或LIMIT放到最后一个的后面: (SELECT a FROM tbl_name WHERE a=10 AND B=1) UNION (SELECT a FROM tbl_name WHERE a=11 AND B=2) ORDER BY a LIMIT 10; 麻烦一点也可以这么干: select userid from ( select userid from testa union all select userid from testb) t order by userid limit 0,1;

如果你还想group by,而且还有条件,那么: select userid from (select userid from testa union all select userid from testb) t group by userid having count(userid) = 2;

注意:在union的括号后面必须有个别名,否则会报错

当然了,如果当union的几个表的数据量很大时,建议还是采用先导出文本,然后用脚本来执行 因为纯粹用sql,效率会比较低,而且它会写临时文件,如果你的磁盘空间不够大,就有可能会出错 Error writing file "/tmp/MYLsivgK" (Errcode: 28)

JOIN

创建表 DROP TABLE IF EXISTS department; CREATE TABLE ( id int(11) NOT NULL AUTO_INCREMENT, deptName varchar(30) DEFAULT NULL, address varchar(40) DEFAULT NULL, PRIMARY KEY () ) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8;

INSERT INTO VALUES ("1", "研发部(RD)", "2层"); INSERT INTO VALUES ("2", "人事部(HR)", "3层"); INSERT INTO VALUES ("3", "市场部(MK)", "4层"); INSERT INTO VALUES ("4", "后勤部(MIS)", "5层"); INSERT INTO VALUES ("5", "财务部(FD)", "6层");

DROP TABLE IF EXISTS employee; CREATE TABLE ( name varchar(20) DEFAULT NULL, dep_id int(11) DEFAULT NULL, age salary decimal(10,2) DEFAULT NULL, cus_id ) ) ENGINE=InnoDB AUTO_INCREMENT=109 DEFAULT CHARSET=utf8;

INSERT INTO VALUES ("1", "鲁班", "1", "10", "1000.00", "1"); INSERT INTO VALUES ("2", "后裔", "1", "20", "2000.00", "1"); INSERT INTO VALUES ("3", "孙尚香", "1", "20", "2500.00", "1"); INSERT INTO VALUES ("4", "凯", "4", "20", "3000.00", "1"); INSERT INTO VALUES ("5", "典韦", "4", "40", "3500.00", "2"); INSERT INTO VALUES ("6", "貂蝉", "6", "20", "5000.00", "1"); INSERT INTO VALUES ("7", "孙膑", "6", "50", "5000.00", "1"); INSERT INTO VALUES ("8", "蔡文姬", "30", "35", "4000.00", "1");

内连接

查询两张表的共有部分

语法 Select from tableA A Inner join tableB B on A.Key = B.Key 举例 SELECT * from employee e INNER JOIN department d on e.depart_id = d.id;

左连接

把左边表的内容全部查出,右边表只查出满足条件的记录

语法 Select from tableA A Left Join tableB B on A.Key = B.Key 举例 SELECT * from employee e LEFT JOIN department d on e.depart_id = d.id;

右连接

把右边表的内容全部查出,左边表只查出满足条件的记录

语法 Select from tableA A RIGHT JON tableB B on A.Key = B.Key 举例 SELECT * from employee e RIGHT JOIN department d on e.depart_id = d.id;

左表独有

查询A的独有数据

Select from tableA A Left Join tableB B on A.Key = B.Key where B.key IS NULL 举例 SELECT * from employee e LEFT JOIN department d on e.depart_id = d.id WHERE d.id IS NULL;

右表独有

查询B的独有数据

Select from tableA A Right Join tableB B on A.Key = B.Key where A.key IS NULL 举例 SELECT * from employee e RIGHT JOIN department d on e.depart_id = d.id WHERE e.id IS NULL;

全连接

查询两个表的全部信息

Select from tableA A Full Outter Join tableB B on A.Key = B.Key 注意 :注:Mysql 默认不支持此种写法 Oracle支持 SELECT * from employee e LEFT JOIN department d on e.depart_id = d.id UNION SELECT * from employee e RIGHT JOIN department d on e.depart_id = d.id

查询左右表各自的独有的数据

查询A和B各自的独有的数据

Select from tableA A Full Outter Join tableB B on A.Key = B.Key where A.key = null or B.key=null

SELECT * from employee e LEFT JOIN department d on e.depart_id = d.id WHERE d.id is NULL UNION SELECT * from employee e RIGHT JOIN department d on e.depart_id = d.id WHERE e.depart_id is NULL

[MySQL三大范式]

第一范式(1NF)

数据表的每一列都要保持它的原子特性,也就是列不能再被分割。

第二范式(2NF)

属性必须完全依赖于主键。

第三范式(3NF)

所有的非主属性不依赖于其他的非主属性 数据库表中每一列数据都和主键直接相关,不能间接相关。

数据类型的优化

1.更小的通常更好 应该尽量使用可以正确存储数据的最小数据类型,更小的数据类型通常更快,因为它们占用更少的磁盘、内存和CPU缓存,并且处理时需要的CPU周期更少,但是要确保没有低估需要存储的值的范围,如果无法确认哪个数据类型,就选择你认为不会超过范围的最小类型

案例:设计两张表,设计不同的数据类型,查看表的容量

2.简单就好 简单数据类型的操作通常需要更少的CPU周期,例如,

1、整型比字符操作代价更低,因为字符集和校对规则是字符比较比整型比较更复杂,2、使用mysql自建类型而不是字符串来存储日期和时间3、用整型存储IP地址 案例:创建两张相同的表,改变日期的数据类型,查看SQL语句执行的速度

3.尽量避免null 如果查询中包含可为NULL的列,对mysql来说很难优化,因为可为null的列使得索引、索引统计和值比较都更加复杂,坦白来说,通常情况下null的列改为not null带来的性能提升比较小,所有没有必要将所有的表的schema进行修改,但是应该尽量避免设计成可为null的列

数据类型的实际优化细节

1.整数类型

可以使用的几种整数类型:TINYINT,SMALLINT, MEDIUMINT,INT,BIGINT分别使用8,16,24,32,64位存储空间。

尽量使用满足需求的最小数据类型 2.字符和字符串类型

1、char长度固定,即每条数据占用等长字节空间;最大长度是255个字符,适合用在身份证号、手机号等定长字符串2、varchar可变程度,可以设置最大长度;最大空间是65535个字节,适合用在长度可变的属性3、text不设置长度,当不知道属性的最大长度时,适合用text

按照查询速度:char>varchar>text 3.BLOB和TEXT类型

MySQL 把每个 BLOB 和 TEXT 值当作一个独立的对象处理。

两者都是为了存储很大数据而设计的字符串类型,分别采用二进制和字符方式存储。 4.date,datetime和timestamp

datetime 占用8个字节 与时区无关,数据库底层时区配置,对datetime无效 可保存到毫秒 可保存时间范围大 不要使用字符串存储日期类型,占用空间大,损失日期类型函数的便捷性timestamp 占用4个字节 时间范围:1970-01-01到2038-01-19 精确到秒 采用整形存储 依赖数据库设置的时区 自动更新timestamp列的值date 占用的字节数比使用字符串、datetime、int存储要少,使用date类型只需要3个字节 使用date类型还可以利用日期时间函数进行日期之间的计算 date类型用于保存1000-01-01到9999-12-31之间的日期

5.使用枚举代替字符串类型

有时可以使用枚举类代替常用的字符串类型,mysql存储枚举类型会非常紧凑,会根据列表值的数据压缩到一个或两个字节中,mysql在内部会将每个值在列表中的位置保存为整数,并且在表的.frm文件中保存“数字-字符串”映射关系的查找表 create table enum_test(e enum("fish","apple","dog") not null);insert into enum_test(e) values("fish"),("dog"),("apple");select e+0 from enum_test;

6.特殊类型数据

人们经常使用varchar(15)来存储ip地址,然而,它的本质是32位无符号整数不是字符串,可以使用INET_ATON()和INET_NTOA函数在这两种表示方法之间转换案例: select inet_aton("1.1.1.1") select inet_ntoa(16843009)

show processlist

使用show processlist查看连接的线程个数,来观察是否有大量线程处于不正常的状态或者其他不正常的特征(和navcat中的服务请监控对应)

1.id表示session id 2.user表示操作的用户 3.host表示操作的主机 4.db表示操作的数据库 5.command表示当前状态

sleep:线程正在等待客户端发送新的请求query:线程正在执行查询或正在将结果发送给客户端locked:在mysql的服务层,该线程正在等待表锁analyzing and statistics:线程正在收集存储引擎的统计信息,并生成查询的执行计划Copying to tmp table:线程正在执行查询,并且将其结果集都复制到一个临时表中sorting result:线程正在对结果集进行排序sending data:线程可能在多个状态之间传送数据,或者在生成结果集或者向客户端返回数据

6.info表示详细的sql语句 7.time表示相应命令执行时间 8.state表示命令执行状态

mysql数据结构选择

B+树添加和删除数据图解

红黑树知识补充

索引

索引基本知识

索引优点

1、大大减少了服务器需要扫描的数据量2、帮助服务器避免排序和临时表3、将随机io变成顺序io

索引的用处

1、快速查找匹配WHERE子句的行2、从consideration中消除行,如果可以在多个索引之间进行选择,mysql通常会使用找到最少行的索引3、如果表具有多列索引,则优化器可以使用索引的任何最左前缀来查找行4、当有表连接的时候,从其他表检索行数据5、查找特定索引列的min或max值6、如果排序或分组时在可用索引的最左前缀上完成的,则对表进行排序和分组7、在某些情况下,可以优化查询以检索值而无需查询数据行

索引的分类

1.主键索引2.唯一索引3.普通索引4.全文索引5.组合索引

技术名词解释

回表

捕获1.PNG

我们对id建立索引,然后再对name建立索引。那么当我们执行select * from student where name=?时,由于索引底层数据结构的B+Tree,对name列建立的索引叫做二级索引或者副主索引(普通索引),这个索引的数据存储的是id(或者唯一列、或者是6字节的row id),那么我们执行完SQL时,会从name的B+Tree中拿到id,再回到id的B+Tree中去搜索所对应的数据,这个过程就叫做回表

索引覆盖

例如 select id ,name from student where name=? 如果一个索引包含(或覆盖)所有需要查询的字段的值,称为‘覆盖索引’。即只需扫描索引而无须回表

最左匹配原则

一帮情况下和组合索引一起使用,例如吧name,age共同建立索引(name,age),假设现在有下面四条sql语句

select * from student where name=? and age=?

select * from student where name=?

select * from student where age=?

select * from student where age=? and name=?

现在问题来了,那个会走组合索引(name,age)? 答案是1,2,4,而3会进行全表扫描,看下图

听名知意,就是最左边开始匹配呗,也就是先匹配name,再来age。虽然2只有name,但是也会走索引。 你可能的疑惑就是4为啥会走索引,其实mysql中有个叫做优化器的东西,他会对这个age和name的顺序进行优化。这样就可以走索引了 而语句3没有按照匹配到name时候就不能使用索引 优化器简单的说一下,有两种:CBO(基于成本的优化),RBO(基于规则的优化)MySQL默认用的是CBO。

索引下推

例如 select * from student where name="张三" and age=14 首先:

数据是存储在磁盘的、MySQL有自己的服务,MySQL服务要跟磁盘发生交互。这样能从磁盘拿到数据

没有索引下推时:

存储引擎先从磁盘中筛选出name符合条件的数据,全部取出,MySQL server再根据age条件筛选一次。这样就得到了符合条件的值。

这样会有大量的IO操作,所以浪费时间和资源

有存索引下推时

存储引擎先从磁盘中直接筛选出name,age同时都符合条件的数据,不需要server再去做任何的数据筛选

索引下推需要在磁盘上进行数据筛选,原来的筛选是在内存中进行,现在放到了磁盘上进行查找数据的环节,但是,虽然这样看起来成本更高了,可别忘了,索引数据是排序的,所有数据是聚集存放的没所以性能并不会有影响,而且还会减少IO次数,反而会提升性能

哈希索引

基于哈希表的实现,只有精确匹配索引所有列的查询才有效 在mysql中,只有memory的存储引擎显式支持哈希索引 哈希索引自身只需存储对应的hash值,所以索引的结构十分紧凑,这让哈希索引查找的速度非常快

哈希索引的限制

1、哈希索引只包含哈希值和行指针,而不存储字段值,索引不能使用索引中的值来避免读取行 2、哈希索引数据并不是按照索引值顺序存储的,所以无法进行排序 3、哈希索引不支持部分列匹配查找,哈希索引是使用索引列的全部内容来计算哈希值 4、哈希索引支持等值比较查询,也不支持任何范围查询 5、访问哈希索引的数据非常快,除非有很多哈希冲突,当出现哈希冲突的时候,存储引擎必须遍历链表中的所有行指针,逐行进行比较,直到找到所有符合条件的行 6、哈希冲突比较多的话,维护的代价也会很高

组合索引

创建索引a、b、c

不同SQL语句使用索引情况.png

出现范围查找右侧索引失效, 而"%sss%" 只有%之前的索引有效

聚簇索引与非聚簇索引

1.聚簇索引 不是单独的索引类型,而是一种数据存储方式,指的是数据行跟相邻的键值紧凑的存储在一起

优点1、可以把相关数据保存在一起2、数据访问更快,因为索引和数据保存在同一个树中3、使用覆盖索引扫描的查询可以直接使用页节点中的主键值缺点1、聚簇数据最大限度地提高了IO密集型应用的性能,如果数据全部在内存,那么聚簇索引就没有什么优势2、插入速度严重依赖于插入顺序,按照主键的顺序插入是最快的方式3、更新聚簇索引列的代价很高,因为会强制将每个被更新的行移动到新的位置4、基于聚簇索引的表在插入新行,或者主键被更新导致需要移动行的时候,可能面临页分裂的问题5、聚簇索引可能导致全表扫描变慢,尤其是行比较稀疏,或者由于页分裂导致数据存储不连续的时候

2.非聚簇索引 数据文件跟索引文件分开存放

执行计划

在企业的应用场景中,为了知道优化SQL语句的执行,需要查看SQL语句的具体执行过程,以加快SQL语句的执行效率。

可以使用explain+SQL语句来模拟优化器执行SQL查询语句,从而知道mysql是如何处理sql语句的。

1、执行计划中包含的信息

id

select查询的序列号,包含一组数字,表示查询中执行select子句或者操作表的顺序

id号分为三种情况:

1、如果id相同,那么执行顺序从上到下

select查询的序列号,包含一组数字,表示查询中执行select子句或者操作表的顺序

id号分为三种情况: (1)、如果id相同,那么执行顺序从上到下

explain select * from emp e join dept d on e.deptno = d.deptno join salgrade sg on e.sal between sg.losal and sg.hisal;

(2)、如果id不同,如果是子查询,id的序号会递增,id值越大优先级越高,越先被执行

explain select * from emp e where e.deptno in (select d.deptno from dept d where d.dname = "SALES");

(3)、id相同和不同的,同时存在:相同的可以认为是一组,从上往下顺序执行,在所有组中,id值越大,优先级越高,越先执行

explain select * from emp e join dept d on e.deptno = d.deptno join salgrade sg on e.sal between sg.losal and sg.hisal where e.deptno in (select d.deptno from dept d where d.dname = "SALES");

select_type

主要用来分辨查询的类型,是普通查询还是联合查询还是子查询

table

对应行正在访问哪一个表,表名或者别名,可能是临时表或者union合并结果集 1、如果是具体的表名,则表明从实际的物理表中获取数据,当然也可以是表的别名

2、表名是derivedN的形式,表示使用了id为N的查询产生的衍生表

3、当有union result的时候,表名是union n1,n2等的形式,n1,n2表示参与union的id

type

type显示的是访问类型,访问类型表示我是以何种方式去访问我们的数据,最容易想的是全表扫描,直接暴力的遍历一张表去寻找需要的数据,效率非常低下,访问的类型有很多,效率从最好到最坏依次是:

system > const > eq_ref > ref > fulltext > ref_or_null > index_merge > unique_subquery > index_subquery > range > index > ALL

一般情况下,得保证查询至少达到range级别,最好能达到ref

possible_keys

显示可能应用在这张表中的索引,一个或多个,查询涉及到的字段上若存在索引,则该索引将被列出,但不一定被查询实际使用

explain select * from emp,dept where emp.deptno = dept.deptno and emp.deptno = 10;

key

实际使用的索引,如果为null,则没有使用索引,查询中若使用了覆盖索引,则该索引和查询的select字段重叠。

key_len

表示索引中使用的字节数,可以通过key_len计算查询中使用的索引长度,在不损失精度的情况下长度越短越好。

ref

显示索引的哪一列被使用了,如果可能的话,是一个常数

rows

根据表的统计信息及索引使用情况,大致估算出找出所需记录需要读取的行数,此参数很重要,直接反应的sql找了多少数据,在完成目的的情况下越少越好

explain select * from emp;

extra

包含额外的信息。

--using filesort:说明mysql无法利用索引进行排序,只能利用排序算法进行排序,会消耗额外的位置 explain select * from emp order by sal;

--using temporary:建立临时表来保存中间结果,查询完成之后把临时表删除 explain select ename,count(*) from emp where deptno = 10 group by ename;

--using index:这个表示当前的查询时覆盖索引的,直接从索引中读取数据,而不用访问数据表。如果同时出现using where 表名索引被用来执行索引键值的查找,如果没有,表面索引被用来读取数据,而不是真的查找 explain select deptno,count(*) from emp group by deptno limit 10;

--using where:使用where进行条件过滤 explain select * from t_user where id = 1;

--using join buffer:使用连接缓存,情况没有模拟出来

--impossible where:where语句的结果总是false explain select * from emp where empno = 7469;

索引监控

show status like "Handler_read%";参数解释 Handler_read_first:读取索引第一个条目的次数 Handler_read_key:通过index获取数据的次数 Handler_read_last:读取索引最后一个条目的次数 Handler_read_next:通过索引读取下一条数据的次数 Handler_read_prev:通过索引读取上一条数据的次数 Handler_read_rnd:从固定位置读取数据的次数 Handler_read_rnd_next:从数据节点读取下一条数据的次数

本文如果对你有帮助,请点赞收藏《好文推荐:Mysql基础复习》,同时在此感谢原作者。

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。
相关阅读
一文详解MySQL如何同时自增自减多个字段

一文详解MySQL如何同时自增自减多个字段

...方案一的解决方法。毕竟这种情况是属于少数的,在框架基础改着改着自己都会乱。三、使用SQL语句进行实现如果为了解决问题这一节的内容就不用在看了,看第一节就可以完美的解决你的问题了。小编是喜欢琢磨一个问题使用...

2023-06-07 #经典句子

mysql基础之sql语句分类及实际中的用途

mysql基础之sql语句分类及实际中的用途

做IT有时候无关乎技术好坏,关键要显得专业。显得专业你会拿到公司的Offer,显得专业客户就信服你,显得专业领导就欣赏你,反正就是各种好处,今天咱们就来讲一讲mysql专业一点的东西,提升一下逼格。上节课中老韩说“sel...

2023-10-07 #经典句子

mysql中insert语句如何使用?

mysql中insert语句如何使用?

...不需要赋值的列也必须要赋值为null。这样的sql语句是不推荐使用的。因为如果使用此方法,一旦表中的列发生顺序变化就会不能再正确插入。这种方法的维护性以及拓展性都比较差。2. 完整的insert语句如何使用?insert 语句...

2022-12-21 #经典句子

别再瞎找资料了 这份MySQL基础语句你一定要收好

别再瞎找资料了 这份MySQL基础语句你一定要收好

本文来自牛鹭学院学员:范汉一创建数据库创建之前判断该数据库是否存在:if exists (select * from sysdatabases where name="databaseName")drop database databaseNamegoCreate DATABASE databasenameon primary-- 默认就属于primary文件组,可省略;(/*--数据文件的...

2023-06-07 #经典句子

mysql查询语句中like instr in  find

mysql查询语句中like instr in find

...表里面有个type字段,它存储的是文章类型,有 1头条、2推荐、3热点、4图文等等 。现在有篇文章他既是头条,又是热点,还是图文,type中以 1,3,4 的格式存储。那我们如何用sql查找所有type中有4的图文类型的文章呢??这就要我...

2023-06-07 #经典句子

MySQL数据查询select语句灵活使用详解

MySQL数据查询select语句灵活使用详解

...个,这个跟现实结果记录数有关系。最好结合老刘的《零基础数据库教程》视频学习,注意观察一下不同的使用,得到的不同表关联结果。以下简单说明一下:A left join B 就是A为主表A right join B 就是B为主表A inner join B 就是取两...

2023-06-07 #经典句子

《面试八股文》之 MySql 35卷

《面试八股文》之 MySql 35卷

...,并且是单一职责 「第二范式」:「建立在第一范式的基础上」,第二范式要求数据库表中的每个实例或行必须「可以被惟一地区分」。为实现区分通常需要为表加上一个列,以存储各个实例的惟一标识。这个惟一属性列被称...

2012-07-17 #经典句子

MYSQL常用插入语句及使用场景总结

MYSQL常用插入语句及使用场景总结

...入数据时,如果唯一性校验出现重复问题,则在原有记录基础上,更新指定字段内容,其它字段内容保留;如果没有重复性问题,则执行插入操作。简单总结:重复则更新指定字段,不重复则插入示例INSERT INTO `user` ( username, PASSW...

2022-12-03 #经典句子