mysql 索引

数据库索引是存储到磁盘的而我们又一般以使用磁盘I/O次数来评价索引结构的优劣。先从B-Tree分析,根据B-Tree的定义,可知检索一次最多需要访问h-1个节点(根节点常驻内存)。数据库系统的设计者巧妙利用了磁盘预读原理,将一个节点的大小设为等于一个页,这样每个节点只需要一次I/O就可以完全载入。为了达到这个目的,在实际实现B-Tree还需要使用如下技巧:每次新建节点时,直接申请一个页的空间,这样就保证一个节点物理上也存储在一个页里,加之计算机存储分配都是按页对齐的,就实现了一个node只需一次I/O

DB在执行一条Sql语句的时候,默认的方式是根据搜索条件进行全表扫描,遇到匹配条件的就加入搜索结果集合,添加索引的话,首先去索引列表中查询。

一、MYSQL索引算法:

HASH适合等值查找,不适合范围,不能排序
BTREE适合范围查找,无hash冲突

1)、BTree索引是最常用的mysql数据库索引算法,因为它不仅可以被用在=,>,>=,<,<=和between这些比较操作符上,而且还可以用于like操作符,只要它的查询条件是一个不以通配符开头的常量.

2)、Hash索引只能用于对等比较,例如=,<=>(相当于=)操作符。由于是一次定位数据,不像BTree索引需要从根节点到枝节点,最后才能访问到页节点这样多次IO访问,所以检索效率远高于BTree索引。 
但hash也有较多缺点,如:

①. Hash索引仅仅能满足“=”,“IN”,“<=>”查询,不能使用范围查询。 

② 联合索引中,Hash索引不能利用部分索引键查询。 
对于联合索引中的多个列,Hash是要么全部使用,要么全部不使用,并不支持BTree支持的联合索引的最优前缀,也就是联合索引的前面一个或几个索引键进行查询时,Hash索引无法被利用。 

③. Hash索引无法避免数据的排序操作 
由于Hash索引中存放的是经过Hash计算之后的Hash值,而且Hash值的大小关系并不一定和Hash运算前的键值完全一样,所以数据库无法利用索引的数据来避免任何排序运算。 

④. Hash索引任何时候都不能避免表扫描 
Hash索引是将索引键通过Hash运算之后,将Hash运算结果的Hash值和所对应的行指针信息存放于一个Hash表中,由于不同索引键存在相同Hash值,所以即使满足某个Hash键值的数据的记录条数,也无法从Hash索引中直接完成查询,还是要通过访问表中的实际数据进行比较,并得到相应的结果。 

⑤. Hash索引遇到大量Hash值相等的情况后性能并不一定会比BTree高 
对于选择性比较低的索引键,如果创建Hash索引,那么将会存在大量记录指针信息存于同一个Hash值相关联。这样要定位某一条记录时就会非常麻烦,会浪费多次表数据访问,而造成整体性能底下。

二、索引的优缺点

优点

提高查询效率
缺点降低了更新效率

三、 MySQL使用索引的场景

1) 快速查找符合where条件的记录

2) 快速确定候选集。若where条件使用了多个索引字段,则MySQL会优先使用能使候选记录集规模最小的那个索引,以便尽快淘汰不符合条件的记录。

3) 如果表中存在几个字段构成的联合索引,则查找记录时,这个联合索引的最左前缀匹配字段也会被自动作为索引来加速查找。
例如,若为某表创建了3个字段(c1, c2, c3)构成的联合索引,则(c1), (c1, c2), (c1, c2, c3)均会作为索引,(c2, c3)就不会被作为索引,而(c1, c3)其实只利用到c1索引。

4) 多表做join操作时会使用索引(如果参与join的字段在这些表中均建立了索引的话)

5) 若某字段已建立索引,求该字段的min()或max()时,MySQL会使用索引

6) 对建立了索引的字段做sort或group操作时,MySQL会使用索引

四、 哪些SQL语句会真正利用索引

1) B-Tree可被用于sql中对列做比较的表达式,如=, >, >=, <, <=及between操作

2) 若like语句的条件是不以通配符%开头的常量串,MySQL也会使用索引

3) 若已对名为col_name的列建了索引,则形如"col_name is null"的SQL会用到索引

4) 对于联合索引,sql条件中的最左前缀匹配字段会用到索引,示例请参考本文第2节第3条对联合索引的说明

5) 若sql语句中的where条件不只1个条件,则MySQL会进行Index Merge优化来缩小候选集范围

五、索引种类

唯一索引不允许任何两行具相同值
主键索引唯一索引的一种
聚集索引行的物理顺序和键值的索引顺序相同
普通索引无限制
全文索引针对较大的数据生成全文索引很耗时间空间
组合索引最左前缀原则:若对多列建立组合索引,若第二列未使用索引,则第三列也不会使用
聚集索引数据按索引顺序存储,节点存储的是真实数据
非聚集索引节点存储的是指向真正数据的指针

1.当你定义一个主键时,InnnodDB存储引擎则把它当做聚集索引

2.如果你没有定义一个主键,则InnoDB定位到第一个唯一索引,且该索引的所有列值均飞空的,则将其当做聚集索引。

3如果表没有主键或合适的唯一索引INNODB会产生一个隐藏的行ID值6字节的行ID聚集索引,

补充:由于实际的数据页只能按照一颗B+树进行排序,因此每张表只能有一个聚集索引,聚集索引对于主键的排序和范围查找非常有利,

二级索引:一个表中的所有索引除了聚集索引,其他的都是二级索引(secondary index)

辅助索引:其叶子节点并不包含行记录的全部数据,叶子结点除了包含键值以外,每个叶子结点中的索引行还包含了一个书签,该书签用来告诉存储引擎可以在哪找到相应的数据行,由于innodb引擎表是索引组织表,因此innodb存储引擎的辅助索引的书签就是相应行数据的聚集索引键,


六、使用索引注意点

最左前缀原理:

若为某表创建了3个字段(c1, c2, c3)构成的联合索引,则(c1), (c1, c2), (c1, c2, c3)均会作为索引,(c2, c3)就不会被作为索引,而(c1, c3)其实只利用到c1索引。

查询条件中含有函数或表达式:

很不幸,如果查询条件中含有函数或表达式,则MySQL不会为这列使用索引

范围查询:

范围列可以用到索引(必须是最左前缀),但是范围列后面的列无法用到索引。同时,索引最多用于一个范围列,因此如果查询条件中有两个范围列则无法全用到索引。

七、使用索引应该避免的点:

1、应尽量避免在 where 子句中对字段进行 null 值判断,否则将导致引擎放弃使用索引而进行全表扫描

2、当索引列有大量数据重复时,查询可能不会去利用索引,如一表中有字段sex,male、female几乎各一半,那么即使在sex上建了索引也对查询效率起不了作用

3、应尽可能的避免更新索引数据列,因为索引数据列的顺序就是表记录的物理存储顺序,一旦该列值改变将导致整个表记录的顺序的调整,会耗费相当大的资源

4、尽量使用数字型字段,若只含数值信息的字段尽量不要设计为字符型,这会降低查询和连接的性能,并会增加存储开销。这是因为引擎在处理查询和连接时会逐个比较字符串中每一个字符,而对于数字型而言只需要比较一次就够了

5、尽可能的使用 varchar/nvarchar 代替 char/nchar ,因为首先变长字段存储空间小,可以节省存储空间

6、MySQL 临时表在我们需要保存一些临时数据时是非常有用的。临时表只在当前连接可见,当关闭连接时,Mysql会自动删除表并释放所有空间。当需要重复引用大型表或常用表中的某个数据集时。临时表挺好的。但是,对于一次性事件,最好使用导出表,尽量使用表变量来代替临时表。

内容整理自:

https://www.2cto.com/database/201503/381295.html

https://blog.youkuaiyun.com/u011010851/article/details/80074550

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值