1. 索引

1.1优缺点:

优势:
提高数据检索的效率,降低数据库的IO成本。
通过索引列对数据进行排序,降低数据排序的成本,降低CPU的消耗。

劣势:
索引列也是要占用窄间的。
索引大大提高了查询效率,同时却也降低更新表的速度,
如对表进行:INSERT、UPDATE、DELETE时,效率降低。

1.2 索引底层结构

1.2.1 简介:

什么是索引

在数据之外,数据库还维护着满足特定查找算法的数据结构,这些数据结构以某种方式引用指向数据,这样就可以在这些数据结构上实现高效查找,这些数据结构就是索引。

简单来说索引的出现就是为了提高数据的查询效率,就像书的目录一样。在书籍中,用户不必翻阅完整个书就能根据目录迅速地找到所需要的信息。在数据库中,索引也允许数据库程序迅速地找到表中的数据,而不必扫描整个数据库。

1.2.2 索引的底层原理实现:

1.B+树

最常见的索引类型,大部分引擎都支持B+树索引

索引结构:

InnoDB 支持

MylSAM 支持

Memory 支持

2.R-Tree

空间索引是MyISAM引擎的一个特殊索引类型,主要用于地理空间数据类型,通常使用较少

索引结构:

InnoDB 不支持

MylSAM 支持

Memory 不支持

3.Full-text

是一种通过建立倒排索引,快速匹配文档的方式。类似于Lucene,Solr,ES

索引结构:

InnoDB 5.6之后版本支持

MylSAM 支持

Memory 不支持

4各个索引的优缺点:
4.1 二叉树缺点:

顺序插入时,会形成一个链表,查询性能大大降低。大数据量情况下,层级较深,检索速度慢。

4.2B-Tree(多路平衡查找树):

以一颗最大度数〈max-degree)为5(5阶)的b-tree为例(每个节点最多存储4个key,5个指针):
相对于B-Tree区别:

①.所有的数据都会出现在叶子节点
②.叶子节点形成一个单向链表

4.3MySQL索引数据结构对经典的B+Tree进行了优化。

在原B+Tree的基础上,增加一个指向相邻叶子节点的链表指针,就形成了带有顺序指针的B+Tree,提高区间访问的性能.

4.4Hash

Hash索引特点:

1.Hash索引只能用于对等比较(=,in),不支持范围查询(between, >, <,…)

2.无法利用索引完成排序操作

3.查询效率高,通常只需要一次检索就可以了,效率通常要高于B+tree索引

存储引擎支持:
在MySQL中,支持hash索引的是Memory引擎,而InnoDB中具有自适应hash功能,hash索引是存储引擎根据B+Tree索引在指定条件下自动构建的。

4.5为什么InnoDB存储引擎选择使用B+tree索引结构?

相对于二叉树,层级更少,搜索效率高;对于B-tree,无论是叶子节点还是非叶子节点,都会保存数据,这样导致一页中存储的键值减少,指针跟着减少,要同样保存大量数据,只能增加树的高度,导致性能降低;相对Hash索引,B+tree支持范围匹配及排序操作。

1.2 索引建立情形:

1.什么情况下适合建立索引

1)主键自动建立唯一索引

2)频繁作为查询条件的字段(where后面的字段)

3)查询中与其他表关联的字段(各种join on后面的字段)

4)单值/复合索引选择?(高并发下倾向选择复合索引)

5)查询中排序的字段

6)查询中统计或分组的字段

2. 什么情况下不适合建立索引

1)表数据太少

2)频繁更新的字段

3)where后面用不到的字段

1.3最左前缀原则

mysql建立多列索引(联合索引)有最左前缀的原则,即最左优先,如:

如果有一个2列的索引(col1,col2),则已经对(col1)、(col1,col2)上建立了索引;
如果有一个3列索引(col1,col2,col3),则已经对(col1)、(col1,col2)、(col1,col2,col3)上建立了索引;

1、b+树的数据项是复合的数据结构,比如(name,age,sex)的时候,b+树是按照从左到右的顺序来建立搜索树的,比如当(张三,20,F)这样的数据来检索的时候,b+树会优先比较name来确定下一步的所搜方向,如果name相同再依次比较age和sex,最后得到检索的数据;但当(20,F)这样的没有name的数据来的时候,b+树就不知道第一步该查哪个节点,因为建立搜索树的时候name就是第一个比较因子,必须要先根据name来搜索才能知道下一步去哪里查询。

2、比如当(张三,F)这样的数据来检索时,b+树可以用name来指定搜索方向,但下一个字段age的缺失,所以只能把名字等于张三的数据都找到,然后再匹配性别是F的数据了, 这个是非常重要的性质,即索引的最左匹配特性。(这种情况无法用到联合索引)

关于最左前缀的使用,有下面两条说明:

最左前缀匹配原则,非常重要的原则,mysql会一直向右匹配直到遇到范围查询(>、<、between、like)就停止匹配,比如a = 1 and b = 2 and c > 3 and d = 4 如果建立(a,b,c,d)顺序的索引,d是用不到索引的,如果建立(a,b,d,c)的索引则都可以用到,a,b,d的顺序可以任意调整。
=和in可以乱序,比如a = 1 and b = 2 and c = 3 建立(a,b,c)索引可以任意顺序,mysql的查询优化器会帮你优化成索引可以识别的形式

1.4 什么时候索引会失效

1)like以通配符开头(‘%abc’)会导致索引失效,违反最左前缀法则

2)在索引列上做任何操作(计算、函数、类型转换),会导致索引失效而转向全表扫描

3)存储引擎不能使用索引中范围条件右边的列,举例:select id,name from student where id > 50 and name = ‘张三’,会导致name索引失效

4)尽量使用覆盖索引,不要select *

5)MySQL在使用不等于(!=或<>)的时候无法使用索引会导致全表扫描,理由也很简单,B+Tree叶子节点用指针相连且是排好序的,这种数据结构只能解决有序的定值查询,像不等于这种无法利用索引查询。

6)IS NULL、IS NOT NULL无法使用索引,理由同上

7)字符串不加单引号索引失效

隐式转换–>函数操作

8)用or连接时会导致索引失效

1.5覆盖索引的定义与注意事项

如果一个索引覆盖(包含)了所有需要查询的字段的值,这个索引就是覆盖索引。因为索引中已经包含了要查询的字段的值,因此查询的时候直接返回索引中的字段值就可以了。不需要再到表中查询,避免了对主键索引的二次查询,也就提高了查询的效率。

覆盖索引的优点:
1,索引条目通常远小于数据行的大小,因为索引覆盖只需要读取索引,极大地减少了数据的访问量。
2.索引是按照列值顺序存储的,对于IO密集的范围查找会比随机从磁盘读取每一行数据的IO小很多。

3.一些存储引擎比如MyISAM在内存中只缓存索引,数据则依赖操作系统来缓存,因此要访问数据的话需要一次系统调用,使用覆盖索引则避免了这一点。

4.由于InnoDB的聚簇索引,覆盖索引对InnoDB引擎下的数据库表特别有用。因为InnoDB的二级索引在叶子节点中保存了行的主键值,如果二级索引能够覆盖查询,就避免了对主键索引的二次查询。

1.6 联合索引

又名复合索引,由两个或多个列的索引。它规定了mysql从左到右地使用索引字段,对字段的顺序有一定要求。一个查询可以只使用索引中的一部分,更准确地说是最左侧部分(最左优先)。如索引是key index (a,b,c). 可以支持a | a,b| a,b,c 3种组合进行查找,但不支持 b,c进行查找 .当最左侧字段是常量引用时,索引就十分有效。

1.7前缀索引

对于列的值较长,比如BLOB、TEXT、VARCHAR,就必须建立前缀索引,即将值的前一部分作为索引。这样既可以节约空间,又可以提高查询效率。但无法使用前缀索引做 ORDER BY 和 GROUP BY,也无法使用前缀索引做覆盖扫描。

2. 优化

1. 插入数据优化

insert 优化

  1. 批量插入
  2. 手动提交事务
  3. 主键顺序插入

大批量插入数据,如果一次性需要插入大批量数据,使用insert语句插入性能较低,此时可以使用MySQL数据库提供的load指令进行插入。

2. 主键优化

数据组织方式:

在InnoDB存储引擎中,表数据都是根据主键顺序组织存放的,这种存储方式的表称为索引组织表(index organized table IOT)。

页分裂:

页可以为空,也可以填充一半,也可以填充100%。

每个页包含了2-N行数据(如果一行数据多大,会行溢出),根据主键排列。

页合并:

当删除一行记录时,实际上记录并没有被物理删除,只是记录被标记
( flaged)为删除并且它的空间变得允许被其他记录声明使用。

当页中删除的记录达到MERGE_THRESHOLD(默认为页的5Q%)

lnnoDB会开始寻找最靠近的页(前或后)看看是否可以将两个页合并

主键设计原则:

满足业务需求的情况下,尽量降低主键的长度。

插入数据时,尽量选择顺序插入,选择使用AUTO_INCREMENT自增主键。

尽量不要使用UUID做主键或者是其他自然主键,如身份证号。

业务操作时,避免对主键的修改。

3. order by 优化

  1. Using flesort :通过表的索引或全表扫描,读取满足条件的数据行,然后在排序缓冲区sort buffer中完成排序操作,所有不是通过索引直接返回排序结果的排序都叫FileSort排序。
  2. Using index:通过有序索引顺序扫描直接返回有序数据,这种情况即为using index,不需要额外排序,操作效率高。

explain : 查看SQL表执行计划,查看索引方式。

注意:
根据排序字段建立合适的索引,多字段排序时,也遵循最左前缀法则。

尽量使用覆盖索引。

多字段排序,一个升序一个降序,此时需要注意联合索引在创建时的规则(ASC/DESC)。

如果不可避免的出现filesort,大数据量排序时,可以适当增大排序缓冲区大小 sort_buffer_size(默认256k)。

4. group by 优化

思路:
在分组操作时,可以通过索引来提高效率。

分组操作时,索引的使用也是满足最左前缀法则的。

5. limit 优化

优化思路:

一般分页查询时,通过创建覆盖索引能够比较好地提高性能,可以通过覆盖索引加子查询形式进行优化。

6. count优化

MyISAM引擎把一个表的总行数存在了磁盘上,因此执行count(*)的时候会直接返回这个数,效率很高;

InnoDB引擎就麻烦了,它执行count(*)的时候,需要把数据一行一行地从引擎里面读出来,然后累积计数。

优化思路:自己计数

7. update 优化

InnoDB的行锁是针对索引加的锁,不是针对记录加的锁,并且该索引不能失效,否则会从行锁升级为表锁。

所以,没有索引时,添加索引。然后进行修改即可