一文读懂Mysql索引

Mysql索引总结

定义

索引是存储引擎用于快速定位数据的一种数据结构。

聚集索引

聚集索引是指数据库表行中数据的物理顺序与键值的逻辑(索引)顺序相同。一个表只能有一个聚集索引,因为一个表的物理顺序只有一种情况,所以,对应的聚集索引只能有一个。如果某索引不是聚集索引,则表中的行物理顺序与索引顺序不匹配,与非聚集索引相同,聚集索引有着更快的检索速度。
主键可以作为聚集索引。
聚集索引是B+树索引。
直接在Clustered B+Tree上查询。

辅助索引

辅助索引(secondary index,也称二级索引),叶子节点并不包含行记录的全部数据,叶子节点除了包含键值以外,每个叶子节点中的索引行中还包含了一个书签。该书签用来告诉Innodb存储引擎哪里可以找到与索引相对应的行数据。由于Innodb存储引擎是索引组织表,因此Innodb存储引擎的辅助索引的书签就是相应行数据的聚集索引键。
在Secondary B+Tree上查询到主键,用主键在Clustered B+Tree定位列。

单列索引与联合索引

单列索引由单个字段组成。联合索引由多个字段组成。
联合索引字段整体有序,左前缀字段有序。
联合索引可代替左前缀字段的单列索引。
查询条件中联合索引的左前缀为确定值,此联合索引可优化第二个字段排序。

覆盖索引

如果一个索引包含所有要查询的字段的值,就称为“覆盖索引”。
索引是高效找到行的一个方法,但是一般数据库也能使用索引找到一个列的数据,因此它不必读取整个行。毕竟索引叶子节点存储了它们索引的数据;当能通过读取索引就可以得到想要的数据,那就不需要读取行了。一个索引包含了(或覆盖了)满足查询结果的数据就叫做覆盖索引。

什么情况用不到索引?

where条件中没有内容
否定条件:<>,not in,not exists
join中连接字段类型(或字符集)不一致 – 扫描内容超过全表的20%
where条件的字段存在函数运算
like ‘%name’
出现隐式字符类型转换

Explain命令

Explain命令用于分析sql查询效率。

查询结果如下所示:

           id: 1
  select_type: SIMPLE
        table: XXXXX
         type: range
possible_keys: idx_pre_xxx_status
          key: idx_pre_xxx_status
      key_len: 6
          ref: NULL
         rows: 308918
        Extra: Using index condition; Using where; Using filesort
1 row in set (0.25 sec)

每个字段的含义如下:

id:查询编号

select_type:

SIMPLE:简单查询
PRIMARY:最外层的select
SUBQUERY:子查询内层查询的第一个select
DERIVED:子查询派生表的select

table:表名
Type:

index:全索引扫描(全索引扫描,查询时,遍历索引树来获取数据行,如果数据不是密集的会产生随机IO)
const:通过主键访问
all:全表扫描(通过读物理表获取数据,顺序读磁盘上的文件,这种情况会顺序读磁盘上的文件)
range:表示索引范围扫描,对索引的扫描开始于一点,返回匹配值域的行,常见于between,<,>的查询
ref:为非唯一性索引扫描,返回匹配某个单独值的所有行,常见于非唯一索引即唯一索引的非唯一前缀进行的查找
eq_ref:索引扫描,唯一索引匹配值(唯一)
访问效率:const > eq_ref > ref > range > index > ALL

possible_keys:可能使用到的索引
key:最终使用的索引
key_len:索引长度(使用到的)
rows:扫描行数
Extra

Impossible WHERE noticed after reading const tables,Mysql优化器通过分析发现不可能存在结果。
Using index,所需要的数据只需要在Index 即可全部获得而不需要再到 表中取数据。
Using index for group-by,当Query 中使用了GROUP BY 或者DISTINCT 子句的时 候,如果分组字段也在索引中,Extra 中出现该信息。
Using filesort,Query 中包含ORDER BY ,且无法利用索引完成排序操 作的时候,MySQL Query Optimizer 不得不选择相应的 排序算法来实现。(并不一定代表磁盘排序)。
Using temporary,使用临时表时出现,主要常见于GROUP BY和ORDER BY等操作中。
Using where,不是读取表的所有数据,或者不是仅仅通过索引就可以获 取所有需要的数据,则会出现Using where信息。

查询优化

select count(*)不会统计每一列的值(不管是否为null),而是直接统计行数,效率要高些。
将select * 转换为具体的字段。
连接查询的join字段需要添加索引(on后面的字段)。
update/delete语句中的where条件字段同样需要设置索引。
where条件的顺序与索引是否使用无关。
Mysql不支持函数索引,计算类的工作放到程序中进行。
在选择性高区分度的字段上添加索引。
复合索引的建立需要进行仔细分析,尽量考虑用单字段索引代替。

正确选择复合索引中的主列字段,一般是选择性较好的字段。
复合索引的几个字段是否经常同时以AND方式出现在Where子句中?单字段查询是否极少甚至没有?如果是,则可以建立复合索引;否则考虑单字段索引。
如果复合索引所包含的字段超过3个,那么仔细考虑其必要性,考虑减少复合的字段。
如果既有单字段索引,又有这几个字段上的复合索引,一般可以删除复合索引。
频繁进行数据操作的表,不要建立太多的索引。
删除无用的索引,避免对执行计划造成负面影响。

Innodb与Myisam引擎的区别

  1. 区别:
    (1)事务处理:MyISAM是非事务安全型的,而InnoDB是事务安全型的(支持事务处理等高级处理)。
    (2)锁机制不同:MyISAM是表级锁,而InnoDB是行级锁。
    (3)select ,update ,insert ,delete 操作:
    MyISAM:如果执行大量的SELECT,MyISAM是更好的选择。
    InnoDB:如果你的数据执行大量的INSERT或UPDATE,出于性能方面的考虑,应该使用InnoDB表。
    (4)查询表的行数不同:
    MyISAM:select count() from table,MyISAM只要简单的读出保存好的行数,注意的是,当count()语句包含 where条件时,两种表的操作是一样的。
    InnoDB :InnoDB 中不保存表的具体行数,也就是说,执行select count(*) from table时,InnoDB要扫描一遍整个表来计算有多少行。
    (5)外键支持:Mysiam表不支持外键,而InnoDB支持。
  2. 为什么MyISAM会比Innodb的查询速度快。
    INNODB在做SELECT的时候,要维护的东西比MYISAM引擎多很多;
    (1)数据块,INNODB要缓存,MYISAM只缓存索引块,这中间还有换进换出的减少。
    (2)innodb寻址要映射到块,再到行,MYISAM 记录的直接是文件的OFFSET,定位比INNODB要快。
    (3)INNODB还需要维护MVCC一致;虽然你的场景没有,但他还是需要去检查和维护
    MVCC ( Multi-Version Concurrency Control )多版本并发控制 。
  3. 应用场景
    MyISAM适合:(1)做很多count 的计算;(2)插入不频繁,查询非常频繁;(3)没有事务。
    InnoDB适合:(1)可靠性要求比较高,或者要求事务;(2)表更新和查询都相当的频繁,并且行锁定的机会比较大的情况。

事物(Transaction)

事务是数据库管理系统执行过程中的一个逻辑单元,由一个有限的数据库操作序列构成。

事物ACID特性

原子性(Atomicity)、一致性(Consistency)、隔离性(Isolation)、持久性(Durability)
原子性:事务作为整体被执行,全部成功或失败。
一致性:数据库总是从一个一致性状态转换到另一个一致性状态。
隔离性:多事务并发执行时,一个事务不影响其他事务。
持久性:一旦事务提交,其所作修改就永远保存在数据库中。

一个完整的事务 ·

begin;
select balance from acct where user_id=13096;
update acct set banlance=banlance-5000 where user_id=13096;
update saving set banlance=banlance+5000 where user_id=13096;
commit;

其他

表字符集使用UTF8mb4支持emoji字符。

切记,一条慢sql在高并发的情况下,可以让数据库CPU耗尽,拖垮整站业务!!

where查询一定要加索引!!

你可能感兴趣的:(Java,DB,Java开发进阶)