随着我们的时间的推移,相关的数据表会变得越来越大;与此同时的数据库查询也会性能下降;执行时间变长…
可能出现的问题:
- 数据过多
– 这个我们得将数据进行分库分表
- 关联了太多的表,太多join查询
– 需要进行SQL优化
- 没有充分利用到索引
– 索引建立==(1:mysql会自动创建主键索引;2:需要根据实际情况,创建索引)==
- 服务器调优及各个参数设置
– 调整my.cnf配置文件
身为程序员,我们工作上能够接触的可能也就是我们写的sql语句,对sql语句的优化可以说是相当必要的,优化得当效果是非常客观的,尤其是现在的大数据时代;
利用索引来优化我们的sql语句
索引是什么
- 1:MySQL官方对索引的定义为:索引(Index)是帮助MySQL高效获取数据的数据结构。
可以得到索引的本质:索引是数据结构。
- 1.1: 数据本身之外,数据库还维护着一个满足特定查找算法的数据结构,这些数据结构以某种方式指向数据,这样就可以在这些数据结构的基础上实现高级查找算法,这种数据结构就是索引。
- 1.2: 索引的目的在于提高查询效率,可以类比字典, 我们只要在字典的相关拼音就能查询到某个字的具体页数;我们可以简单理解为“排好序的快速查找数据结构”。
- 2:一般来说索引本身也很大,不可能全部存储在内存中,因此索引往往以索引文件的形式存储的磁盘上
索引的优势
- 类似大学图书馆建书目索引,提高数据检索的效率,降低数据库的IO成本
- 通过索引列对数据进行排序,降低数据排序的成本,降低了CPU的消耗
索引的劣势
- 虽然索引大大提高了查询速度,同时却会降低更新表的速度,如对表进行INSERT、UPDATE和DELETE;因为更新表时,MySQL不仅要保存数据,还要保存一下索引文件每次更新添加了索引列的字段,都会调整因为更新所带来的键值变化后的索引信息
- 实际上索引也是一张表,该表保存了主键与索引字段,并指向实体表的记录,所以索引列也是要占用空间的
mysql索引结构
- 平衡树B+tree和bBree mysql使用的是B+tree:

可以看到B+tree只有数据和向下的指针
- 而Btree结构

Btree 的结构有数据和向下的指针和指向数据的指针;
- 在同等内存的情况下比较,加载B+tree比加载Btree能多三分之一;多三分之一的话缺页率也会降低;因为内存有限,这些索引的磁盘块不是全部都加载进来的;多三分之一可以减少缺页率也就是减少I/O的次数;
- 简单来说B+tree的优势是:
-
- B+树的磁盘读写代价更低 :B+树的内部结点并没有指向关键字具体信息的指针。因此其内部结点相对B 树更小。如果把所有同一内部结点的关键字存放在同一盘块中,那么盘块所能容纳的关键字数量也越多。一次性读入内存中的需要查找的关键字也就越多。相对来说IO读写次数也就降低了。
-
- B+树的查询效率更加稳定:
由于非终结点并不是最终指向文件内容的结点,而只是叶子结点中关键字的索引。所以任何关键字的查找必须走一条从根结点到叶子结点的路。所有关键字查询的路径长度相同,导致每一个数据的查询效率相当。
索引的分类和基本语法:
基本语法
创建
- == CREATE [UNIQUE ] INDEX [indexName] ON table_name(column)) ==
删除
- DROP INDEX [indexName] ON mytable;
查看
- SHOW INDEX FROM table_name\G
使用ALTER命令
- ALTER TABLE tbl_name ADD PRIMARY KEY (column_list): 该语句添加一个主键,这意味着索引值必须是唯一的,且不能为NULL。
- 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 ,用于全文索引。
索引的分类
- 单值索引:即一个索引只包含单个列,一个表可以有多个单列索引
– CREATE INDEX idx_customer_name ON customer(customer_name);
- 唯一索引:索引列的值必须唯一,但允许有空值
– CREATE UNIQUEINDEX idx_customer_no ON customer(customer_no);
- 主键索引:设定为主键后数据库会自动建立索引,innodb为聚簇索引
– ALTER TABLE customer
add PRIMARY KEY customer(customer_no);
- 复合索引:即一个索引包含多个列
– CREATE INDEX idx_no_name ON customer(customer_no,customer_name);
哪些情况需要创建索引呢?
- 主键自动建立唯一索引
- 频繁作为查询条件的字段应该创建索引
- 查询中与其它表关联的字段,外键关系建立索引
- 单键/组合索引的选择问题, 组合索引性价比更高
- 查询中排序的字段,排序字段若通过索引去访问将大大提高排序速度
- 查询中统计或者分组字段(order和groud by :groud by 比较慢 groud by 包含order by ,先order by)
哪些情况需要创建索引呢?
表记录太少
经常增删改的表或者字段
Where条件里用不到的字段不创建索引
过滤性不好的不适合建索引(比如说性别,建了效果也不好)
Mysql对sql的性能分析工具Explain
使用EXPLAIN关键字可以模拟优化器执行SQL查询语句,从而知道MySQL是如何处理你的SQL语句的。分析你的查询语句或是表结构的性能瓶颈
能干嘛
- 表的读取顺序(id的顺序)
- 哪些索引可以使用
- 数据读取操作的操作类型
- 哪些索引被实际使用
- 表之间的引用
- 每张表有多少行被物理查询
使用方法:
Explain + SQL语句;
执行后出来的信息比如查看个查询语句sql:

- 可以看到查询出来的有相关字段,首先我们得明白相关的字段:
- id:id是select查询的***,包含一组数字,表示查询中执行select子句或操作表的顺序
– 三种情况:id相同,执行顺序由上至下;id不同,如果是子查询,id的序号会递增,id值越大优先级越高,越先被执行;id相同不同,同时存在
– 注意:id号每个号码,表示一趟独立的查询。一个sql 的查询趟数越少越好。
- select_type:查询的类型,主要是用于区别
普通查询、联合查询、子查询等的复杂查询
- table:显示这一行的数据是关于哪张表的
- partitions:代表分区表中的命中情况,非分区表,该项为null
-
type:显示查询使用了何种类型,
从最好到最差依次是:
system>const>eq_ref>ref>range>index>ALL

- possible_keys:显示可能应用在这张表中的索引,一个或多个。
查询涉及到的字段上若存在索引,则该索引将被列出,但不一定被查询实际使用
- key:实际使用的索引。如果为NULL,则没有使用索引,查询中若使用了覆盖索引,则该索引和查询的select字段重叠
- key_len: 表示索引中使用的字节数,可通过该列计算查询中使用(命中)的索引的长度。 key_len字段能够帮你检查是否充分的利用上了索引,越大代表命中越多,查询效率就越高
- ref:显示索引的哪一列被使用了,如果可能的话,是一个常数。哪些列或常量被用于查找索引列上的值
- ==rows:rows列显示MySQL认为它执行查询时必须检查的行数。==越少越好,因为是实际对物理表的查询
- filtered:这个字段表示存储引擎返回的数据在server层过滤后,剩下多少满足查询的记录数量的比例,注意是百分比,不是具体记录数
-
Extra(主要是看order by或者groud by,和关联查询有没有用上查询):包含不适合在其他列中显示但十分重要的额外信息
- 红色代表是效率底下,需要被优化;
这些字段是对我们分析性能是十分的重要
相关文章: