看了这篇MySQL,开发功力又升级!

你们好,我是小菜,一个渴望在互联网行业作到蔡不菜的小菜。可柔可刚,点赞则柔,白嫖则刚!
死鬼~看完记得给我来个三连哦!
mysql

本文主要介绍 Mysql开发和面试中所必知的
本文较长,分为上下篇(可收藏,勿吃尘)
若有须要,能够参考
若有帮助,不忘 点赞linux

1、MySQL架构

1)MySQL简介

MySQL是一个关系型数据库管理系统,由瑞典MYSQL AB公司开发,目前属于Oracle公司。
MySQL 是一种关联数据库管理系统,将数据保存在不一样的表中,而不是将全部数据放在一个大仓库中,这样就增长了速度并提升了灵活性。
Mysql是开源的,是能够定制的,采用了GPL协议,你能够修改源码来开发本身的MySQL系统。
MySQL支持大型的数据库。能够处理拥有上千万条记录的大型数据库。MySQL能够容许于多个系统上,而且支持多种语言。这些编程语言包括C、C++、Python、Java、Perl、PHP、Eiffel、Ruby和Tcl等。
MySQL支持大型数据库,支持5000条记录的数据仓库,32位系统表文件最大可支持4GB,64位系统支持最大的表文件为8TB。ios

2)MySQL配置文件

  • binlog(二进制日志)
    用于主从复制及备份恢复:binlog中存放了全部操做记录,可用于恢复。至关于Redis中的AOF,my.ini中binlog配置(默认是关闭的)如何开启:
[mysqld]
log-bin = mysql-bin
binlog-format = row
复制代码
  • Error log(错误日志)
    默认是关闭的,一般用于记录数据库服务端启动、重启、主从复制时,记录错误,将日志详情保留在文件中,方便DBA、运维开发人员阅读。如何开启:
[mysqld]
log-error=/data/mysql_error.log
复制代码
  • 慢查询日志log
    默认是关闭的。记录查询的sql语句,若是开启会减低mysql的总体性能,由于记录日志也是须要消耗系统资源的。如何开启:
[mysqld]
slow_query_log = ON
slow_query_log_file = /usr/local/mysql/data/slow.log     //linux
long_query_time = 1
复制代码
  • 数据文件
    windows:
    ..\mysql-8.0.19-winx64\data目录下存储数据库文件
    linux:
    默认路径/var/lib/mysql(可在配置文件中更改/usr/share/mysql/下的my-huge.cnf)每一个目录表明一个同名的库。
    Myisam存放方式:
  • frm文件(framework):存放表结构
  • myd文件(data):存放表数据
  • myi文件(index):存放表索引
    innodb存放方式:
  • ibdata1:Innodb引擎将全部表的数据都存放在这里面/usr/share/mysql/ibdata1而frm文件存放在库同名的包下
  • frm文件:存放表结构
  • 配置方式
    • windows:my.ini 配置文件
    • linux:my.cnf 配置文件

3)MySQL的用户与权限管理

  • MysSQL用户管理
    • 建立用户
      create user cbuc identified by '123456'
    • 关于 user 表
      select host,user,select_priv,insert_priv,drop_priv from mysql.user;

      host: 表示链接类型
      user:表示用户名
      select_priv,insert_priv,drop_priv等:该用户所拥有的权限
    • 设置密码
      --- 修改当前用户的密码
      set password = password('123456')
      --- 修改某个用户的密码
      update mysql.user set password = password('123456') where user = 'cbuc'
    • 修改用户
      --- 修改用户名:
      update mysql.user set user = 'cbuc' where user='c1';
      --- 全部经过user表修改后必须用该命令才能生效
      flush privileges;
    • 删除用户
      --- 不要经过delete from user t1 where t1.user='cbuc'进行删除,系统会有残留信息保留
      drop user cbuc;
  • 权限管理
    • 授予权限:
      --- 若是发现没有该用户,则会直接建立一个用户
      grant 权限1,权限2,…,权限n on 数据库名.表名 to 用户名@用户地址 identified by '密码'
      --- 给cbuc用户赋予对表增删改查的权限
      grant select,insert,delete,update on db_crm.* to cbuc@localhost;
    • 收回权限:
      --- 若是已赋全库的表,就回收全库全表的全部权限
      revoke 权限1,权限2,…,权限n on 数据库名.表名 from 用户名@用户地址
      revoke all privileges on mysql.* from cbuc@localhost
    • 收回权限:
      --- 查看当前用户权限
      show grants;
      --- 查看某用户的全局权限
      select * from mysql.user;
      --- 查看某用户的某库的权限
      select * from mysql.db;
      --- 查看某用户的某个表的权限
      select * from mysql.tables_priv;

4)MySQL其余配置

  • 大小写问题

windows系统默认是大小写不敏感,可是linux系统是大小写敏感的。web

  • 0(默认): 大小写敏感
  • 1: 大小写不敏感。建立的表,数据库都是以小写形式存放在磁盘中,对于sql语句都是转换为小写对表的DB进行查找。
  • 2: 建立的表和DB依据语句上格式存放,凡是查找都是转换为小写进行
SHOW VARIABLES LIKE '%lower_case_table_names%';
复制代码

设置:

set lower_case_table_names = 1;   #此变量是只读权限,须要在配置文件中修改
复制代码
  1. 在my.inni / my.cnf中添加
    [mysqld]
    lower_case_table_names = 1 
复制代码
  1. 重启服务器(重启前要将原来的数据库和表转换为小写,不然更改后将找不到数据库名
  • sql_mode

sql_mode 是个很容易被忽视的变量,默认值是空值,在这种设置下是能够容许一些非法操做的, 好比容许一些非法数据的插入。在生产环境必须将这个值设置为严格模式,因此开发、测试环境的数据库也必需要设置,这样在开发测试阶段就能够发现问题。面试

经常使用设置:算法

[mysqld]
sql-mode="STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION"
复制代码

5)MySQL存储引擎

  • 查看引擎
show engines;
复制代码

能够看出默认的存储引擎是 InooDB

  • 各引擎简介sql

    • InnoDB存储引擎:
      InnoDB是MySQL默认的事务型引擎,它被设计用来处理大量的短时间(short-lived)事务。除非有很是特别的缘由须要使用其余的存储引擎,不然应该优先考虑InnoDB引擎。具备行级锁外键事务等优点,适合高并发状况
    • MyISAM存储引擎:
      MyISAM提供了大量的特性,包括全文索引、压缩、空间函数(GIS)等,但MyISAM不支持事务和行级锁(MyISAM改表时会将整个表全锁住),缺陷:崩溃后没法安全恢复
    • Archive引擎:
      rchive存储引擎只支持 insert 和 select操做,在MySQL5.1以前不支持索引。Archive表适合日志和数据采集类引用。适合低访问量大数据等状况
    • Blackhole引擎
      Blackhole引擎没事实现任何存储机制,它会丢弃全部插入的数据,不任何保存。但服务器会记录Blackhole表的日志,因此能够用于复制数据到备库,或者简单地记录到日志。但这种应用方式会碰到不少问题,所以并不推荐。
    • CSV引擎
      CSV引擎能够将普通的CSV文件做为MySQL的表来处理,但不支持索引。能够做为一种数据交换的机制,很是有用。存储的数据直接能够在操做系统里,用文本编辑器,或者excel读取。
    • Memory引擎
      若是须要快速地访问数据,而且这些数据不会被修改,重启后丢失也没有关系的话,那么使用Memory表是很是有用的。Memory表至少比MyISAM表要快一个数量级。
    • Federated引擎
      Federated引擎是访问其余MySQL服务器的一个代理,尽管该引擎看起来提供了一种很好的跨服务器的灵活性,但也常常带来问题,所以默认是禁用的。
  • MyISAM和InnoDB比较
    数据库

    InnoDB主键为聚簇索引,基于聚簇索引的增删改查效率很是高
    聚簇索引: 实际存储的循序结构与数据存储的物理机构是一致的
    非聚簇索引: 记录的物理顺序与逻辑顺序没有必然的联系,与数据的存储物理结构没有关系

2、索引优化分析

1)性能降低/SQL执行时间长

  • 查询数据过多
    能拆则拆,条件过滤尽可能少
  • 过多JOIN
    JOIN原理:用A表的每一条数据扫描B表的全部数据,因此尽可能先过滤再关联
  • 没有利用到索引
    索引针对建索引,但并不可能每一列都建索引
    索引并不是越多越好。当数据更新了,索引会进行调整,也会很消耗性能。
    而且MySQL并不会把全部索引都用上,只会根据其算法挑一个索引用。因此建的准很重要
  • 服务器调优及各个参数设置(缓冲、线程数)

2)JOIN查询

  • SQL执行顺序编程

    人工读取顺序:windows

    SELECT (DISTINCT)
        < select_list >
    FROM
        < left_table > < join_type >
    JOIN < right_table > ON < join_condition >
    WHERE
        < where_condition >
    GROUP BY 
        < group_by_list >
    HAVING
        < having_condition>
    ORDER BY
        < order_by_condition >
    LIMIT < limit_number >
    复制代码

    引擎执行顺序:

    FROM < left_table >
    ON < join_condition >
    < join_type > JOIN < right_table >
    WHERE < where_condition >
    GROUP BY < group_by_list >
    HAVING < having_condition >
    SELECT 
    (DISTINCT) < select_list >
    ORDER BY < order_by_condition >
    LIMIT < limit_number >
    复制代码

总结:

  • 共有/独有
    有两个表,员工表Employee和部门表Dept,员工表里面有Dept字段与部门表的主键ID相对应。
    共有:知足employee.deptId = dept.id 的数据 称为两表共有
    独有:employee.deptId <> dept.id 的数据 称为员工表独有
  • 七种JOIN
    有两个表,t1 表是员工表 emp,t1 表是部门表 dept

一、 t1 表和 t2 表共有 (inner join)

在这里插入图片描述
在这里插入图片描述
select * from emp t1 inner join dept t2 on t1.deptId = t2.id
复制代码

二、t1 表和 t2 表共有 + t1 表独有 (left join)

在这里插入图片描述
在这里插入图片描述
select * from emp t1 left join dept t2 on t1.deptId = t2.id
复制代码

三、t1 表和 t2 表共有 + t2表独有(right join

在这里插入图片描述
在这里插入图片描述
select * from emp t1 right join dept t2 on t1.deptId = t2.id
复制代码

四、 t1 表的独有(left join…where t2.id is null

在这里插入图片描述
在这里插入图片描述
select * from emp t1 left join dept t2 on t1.deptId = t2.id where t2.id is null
复制代码

5.t2 表的独有(right join…where t1.id is null

在这里插入图片描述
在这里插入图片描述

6. t1 表和 t2 表全有( union
在这里插入图片描述
在这里插入图片描述

MySQL中不支持FULL JOIN
UNION: 可去除重复数据
UNION ALL: 不去除重复数据

select * from emp t1 left join dept t2 on t1.deptId = t2.id
union
select * from emp t1 right join dept t2 on t1.deptid = t2.id
复制代码

七、 t1 表的独有 + t2 表的独有(union

在这里插入图片描述
在这里插入图片描述
select * from emp t1 left join dept t2 on t1.deptId = t2.id where t2.id is null
UNION
select * from emp t1 right join dept t2 on t1.deptId = t2.id 
where t1.deptId is null 
复制代码

3)索引简介

MySQL官方对索引的定义为:索引(Index)是帮助MySQL高效获取数据的数据结构。能够获得索引的本质:索引是数据结构。 目的在于提升查询效率,能够类比字典。

  • 简单理解为 “排好序的快速查找数据结构”
    在数据以外,数据库系统还维护着知足特定查找算法的数据结构,这些数据结构以某种方式引用(指向)数据。

    在这里插入图片描述
    在这里插入图片描述

    左边是数据表,一共有两列七条数据,最左边是数据记录的物理地址,为了加快Col2 的查找,能够维护一个右边所示的二叉查找树,每一个节点分别包含索引值和一个指向对应数据记录物理地址的指针,这样就能够运用二叉查找在必定的复杂度内获取到相应数据,从而快速的检索出符合条件的记录。
    二叉树: 二叉树极可能会发生两边不平衡的状况。
    B-Tree: 会自动根据两边的状况自动调节,使两端无限趋近于平衡状态,可使性能最稳定。可是插入/修改操做过多时,B-TREE会不断调整平衡,消耗性能。

  • 通常来讲索引自己也很大,不可能所有存储在内存中,所以索引每每以索引文件的形式存储在磁盘上。

  • 咱们日常所说的索引,若是没有特别指明,都是指B树 (多路搜索树,并不必定是二叉的)结构组织的索引。其中汇集索引,次要索引,覆盖索引,复合索引,前缀索引,惟一索引默认都是使用B+树这种类型的索引以外,还有哈希索引(hash index)等。

  • 索引优点

    • 相似图书馆简历书目索引,提升数据检索的效率,下降数据库的IO成本。
    • 经过索引列对数据进行排序,下降数据排序的成本,下降了CPU的消耗。
  • 索引劣势

    • 实际上索引也是一张表,该表保存了主键与索引字段,并指向实体表的记录,因此索引列也是要占用空间的。
    • 虽然索引大大提升了查询速度,同时却会下降更新表的速度,如对表进行INSERT、UPDATE、和DELETE,由于更新表时,MySQL不只要保存数据,还要保存一下索引文件每次更新添加了索引列的字段,都会调整由于更新所带来的键值变化后的索引信息。
    • 索引只是提升效率的一个因素,若是你的MySQL有大量的表,就须要花时间研究创建最优秀的索引,或优化查询语句
  • 索引结构

    • BTree索引:
      真实数据存在于叶子节点,即三、五、九、十、1三、1五、2八、2九、3六、60、7五、7九、90、99.
      非叶子节点不存储真实的数据,只存储指引搜索方向的数据项,如1七、35并不真实存在于数据表中。
      在这里插入图片描述
      在这里插入图片描述

      【查找过程】
      若是要查找数据29,那么首先会把磁盘块1有磁盘加载到内存,此时发生一次IO,在内存中用二分查找肯定29在17和35之间,锁定磁盘块1的P2指针,内存时间由于很是短(相比磁盘的IO)能够忽略不计,经过磁盘块1的的P2指针的磁盘的磁盘地址把磁盘块3由磁盘加载到内存,发生第二次IO,29在26和30之间,锁定磁盘块3的P2指针,经过指针加载磁盘块8到内存,发生第三次IO,同时内存中作二分查找到29,结束查询,总计三次IO
    • B+Tree索引:
      在这里插入图片描述
      在这里插入图片描述

      B+Tree 第二级的数据并不能直接取出来,只做索引使用。在内存有限的状况下,查询效率高于BTree
      BTree第二级能够直接取出来,树形结构比较重,在内存无限大到时候有优点。

    【B+Tree 和 BTree 的区别】
    1) 内存有限的状况下,B+Tree永远比BTree好,无限内存则反之
    2) B树的关键字和记录是放在一块儿的,叶子节点能够看作外部节点,不包含任何信息;B+树叶子节点中国你只有关键字和指向下一个节点的索引,记录只放在叶子节点中。(一次查询可能进行两次I/O操做)
    3) 在B树中,越靠近根节点的记录查找时间越快,只要找到关键字便可肯定记录存在;而B+树每一个记录的查找时间基本是同样的,都须要从根节点走到叶子节点,并且在叶子节点中还要在比较关键字。从这个角度看B树的性能好像会比B+树好,而在实际应用中倒是B+树的性能要好些。由于B+树的非叶子节点不存放实际的数据,这样每一个节点可容纳的元素个数比B数多,树高比B树小,这样带来的好处是减小磁盘访问次数。尽管B+树找到一个记录所需的比较次数比B树多可是一次磁盘访问时间至关于成百上千次内存比较时间,所以实际中B+树的性能可能还会好写,并且B+树的叶子节点使用指针链接在一块儿,方便顺序遍历(例如查看一个目录下的全部文件,一个表中的全部记录等)
    4) B+树的磁盘读写代价更低,相对来讲IO读写次数也就下降了。
    5) B+树的查询效率更加稳定。因为非终结点并非指向文件内容的节点,而只是叶子节点中关键字的索引。因此任何关键字的查找必须走一条从根节点到叶子节点的路。因此关键字查询的路径长度相同,致使每个数据的查询效率至关。

    • 聚簇索引

      在这里插入图片描述
      在这里插入图片描述

      好处:
      按照聚簇索引排序顺序,查询显示必定范围数据的时候,因为数据都是紧密相连,数据库不用从多个数据块中提取数据,因此节省了大量的IO操做。
      限制:

      • 对于MySQL数据库目前只有InnoDB数据引擎支持聚簇索引,而MyISAM并不支持聚簇索引。
      • 因为数据物理存储排序方式只能有一种,因此每一个MySQL的表只能有一个聚簇索引。通常状况下就是该表的主键
    • full-text全文索引

      全文索引(也称全文检索)是目前搜索引擎使用的一种关键技术。它可以利用分词技术等多种算法智能分析出文本文字中关键词的频率和重要性,而后按照必定的算法规则智能地筛选出咱们想要的搜索结果。

      • 查询:
      # 传统 LIKE 查询
      select * from blink t1 where t1.content like '%菜%'

      # 全文检索
      select * from blink t1 where MATCH(title,content) AGAINST('菜'
      复制代码
      • 限制: MySQL5.6.4以前只用MyISAM 支持,5.6.4之后 InnoDB才支持,可是官方版不支持中文分词,须要第三方分词插件。
    • Hash索引

      • Hash 索引只有Memory,NDB两种引擎支持,Memory引擎默认支持。
      • Hash索引,若是多个Hash值相同,出现哈希碰撞,那么索引以链表的方式存储。
      • NoSql采用此索引结构。
    • RTree索引
      R-Tree在MySQL不多使用,仅支持geometry 数据结构,支持该类型的存储引擎只有MyISAM、bdb、InnoDB、ndb、archive几种。相对于B-Tree,R-Tree的优点在于查找

  • 索引分类

    • 主键索引
      设定为主键后数据库会自动简历索引,InnoDB采用聚簇索引
      语法:
    # 随表一块儿建立
    CREATE TABLE emp (
        # 使用AUTO_INCREMENT关键字的列必需要有索引
        ID int(10UNSIGNED AUTO_INCREMENT
        , NAME varchar(8)
        , PRIMARY KEY(ID)
     )

    # 单独建主键索引
    ALTER TABLE emp add PRIMARY KEY emp(id);

    # 删除主键索引
    ALTER TABLE emp drop PRIMARY KEY;   # 修改主键索引前必须删除(drop)原索引,再新建(add)索引
    复制代码
    • 单值索引
      即一个索引只包含单个列,一个表能够有多个单列索引。
      语法:
    # 随表一块儿建立
    CREATE TABLE emp (
        # 使用AUTO_INCREMENT关键字的列必需要有索引
        ID int(10UNSIGNED AUTO_INCREMENT
        , EMP_NO varchar(8)
        , NAME varchar(8)
        , KEY(EMP_NO)
     )

    # 单独建单列索引
    create index idx_emp_no on emp(EMP_NO)

    # 删除单列索引
    drop index idx_emp_no
    复制代码
    • 惟一索引
      索引列的值必须惟一,但容许有空值。
      创建惟一索引是必须保证全部的值是惟一的(除了null),如有重复数据,会报错
    # 随表一块儿建立
    CREATE TABLE emp (
        # 使用AUTO_INCREMENT关键字的列必需要有索引
        ID int(10UNSIGNED AUTO_INCREMENT
        , EMP_NO varchar(8)
        , NAME varchar(8)
        , UNIQUE(EMP_NO)
     )

    # 单独建惟一索引
    create unique index idx_emp_no on emp(EMP_NO)

    # 删除主键索引
    drop index idx_emp_no on emp
    复制代码
    • 复合索引
      在数据库操做期间,复合索引比单值索引所须要的开销更小(对于相同的多个列建索引);
      当表的行数远大于索引列的数目时可使用复合索引。
    # 随表一块儿建立
    CREATE TABLE emp (
        # 使用AUTO_INCREMENT关键字的列必需要有索引
        ID int(10UNSIGNED AUTO_INCREMENT
        , EMP_NO varchar(8)
        , NAME varchar(8)
        , key(EMP_NO,NAME)
     )
    #创建惟一索引是必须保证全部的值是惟一的(除了null),如有重复数据,会报错

    # 单独建惟一索引
    create index idx_no_name on emp(EMP_NO,NAME)

    # 删除主键索引
    drop index idx_no_name on emp
    复制代码

    【基本语法】

    # 建立
    alter < table_name > add [uniqueindex <index_name> on <column_name>

    # 删除
    drop index <index_name> on <table_name>

    #查看
    show index from <table_name>

    #使用ALTER命令
    #方式1:该语句添加一个主键,这意味着索引值必须是惟一的,且不能为null
    alter table <table_name> add primary key <column_name>

    #方式2:该语句添加一个惟一索引,值必须是惟一的(null外,null可能会出现不少次)
    alter table <table_name> add unique key <column_name>

    #方式3:该语句添加普通索引,索引值能够出现不少次
    alter table <table_name> add index <index_name>(column_name)

    #方式4:该语句指定了索引为FULLTEXT,用户全文索引
    alter table <table_name> add FULLTEXT <index_name>(column_name)
    复制代码
  • 哪些状况须要创建索引

    • 主键自动创建惟一索引
    • 频繁做为查询条件的字段应该建立索引(where后面的语句)
    • 查询中与其余表关联的字段,外键关系创建索引
    • 单键/组合索引的选择问题(在高并发下倾向建立组合索引)
    • 查询中排序的字段,排序字段若经过索引去访问将大大提升排序速度
    • 查询中统计或者分组字段
  • 哪些状况不须要创建索引

    • 表记录太少
    • 常常增删改的表(由于更新表时,MySQL不只要保存数据,还要保存一下索引文件)
    • where 条件里用不到的字段不建立索引
    • 数据重复且分布平均的表字段,所以应该只为最常常查询和最常常排序的数据列创建索引。注意,若是某个数据列包含许多重复的内容,为它创建索引就没有太大的实际效果。

4)性能分析

  • MySQL常见瓶颈

    • CPU
      SQL中对大量数据进行比较、关联、排序、分组(最大的压力在于比较
    • IO
      实例内存知足不了缓存数据或排序等须要,致使产生大量物理IP。查询执行效率低,扫描过多数据行。

    • 不适宜的锁的设置,致使线程阻塞,性能降低。死锁,线程之间交叉调用资源,致使死锁,程序卡主。

    服务器硬件的性能瓶颈:
    top,free,iostat和vmstat来查看系统的性能状态

  • Explain的使用

    使用Explain关键字能够模拟优化器执行SQL查询语句,从而知道MySQL是如何处理你的SQL语句的。分析你的查询语句或是表结构的性能瓶颈

    • 能够查看的内容
    1. 表的读取顺序
    2. 哪些索引可使用
    3. 哪些索引被实际使用
    4. 表之间的引用
    5. 每张表有多少行被优化器查询
    • 怎么用
      explain + SQL语句
      包含的信息:
    • 各字段解释

1.【 id】
select查询的序列号,包含一组数字,表示查询中执行select字句或操做表的顺序。
三种状况:

  • id相同,执行顺序由上至下

  • id不一样,若是是子查询,id的序号会递增,id值越大优先级越高,越被先执行

  • id相同和不一样同时存在

id若是相同,能够认为是一组,从上往下顺序执行;在全部组中,id值越大,优先级越高,越先执行。
2.【select_type】

  • SIMPLE
    简单的select查询,查询中不包含子查询或者UNION
  • PRIMARY
    查询中若包含任何复杂的子部分,最外层查询则被标记为Primary
  • DERIVED
    在FROM列表中包含的子查询被标记为DERIVED(衍生)MySQL会递归执行这些子查询,把结果放在临时表里。
  • SUBQUERY
    在SELECT或WHERE列表中包含了子查询
  • DEPENDENT SUBQUERY
    在SELECT或WHERE列表中包含了子查询,子查询基于外层

    【dependent subquery 和 subquery 的区别】
    依赖子查询:子查询结果为多值
    子查询:查询结果为单值
  • UNCACHEABLE SUBQUERY
    没法被缓存的子查询

    @@表示查的是环境参数,没办法缓存
  • UNION
    若第二个SELECT出如今UNION以后,则被标记为UNION;
    若UNION 包含在FROM字句的子查询中,外层SELECT将被标记为:DERIVED
  • UNION RESULT
    从UNION表获取结果的SELECT

3.【table】
显示这一行的数据是关于哪张表的
4.【type】
type显示的是访问类型,是较为重要的一个指标,结果值从最好到最坏的依次排序:
system > const > eq_ef > ref > range(尽可能保证) > index > ALL
通常来讲,得保证查询至少达到range级别,最好能达到ref

  • system
    表只有一行记录(等于系统表),这是const类型的特列,平时不会出现,这个也能够忽略不计
  • const
    表示经过索引一次就找到了,const 用于比较primary key或者 unique索引。由于只匹配一行数据,因此很快将主键置于where列表中,MySQL就能将该查询转换为一个常量
  • eq_ref
    惟一性索引扫描,对于每一个索引键,表中只有一条记录与之匹配。常见于主键或惟一索引扫描
  • ref
    非惟一性索引扫描,返回匹配某个单独值的全部行,本质上也是一种索引访问,它返回全部匹配某个单独值的行,然而,他可能会找到多个符合条件的行,因此他应该属于查找和扫描的混合体
  • range
    检索给定范围的行,使用一个索引来选择行。key列显示使用了哪一个索引,通常就是在你的where语句中出现了between<>in等查询。这种范围扫描索引比全表扫描要好,由于它只须要开始于索引的某一个点,而结束于另外一点,不用扫描所有索引。
  • index
    Full Index Scan,index与ALL区别为index类型只遍历索引树。这一般比ALL快,由于索引文件一般比数据文件小。(也就是说虽然all和index都是读全表的),但index是从索引中读取的,而all是从硬盘中读的。
  • all
    Full Table Scan,将遍历全表以找到匹配的行

5.【possible_keys】
显示可能应用到这张表中的索引,一个或多个。查询涉及到的字段上若存在的索引,则该索引将被列出,但不必定被查询实际使用
6.【key】
实际使用的索引,若是为NULL,则没有使用索引。查询中若使用了覆盖索引,则该索引和查询的select字段重叠。
7.【key_len】
表示索引中使用的字节数,可经过该列计算查询中使用的索引的长度。key_len字段可以帮你检查是否充分利用上了索引。


计算方式:

动态类型包括:varchar,detail text()截取字符串
本张的表结构以下:

第一组计算为:
key_len=deptno(int)+null+ename(varchar(20)3+动态=4+1+203+2=67
第二组计算为:
key_len=deptno(int)+null=4+1=5
8.【ref】
显示索引的哪一列被使用了,若是可能的话,是一个常数。哪些列或者常量被用于查找索引列上的值

9.【row】
rows列显示MySQL认为它执行查询时必须检查的行数(越少越好)

10.【Extra】
包含不适合在其余列中显示但十分重要的额外信息。

  • Using filesort
    说明mysql会对数据使用一个外部的索引排序,而不是按照表内的索引顺序进行读取。MySQL中没法利用索引完成的排序操做称为“文件排序”。
  • Using temporary
    使用了临时表保存中间结果,MySQL在对查询结果排序时使用临时表。常见于排序order by 和分组查询 group by。
  • Using index
    表示相应的select操做中使用了覆盖索引(Covering Index),避免了表的数据行,效率不错。若是同时出现using where,代表索引被用来执行索引键值的查找;若是没有同时出现using where,代表索引只是用来读取数据而非利用索引执行查找。
    覆盖索引:
    一个索引包含了(或覆盖了)【select子句】与查询条件【where 子句】中全部须要的字段就叫作覆盖索引。
    注意: 只取出须要的列,不可select *,不可将全部字段一块儿作索引
  • Using where
    代表使用了 where 过滤
  • Using join buffer
    使用了链接缓存

5)查询优化

  • 索引的使用
  1. 全值匹配我最爱
    staffs 表创建索引 idx_staffs_nameAgePos,以name,age,pos的顺序创建,全值匹配标识按顺序匹配。
  2. 最佳左前缀原则
    若是索引了多列,要遵照最左前缀原则,值得是查询从索引的最左前列开始,而且不跳过索引中的列
    and 忽略左右关系,即便没有按顺序,因为优化器的存在,会自动优化
  3. 不在索引列上作任何操做(计算、函数、(自动或手动)类型转换),会致使索引失效而转向全表扫描。
  4. 存储引擎不能使用索引中范围条件右边的列
    范围如有索引则能使用到索引,范围条件右边的索引会失效(范围条件右边与范围条件使用的同一个组合索引,右边的才会失效,如果不一样索引则不会失效)
  5. **尽可能使用覆盖索引(只访问索引的查询(索引列和查询列一致)),减小select ***
  6. MySQL在使用不等于(!= 或 <>)的时候没法使用索引,会致使全表扫描。
    where age != 10 and name = 'xxx' 这种状况下,mysql会自动优化将 name = 'xxx' 放在 age != 10 以前,name依然能使用索引,只是age的索引失效
  7. is not null 也没法使用索引,可是 is null 是可使用索引
  8. like 以通配符开头('%xxx')索引失效变成全表扫描
    like '%xxx':type 类型会变成all
    like 'xxx%':type 类型为range,算是范围,可使用索引
  9. 字符串不加单引号索引失效
    底层进行类型转换时索引失效,使用了函数形成了索引失效

10.少用or,用它链接时索引会失效

【例子小节】
此时复合索引index(a,b,c)

【使用建议】

  1. 对于单键索引,尽可能选择针对当前query过滤性更好的索引
  2. 在选择组合索引的时候,当前query中过滤性最好的字段在索引字段顺序中,位置越靠前越好。(避免索引过滤性好的索引失效)
  3. 在选择组合索引的时候,尽可能选择能够可以包含当前query中where字句中更多字段的索引
  4. 尽量经过分析统计信息和调整query的写法来达到选择合适索引的目的
  • 关联查询优化
    一、保证被驱动表的join字段已经被索引(join后的表为驱动表)
    二、left join时,选择小表做为驱动表,大表做为被驱动表(left join必定是左边是驱动表,右边是被驱动表)
    三、inner join时,MySQL会本身帮你把小结果集选为驱动表。由于驱动表不管如何都会被全表扫描,因此扫描次数越少越好。
    四、子查询尽可能不要放在被驱动表,有可能使用不到索引。
# 未加索引,type为ALL
explain select * from class left join book on class.card = book.card
# 添加索引优化,第二行的type变成了ref
alter table book add index idx_card_B(card);
# 这是由左链接特效决定的,left join条件用于肯定如何从右表搜索行,左边必定都有
# 继续优化,删除旧索引,新建新索引
drop index idx_card_B on book;
alter table class add index idx_card_A(card)
复制代码
  • 子查询优化
    一、 有索引的状况下用 inner join 是最好的,其次是 in,exists最糟糕
    二、 无索引的状况下用小表驱动大表,由于 join 方式须要 distinct ,没有索引distinct 消耗性能比较大,因此 exists 性能最佳,其次 in 其次,join性能最差
    三、 无索引的状况下大表驱动小表,in和exists的性能应该是接近的,都比较糟糕,exists稍微好一点,可是超不过5%
  • order by关键字优化
    尽可能使用Index方式排序,避免使用FileSort 方式排序。MySQL中支持两种方式的排序,FileSortIndex,其中index效率高,它指Mysql扫描索引自己完成排序,FileSort方式效率比较低。知足三种状况会使用Index排序。
  • Order By语句使用索引最左前列
  • 使用where子句与order by子句条件列组合知足索引最左前列
  • where子句中若是出现索引的范围查询(即explain中出现range)会致使order by索引失效。

例子:talA 表中有索引 (age,birth,name)


  • 分页查询的优化--limit
explain select sql_no_chache  * from emp order by deptno limit 10000,40
复制代码
#加上索引
create index emp on emp(deptno)
复制代码
# 经过以上结果能够看出加上索引并不能改变
# 进一步优化:先利用覆盖索引把要取的数据行的主键取到,而后再用这个主键列与数据表作关联(查询数据量小了后)
explain select sql_no_cache * from emp e inner join (select id from emp e order by deptno limit 10000,40)a on a.id = e.id 
复制代码
  • GROUP BY 关键字优化
    一、group by实质上是先排序后进行分组,遵守索引建的最佳左前缀
    二、当没法使用索引列,增大max_length_for_sort_data参数的设置+增大sort_buffer_size参数的设置
    三、where高于having,能写在where限定的条件就不要去having限定了。
  • 去重优化
    尽可能不要使用distinct关键字去重
    例子:
# 使用distinct关键字去重消耗性能
select distinct BOOK_NAME from book where id in(1,2,5,4,8)
# 使用 group by可以利用到索引
select BOOK_NAME from book where id in(1,2,5,4,8group by BOOK_NAME
复制代码
看完不赞,都是坏蛋
看完不赞,都是坏蛋

本文较长,能看到这里的都是最棒的!成长之路学无止境~
今天的你多努力一点,明天的你就能少说一句求人的话!
好久好久以前,有个传说,听说:
看完不赞,都是坏蛋

相关文章
相关标签/搜索