MySql

MySql索引优化

一、性能下降SQL慢 执行时间长 等待时间长

原因:
(1)、查询语句写的烂
(2)、索引失效:索引分为单值索引和多值索引
单值索引:
    create index idx_user_name on user(name);
多值索引:
    create index idx_user_nameEmail on user(name,email);

 (3)、关联查询太多join(设计缺陷或不得已的需求;
(4)、服务器调优及各个参数设置(缓冲\线程数等)。

二、常见的Join查询

1、SQL的执行顺序:
手写:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
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_condotion>
ORDER BY
<order_by_condotion>
LIMIT <limit_number>
机读:
1
2
3
4
5
6
7
8
9
10
FORM <left_table>
ON <join_condition>
<join_type> JOIN <right_type>
WHERE <where_condition>
GROUP BY <group_by_list>
HAVING <having_condition>
SELECT
DISTINCT <select_list>
ORDER BY <order_by_condition>
LIMIT <limit_number>
2、join图

image

两张表:tbl_dept

image

tbl_emp:

image

查询结果:

image

中: select * from tbl_emp a inner join tbl_dept b on a.deptId=b.id;

image

左上:select * from tbl_emp a left join tbl_dept b on a.deptId=b.id;

image

右上:select * from tbl_emp a right join tbl_dept b on a.deptId=b.id;

image

左中:select * from tbl_emp a left join tbl_dept b on a.deptId=b.id where b.id is null;

image

右中:select * from tbl_emp a right join tbl_dept b on a.deptId=b.id where a.deptId is null;

image

左下: select * from tbl_emp a left join tbl_dept b on a.deptId=b.id ;

image

右下:SELECT * FROM tbl_emp a LEFT JOIN tbl_dept b ON a.deptId=b.id WHERE b.id IS NULL 
UNION 
SELECT * FROM tbl_emp a RIGHT JOIN tbl_dept b ON a.deptId=b.id WHERE a.`deptId` IS NULL ;

image

三、索引

1、什么是索引
   Mysql官方对索引的定义为:索引(Index)是帮助MySQL高效获取数据的数据结构。可以得到索引的本质:引是数据结构。目的在于提高查找效率
   。
可以理解为“排好序的快速查找数据结构”。
   数据本身之外,数据库还维护着一个满足特定查找算法的数据结构,这些数据结构以某种方式指向数据,这样就可以在这些数据结构的基础上实现
   高级查找算法,这种数据结构就是索引。

image

一般来说索引本身也很大,不可能全部存储在内存中,因此索引往往以文件形式存储在硬盘上,如下图的.MYI文件就是索引文件:

image

 我们平时所说的索引,如果没有特别指明,都是指B树(多路搜索树,并不一定是二叉树)结构组织的索引。其中聚集索引,次要索引,覆盖索引,
复合索引,前缀索引,唯一索引默认都是使用B+树索引,统称索引。当然,除了B+树这种类型的索引之外,还有哈希索引(hash index)等。

2、索引的优势

(1)、类似大学图书馆建书目索引,提高数据检索效率,降低数据库的IO成本;

(2)、通过索引列对数据进行排序,降低数据排序成本,降低了CPU的消耗;

3、索引的劣势

(1)、实际上索引也是一张表,该表保存了主键和索引字段,并指向实体表的记录,所以索引列也是要占用空间的;

(2)、虽然索引大大提高了查询速度,同时却会降低更新表的速度,如果对表INSERT,UPDATE和DELETE。因为更新表时,MySQL不仅要不存数据,
还要保存一下索引文件每次更新添加了索引列的字段,都会调整因为更新所带来的键值变化后的索引信息;

(3)、索引只是提高效率的一个因素,如果你的MySQL有大数据量的表,就需要花时间研究建立优秀的索引,或优化查询语句;

4、索引的分类
(1)、单值索引:
即一个索引只包含单个列,一个表可以有多个单列索引。建议一张表索引不要超过5个,优先考虑复合索引。

(2)、唯一索引:
索引列的值必须唯一,但允许有空值。(unique key)

(3)、复合索引,即一个索引包含多个列。


基本语法:
(1)、创建
创建表时添加索引:
CREATE [UNIQUE] INDEX  indexName ON mytable(columnname(length));
修改表时添加索引:
ALTER mytable ADD [UNIQUE]  INDEX [indexName] ON(columnname(length));

(2)、删除索引
DROP INDEX [indexName] ON mytable;

(3)、查看索引
SHOW INDEX FROM table_name\G

(4)有四种方式来添加数据表的索引
ALTER TABLE tbl_name ADD PRIMARY KEY(column_list)#该语句添加一个主键,这意味着索引值必须是唯一的,且不能为空
ALTER TABLE tbl_name ADD UNIQUE index_name(column_list)#这条语句创建的索引值必须是唯一的(除NULL除外,NULL可能会多次出现)
ALTER TABLE tbl_name ADD INDEX index_name(column_list)#添加普通值索引,索引值可能出现多次
ALTER TABLE tbl_name ADD FULLTEXT index_name(column_list)#该语句指定索引为fulltext,用于全文索引.

5、mysql索引结构
(1)、BTree索引

image

上图是一颗b+Tree,浅蓝色的块我们称之为一个磁盘块,可以看到每个磁盘块包含几个数据项(深蓝色的所示)和指针(黄色所示),如磁盘块1包含
数据项17和35,包含指针P1、P2、P3,P1表示小于17的磁盘块,P2表示在17和35之间的磁盘块,P3表示大于35的磁盘块。其实真实的数据存在于叶子
节点,即3、5、9、10、13、15、28、29、36、60、75、79、90、99,非叶子节点不存储真实的数据,只存储搜索方向的数据项,如:17,35并不真实存在于数据表中。
查找过程:
    如果要查找数据项29,那么先把磁盘块1由磁盘加载到内存,此时发生一次IO,在内存中用二分法查找确定29在17和35之间,锁定磁盘块1 
    的P2指针,内存时间因为非常短(相比磁盘的IO)可以忽略不计,通过磁盘块1的P2指针的磁盘地址把磁盘块3由由磁盘加载到内存,发生第二次IO,
    29在26和30之间,锁定磁盘块P2指针,通过指针加载磁盘块8到内存,发生第三次IO,同时内存中做二分查找找到29,结束查询,总计三次IO。
Btree索引(或Balanced Tree),是一种很普遍的数据库索引结构,oracle默认的索引类型(本文也主要依据oracle来讲)。其特点是定位高效、利用
率高、自我平衡,特别适用于高基数字段,定位单条或小范围数据非常高效。理论上,使用Btree在亿条数据与100条数据中定位记录的花销相同。
    数据结构利用率高、定位高效

(2)、Hash索引
(4)、full-text全文索引
(5)、R-Tree索引

6、哪些情况需要建索引
    (1).主键自动建立唯一索引
    (2).频繁作为查询的条件的字段应该创建索引
    (3).查询中与其他表关联的字段,外键关系建立索引
    (4).频繁更新的字段不适合创建索引,因为每次更新不单单是更新了记录还会更新索引,加重IO负担
    (5).Where条件里用不到的字段不创建索引
    (6).单间/组合索引的选择问题,who?(在高并发下倾向创建组合索引)
    (7).查询中排序的字段,排序字段若通过索引去访问将大大提高排序的速度
    (8).查询中统计或者分组字段

7、哪些情况不需要建索引
(1)、表记录太少
(2)、经常增删改的表
原因:提高了查询速度,同时却会降低更新表的速度,比如对表进行INSERT、UPDATE、DELETE.因为更新表时,MySQL不仅要保存数据,还要保存一下索引。
(3)、数据重复且分布平均的表字段,因此应该只为经常查询和经常排序的数据列建立索引。
注意,如果某个数据列包含许多重复的内容,为它建立索引就没有太大的实际效果。
例如:假如一个表有10万行记录,有一个字段A只有T和F两种值,且每个值得分布盖里大概为50%,那么对这种表A建索引一般不会提高数据库的查询速度。  
    索引的选择性是指索引列中不同值得数目与表中记录数的比,如果一个表中有2000条记录,表索引列有1980个不同的值,那么这个索引的选择性就是1980/2000=0.99.一个索引的选择性越接近于1,这个索引的效率就越高。

性能分析

1、MySQL Query Optimizer(查询优化器)
(1)、MySQL中有专门负责优化SELECT语句的优化器模块,主要功能:通过计算分析系统中收集到 的统计信息,为客户端请求的Query提供认为最优的执行
计划(它认为的最优的数据检索方式,但不见得是DBA认为是最优的)。
(2)、当客户端向MySQL请求一条Query,命令解析器模块完成请求分析,区别出是SELECT并转发给MySQL Query Optimizer时,MySQL Query Optimizer首先会对整条Query进行优化,处理掉一些常量表达式预算,直接换算成常量值。并对Query的查询条件进行简化和转换,去掉一条无用或者显而易见的条件、结构调整等。
2、MySQL常见瓶颈
(1)、CPU:CPU在饱和的时候一般发生在数据装入在内存或从磁盘上读取数据时候
(2)、IO:磁盘I/O瓶颈发生在装入数据远大于内存容量时;
(3)、服务器硬件的性能瓶颈:top,free,iostat和vmstat来查看系统的性能状态;

3、Explain

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

能干嘛?
表的读取顺序;
数据读取操作的操作类型;
哪些索引可以使用;
哪些索引被实际使用;
表之间的引用;
每张表有多少行被优化器查询;

怎么用?
Explain+SQL语句

image

获得:执行计划包含的信息
文章目录
  1. 1. 一、性能下降SQL慢 执行时间长 等待时间长
  2. 2. 二、常见的Join查询
  3. 3. 三、索引
  4. 4. 性能分析