随着我们的时间的推移,相关的数据表会变得越来越大;与此同时的数据库查询也会性能下降;执行时间变长…

可能出现的问题:

  • 数据过多
    – 这个我们得将数据进行分库分表
  • 关联了太多的表,太多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:
    Mysql索引优化分析(一站式)
    可以看到B+tree只有数据和向下的指针
  • 而Btree结构
    Mysql索引优化分析(一站式)
    Btree 的结构有数据和向下的指针和指向数据的指针;
  • 在同等内存的情况下比较,加载B+tree比加载Btree能多三分之一;多三分之一的话缺页率也会降低;因为内存有限,这些索引的磁盘块不是全部都加载进来的;多三分之一可以减少缺页率也就是减少I/O的次数;
  • 简单来说B+tree的优势是:
    1. B+树的磁盘读写代价更低 :B+树的内部结点并没有指向关键字具体信息的指针。因此其内部结点相对B 树更小。如果把所有同一内部结点的关键字存放在同一盘块中,那么盘块所能容纳的关键字数量也越多。一次性读入内存中的需要查找的关键字也就越多。相对来说IO读写次数也就降低了。
    1. 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:

Mysql索引优化分析(一站式)

  • 可以看到查询出来的有相关字段,首先我们得明白相关的字段:
  • 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

Mysql索引优化分析(一站式)

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

这些字段是对我们分析性能是十分的重要

相关文章: