Mysql
索引
索引介绍
1.索引是排好序的数据结构。他的目的是为了提升查询效率。
2.mysql存储引擎分为innodb和myisam。它是用来形容表的。
innodb支持事务、外键、行锁
myisam不支持事务、外键
3.myisam使用3个文件来存储每张表数据,每个文件名以表名开头,扩展名指出文件类型:
.frm 用于存储表的定义
.myd用于存放数据
.myi用户存放表索引
innodb存储引擎存储结构分为内存结构和磁盘结构。
innodb磁盘结构使用
.ibd存储业务表索引和数据。InnoDB Binary Data
.frm用于存储表的定义。
InnoDB 的表空间
表空间是一个抽象的概念,对于系统表空间来说,对应着文件系统中一个或多个实际文件,一般是(ibdata1);对于每个独立表空间(File-Per-Table Tablespaces)来说,对应着文件系统中一个名为表名.ibd 的实际文件。
ibdata1用于系统表空间文件,它用于存储InnoDB存储引擎的系统数据和表数据,比如数据字典、undo日志、事务数据、索引数据等等。这个文件在MySQL的启动时会被加载到内存中,并负责为InnoDB存储引擎的操作提供支持。
数据字典又称系统表,以SYS_开头。比如:SYS_TABLES、SYS_COLUMNS、SYS_INDEXES、SYS_FIELDS
4.因为.frm文件存储的是表结构定义数据,所以系统表元数据信息就是存储在.frm文件中?
(不是的,系统表元数据存储在ibdata1,而不是存在.frm)
其实不是的,系统表和.frm是不同的东西。InnoDB数据字典包括包含用于跟踪对象,如表,索引,和表中的列的元数据的内部系统表。元数据实际上位于InnoDB系统表空间中。由于历史原因,数据字典元数据在某种程度上与InnoDB表元数据文件(.frm文件)中存储的信息重叠。
5.innodb将数据和索引放在一起,也叫聚集索引。
而myisam叫非聚集索引。
这些数据存放的目录在my.ini中配置。
innodb将数据和索引放在一起,放在一起的话不是所以和数据都要一起加载,性能不是很差?
不是的,mysql加载数据的时候是按页进行加载的,页是其磁盘管理的最小单位。不会一次性加载所有的ibd文件数据。
6.JDK1.8以后的hashmap为什么在链表长度为8的时候变为红黑树?
在JDK1.8以及以后的版本中,hashmap的底层结构,由原来单纯的的数组+链表,更改为链表长度为8时,开始由链表转换为红黑树。
因为树结构占用空间比链表大,但是树结构查询和插入数据的效率比链表高。所以当节点数量大的时候,使用树结构存储比较合适。当节点数量小的时候,使用链表存储数据比较合适,因为节点数量少的时候,树结构查询效率相比链表体现不出优势。
那为什么选择8才会选择使用红黑树呢?
链表中节点数是8的概率已经接近千万分之一,此时哈希表的容量已经非常大,链表的性能已经很差了,所以此时需要把结构转为红黑树来提升性能。
也就是大部分情况下,hashmap还是使用的链表。
不是链表中节点>=8就会将数据结构转为红黑树,当数组长度小于MIN_TREEIFY_CAPACITY(64),会先扩容,当>=MIN_TREEIFY_CAPACITY(64),且链表长度>=8时才会转为红黑树。
7.oracle中不存在引擎的概念
Oracle数据库使用实例(Instance)来管理数据库的操作和资源。一个Oracle实例可以包含多个数据库,但是一个实例在任何时刻只能打开和操作一个数据库。
实例的功能和作用与其他数据库系统中的“引擎”类似,都是负责处理数据库请求并管理数据库的核心组件。
数据库是一组文件,那我们需要操作数据库,往里面写入和修改数据是怎么实现的呢?
Oracle的实例就充当了操作系统与数据库沟通交流的这个角色。
8.b+树与b树的区别
1.b+树非叶子节点不存储data,只存储索引(冗余,索引元素重复,即子节点会包含父节点的索引),可以放更多的索引。
2.b+树叶子节点包含所有字段 ,b树不包含
3.b+树叶子节点用指针连接(双向指针),提高区间访问的性能,b树叶子节点指针为空
b树非叶子节点也存储data,且所有索引元素不重复
b树索引为非冗余索引,所有的索引不会重复出现。而b+树会。
9.B+树的高度一般为1~3层,包括根节点、中间节点、叶子节点。每一个节点都是一个数据页,一个页默认会占用16KB的存储空间
10.在Mysql存储引擎中有页(Page)的概念,页是其磁盘管理的最小单位。
Mysql存储引擎中默认每个页的大小为16KB。
使用索引的时候Mysql只需要分配加载16k内存就能找出容量为2000多万条数据的数据库中的数据,而无需一次性加载所有数据导致占用更大的内存,从而可以减少内存的消耗。
11.所以,如果使用索引的时候,B+树高度按照3层来计算,一张表按理来说最多不超过2000万条数据,具体是怎么计算的?
索引b+树使用三层结构 1170117016>2000万
最后一层即叶子节点为保存数据。
根节点、中间节点每个索引数据结构包含:索引键、指向下一层节点的指针。
假设索引的字段为主键,主键的类型为bigint(占8个字节),每个指针占6个字节,则根节点和中间节点一页可以存放161024/(8+6)=1170个索引,如果叶子节点每条数据(数据包含多个字段)为1kb,则叶子节点每一页可以存放16kb/1kb=16条数据,这样3层数结构可以存放11701170*16>2000万条数据。这样2000万条数据只需通过3次查找既可以找到数据。
假设使用b树结构,如果要存储2000万条数据,则树的高度要远远大于3,因为非叶子节点也会存储数据,需要占用空间。
12.为什么建议innodb表必须建主键,并且推荐使用整型的自增主键?
整型索引占用空间小,且当出现树的再平衡的时候,自增整型主键比较效率较高。
使用自增索引>查找没有重复数据的列作为主键索引(unique index)>隐藏字段rowid作为主键索引
innodb表最终都会有主键索引,因为没有主键索引会自动帮我们创建主键索引。
一张表只有一个主键索引。
a.即innodb可以不建主键,如果不建主键的话mysql会帮我们找一列没有重复数据(唯一索引unique index)的列作为主键来当成索引,如果所有列都有重复,那么mysql会帮我们建一个隐藏字段rowid作为作为主键,所以为了不麻烦mysql,建议我们自己建主键。使用整型自增主键是因为其所占的存储空间和比较效率都比较好。
总的来说,mysql innodb下每张表都有聚簇索引,mysql在生成聚簇索引的时候,会先判断有无主键,如有有就用id来当作每个索引节点的key来生成聚簇索引,如果没有id就看有无唯一索引,有就用唯一索引来生成聚簇索引的key,如果也没有就会自动建一个隐藏rowid作为主键来当作索引key生成聚簇索引,除了聚簇索引,还有非聚簇索引(也叫二级索引,辅助索引),非聚簇索引只存放索引键值和主键索引键值,不存放所有行记录数据data。
比较效率,比如在插入数据的时候,会出现树的再平衡情况,怎么平衡就需要比较索引的大小,这时候如果使用自增整型的主键就比较好。
聚集索引效率相对高点。
b.索引分为主键索引和非主键索引
主键索引是聚簇索引,即叶子节点会包含整行所有列的数据。
而非主键索引为非聚簇索引(二级索引、辅助索引),他的叶子节点不会包含整行所有列值,只会包含主键索引键值。
13.mysql索引除了可以选b+树还可以选hash索引
hash索引不支持范围查找
14.联合索引(也叫关联索引)
联合主键,比如3个列作为联合主键,这数据库不会出现多条3个列相等的数据
15.from dual。dual为mysql的一张空表,主要是为了满足mysql的语法,在mysql优化时用到的占位表,以提高效率。
16.如果使用联合索引时,where后面的条件列打乱顺序的时候,会走索引,因为mysql在优化的时候会将顺序排序好。前提是要遵循最左前缀原则,该有的字段要有,不能少字段。
索引最佳实践
1.全值匹配
2.最左前缀法则
3.不在索引列上做任何操作(计算、函数、(自动or手动)类型转换),会导致索引失效而转向全表扫描
下面对hire_time索引进行处理,也会导致索引失败。
EXPLAIN select * from employees where date(hire_time) =‘2018‐09‐30’;
但是可以通过转换成下面语句,转化为日期范围查询,有可能会走索引:
EXPLAIN select * from employees where hire_time >=‘2018‐09‐30 00:00:00’ and hire_time <=‘2018‐09‐30 23:59:59’;
有可能会走索引,是因为mysql底层会判断,如果可能走全表扫描反而更快,这是会走全表扫描,而不是走索引。
4.存储引擎不能使用索引中范围条件右边的列。
(意思是范围条件后面的列不会走索引)
1 EXPLAIN SELECT * FROM employees WHERE name= ‘LiLei’ AND age = 22 AND position =‘manager’;
上面的position会走索引,但是下面的position不会走,因为其前面的age为范围查询
2 EXPLAIN SELECT * FROM employees WHERE name= ‘LiLei’ AND age > 22 AND position =‘manager’;
此时name、age会走索引,但是position要遍历name、age筛选后的结果集,不再从索引中找
5.尽量使用覆盖索引(只访问索引的查询(索引列包含查询列)),减少 select * 语句,要写具体的返回值。
6.mysql在使用不等于(!=或者<>),not in ,not exists 的时候无法使用索引会导致全表扫描
< 小于、 > 大于、 <=、>= 这些,mysql内部优化器会根据检索比例、表大小等多个因素整体评估是否使用索引
7.is null,is not null 一般情况下也无法使用索引
8.like以通配符开头(‘$abc…’)mysql索引失效会变成全表扫描操作
问题:解决like’%字符串%'索引不被使用的方法?
1.使用覆盖索引,查询字段必须是建立覆盖索引字段
2.如果不能使用覆盖索引则可能需要借助搜索引擎 比如es
9.少用or或in,用它查询时,mysql不一定使用索引,mysql内部优化器会根据检索比例、表大小等多个因素整体评
估是否使用索引,详见范围查询优化
10.范围查询优化
(意思是查询范围过大时,mysql会不走索引,所以为了走索引,我们可以将大范围拆分为多个小范围,这样就会走索引了,所以我们在单次查询数据量太大的时候,后端可以将范围查询进行拆分)
给年龄添加单值索引
ALTER TABLE employees
ADD INDEX idx_age
(age
) USING BTREE ;
1 explain select * from employees where age >=1 and age <=2000;
上面没走索引。
没走索引原因:mysql内部优化器会根据检索比例、表大小等多个因素整体评估是否使用索引。比如这个例子,可能是由于单次数据量查询过大导致优化器最终选择不走索引
优化方法:可以将大的范围拆分成多个小范围
1 explain select * from employees where age >=1 and age <=1000;
2 explain select * from employees where age >=1001 and age <=2000;
这样就会走索引了。
索引优化
18.是否走索引,不一定就是就是固定的,优化器要看具体情况,比如看sql扫描的数据量来大概推测扫描时间成本cost,来决定使不使用索引,可以使用trace工具来查看cost。算时间成本是估值而不是实际去执行sql后来计算cost。另外估值也不一定正确,如果你认为mysql预估是错的,你可以强制使用索引。
19.最左前缀原理,比如like之后的字段不会在索引查找(也不一定,看21),因为like之后的结果集的第二个字段(like后面的字段)不一定是有序的
20.in和or在表数据量比较大的情况会走索引,在表记录不多的情况下会选择全表扫描
21.但是like KK%不管表数据量大小,一般情况所有字段都会走索引,而不是只走like字段的索引,其它不走
(即like后面的一般会走索引,但其实也不一定,要看结果集的大小,like查找不一定就是这样的)
为什么呢?这里在5.6的时候引入了索引下推的概念。
a.索引下推(Index Condition Pushdown,ICP), like KK%其实就是用到了索引下推优化。
什么是索引下推?
对于辅助的联合索引(name,age,position),正常情况按照最左前缀原则,
SELECT * FROM employees WHERE name like ‘LiLei%’ AND age = 22 AND position =‘manager’ 这种情况,在MySQL5.6之前的版本,这个查询只会走name字段索引,然后在索引里匹配到名字是 ‘LiLei’ 开头的索引,然后拿这些索引对应的主键逐个回表,到主键索引上找出相应的记录,再比对age和position这两个字段的值是否符合。MySQL 5.6引入了索引下推优化,可以在索引遍历过程中,对索引中包含的所有字段先做判断,过滤掉不符合条件的记录之后再回表,可以有效的减少回表次数。使用了索引下推优化后,上面那个查询在联合索引里匹配到名字是 ‘LiLei’ 开头的索引之后,同时还会在索引里过滤age和position这两个字段,拿着过滤完剩下的索引对应的主键id再回表查整行数据。
b.按道理说>也会索引下推,但是实际不是这样,可能mysql底层觉得like ‘LiLei%’ 过滤后的结果集相对较少,在索引中比较age、position的性能影响较少。而>过滤后的结果集可能会比较大,其在索引中比较age、position的性能影响比较大,还不如直接回表查。所以这里Mysql选择给 like KK% 用了索引下推优化,而不给范围查询使用索引下推。当然这也不是绝对的,有时like KK% 也不一定就会走索引下推。
22.一般in之后使用order by 一般是不走索引的。
select * from employees where name in (‘Aoba’,‘Lisi’) order by age,position
因为从索引中找到的in(‘LiLei’,‘zhuge’)的结果集中,age、position不是有序的。
为什么不是有序的呢,因为in中使用了多个条件,这样结果集是无序的,即in中包含多个条件时算范围查询。范围查询后面的字段一般都不走索引。
比如过滤了Aoba,Lisi后,age返回的数据是 6 7 9 11 5 7 9 12这几条结果集,他们的结果不是无序。
23.索引优化总结一
1、MySQL支持两种方式的排序:filesort和index,Using index是指MySQL扫描索引本身完成排序。index效率高,filesort效率低。
2、order by满足两种情况会使用Using index。
- order by语句使用索引最左前列。
- 使用where子句与order by子句条件列组合满足索引最左前列。
3、尽量在索引列上完成排序,遵循索引建立(索引创建的顺序)时的最左前缀法则。
4、如果order by的条件不在索引列上,就会产生Using filesort。
5、能用覆盖索引尽量用覆盖索引
6、group by与order by很类似,其实质是先排序后分组,遵照索引创建顺序的最左前缀法则。对于group by的优化如果不需要排序的可以加上order by null禁止排序。注意,where高于having,能写在where中的限定条件就不要去having限定了。
group by 底层是先执行order by排序后再分组,如果不需要排序的可以加上order by null禁止排序。注意,where高于having,能写在where中的限定条件就不要去having限定了。
24.Using filesort文件排序原理
a.filesort文件排序方式
1.单路排序:是一次性取出满足条件行的所有字段,然后在sort buffer中进行排序;用trace工具可以看到sort_mode信息里显示< sort_key, additional_fields >或者< sort_key, packed_additional_fields >
2.双路排序(又叫回表排序模式):是首先根据相应的条件取出相应的排序字段和可以直接定位行数据的行 ID,然后在 sort buffer 中进行排序,排序完后需要再次取回其它需要的字段;用trace工具可以看到sort_mode信息里显示< sort_key, rowid >
判断使用哪种排序模式:MySQL 通过比较系统变量 max_length_for_sort_data(默认1024字节) 的大小和需要查询的字段总大小来判断使用哪种排序模式。
1.如果 字段的总长度小于max_length_for_sort_data ,那么使用 单路排序模式;
2.如果 字段的总长度大于max_length_for_sort_data ,那么使用 双路排序模∙式。
通过trace看走单路还是双路,看sort_mode。
b.文件排序filesort和索引排序index的区别(文件排序加载的是主键索引的所有data,而索引排序加载的是二级索引树)
索引排序index应用了索引树,只是将索引树加载到内存RAM。而filesort没有用到索引树,而是将整张表数据加载到内存RAM。
也就是说如果使用了innodb索引引擎,可能使用文件排序和索引排序。这两种排序都会用到ibd文件,ibd文件包含了主键索引
(聚簇索引,整张表的数据)和二级索引(比如联合索引)。只不过index加载的是二级索引树,而filesort加载的主键索引的所有data而不是索引树。
25.索引设计规则
1、代码先行,索引后上
2、联合索引尽量覆盖条件,尽量建联合索引
3、不要在小基数字段上建立索引
4、长字符串我们可以采用前缀索引
类似于 KEY index(name(20),age,position)。
5、where与order by冲突时优先where
在where和order by出现索引设计冲突时,到底是针对where去设计索引,还是针对order by设计索引?到底是让where去用上索引,还是让order by用上索引?
一般这种时候往往都是让where条件去使用索引来快速筛选出来一部分指定的数据,接着再进行排序。因为大多数情况基于索引进行where筛选往往可以最快速度筛选出你要的少部分数据,然后做排序的成本可能会小很多。
6、基于慢sql查询做优化
7、只为用于搜索、排序或分组的列创建索引
26.常见的分页场景优化技巧
1.根据自增且连续的主键排序的分页查询优化
得满足以下两个条件:
主键自增且连续
结果是按照主键排序的
2.根据非主键字段排序的分页查询优化
对于不连续主键分页的优化,且使用了order by name name为非主键且是联合索引的第一个字段
其实关键是让排序时返回的字段尽可能少,所以可以让排序和分页操作先查出主键,然后根据主键查到对应的记录,SQL改写如下:
mysql> select * from employees e inner join (select id from employees order by name limit 90000,5) ed on e.id = ed.id;
select id from employees order by name limit 90000,5这条语句虽说会先找90005条数据再舍弃90000条得到5条数据,但是它只是在二级索引树中(employees这里用了联合索引,非单索引)查找而不是聚簇索引(主键索引)。
原sql是这样的:
select * from employees limit 90000,5;
27.Join关联查询优化
(关联表太多的话,一般使用java代码实现业务代替sql实现业务)
a.驱动表:就是最先执行的表。
inner join中一般会优先选择小表做驱动表。所以使用 inner join 时,排在前面的表并不一定就是驱动表。
当使用left join时,左表是驱动表,右表是被驱动表,当使用right join时,右表时驱动表,左表是被驱动表
b.对于小表定义的明确:不是看原始表的数据大小,而是看过滤后的表的数据大小。
嵌套循环连接 Nested-Loop Join(NLJ) 算法
c.嵌套循环连接 Nested-Loop Join(NLJ) 算法
一次一行循环地从第一张表(称为驱动表)中读取行,在这行数据中取到关联字段,根据关联字段在另一张表(被驱动表)里取出满足条件的行,然后取出两张表的结果合集。
如果被驱动表t1的关联字段没索引,使用NLJ算法性能会比较低(下面有详细解释),mysql会选择Block Nested-Loop Join算法。
d.基于块的嵌套循环连接 Block Nested-Loop Join(BNL)算法
如果被驱动表t1的关联字段没索引,会使用这种算法。该算法是在内存判断而不是磁盘。
把驱动表的数据读入到 join_buffer 中,然后扫描被驱动表,把被驱动表每一行取出来跟 join_buffer 中的数据做对比。
Extra 中 的Using join buffer (Block Nested Loop)说明该关联查询使用的是 BNL 算法。
e.为什么被驱动表t1的关联字段没索引,就采用BNL算法?
(NLJ是磁盘扫描,BNL是内存扫描,内存扫描比磁盘扫描更快)
因为如果t1的关联字段没索引,那么读取的行数和比较的次数都是比较大的。NLJ是磁盘扫描,性能开销会比较大。而BNL提供了buffer,使用的是内存扫描,内存扫描更快。
f.关联sql的优化
1.关联字段加索引,让mysql做join操作时尽量选择NLJ算法
2.小表驱动大表
建议一条sql join表不超过3张,能不关联就不关联,要关联就要用上面优化规则进行优化。
28.in和exsits优化
a.原则:小表驱动大表,即小的数据集驱动大的数据集
b.in:当B表的数据集小于A表的数据集时,in优于exists
1 select * from A where id in (select id from B)
#等价于:
3 for(select id from B){
4 select * from A where A.id = B.id
5 }
c.exists:当A表的数据集小于B表的数据集时,exists优于in
将主查询A的数据,放到子查询B中做条件验证,根据验证结果(true或false)来决定主查询的数据是否保留
1 select * from A where exists (select 1 from B where B.id = A.id)
2 #等价于:
3 for(select * from A){
4 select * from B where B.id = A.id
5 }
6
7 #A表与B表的ID字段应建立索引
d.exists一般比较少用,能用join就用join
e.1、EXISTS (subquery)只返回TRUE或FALSE,因此子查询中的SELECT * 也可以用SELECT 1替换,官方说法是实际执行时会
忽略SELECT清单,因此没有区别
2、EXISTS子查询的实际执行过程可能经过了优化而不是我们理解上的逐条对比
3、EXISTS子查询往往也可以用JOIN来代替,何种最优需要具体问题具体分析
29.count()查询优化
(不需要用count(列名)或count(常量)来替代 count(),mysql并不会把全部字段取出来,而是专门做了优化,不取值,按行累加,效率很高)
a.需要临时关闭mysql查询缓存,为了查看sql多次执行的真实时间
navicat执行show variables like ‘%query%’;查看缓存是否开启
mysql> set global query_cache_size=0;
mysql> set global query_cache_type=0;
b.EXPLAIN select count(1) from jcwb_dayplan;
EXPLAIN select count(id) from jcwb_dayplan;
EXPLAIN select count(deptId) from jcwb_dayplan;
EXPLAIN select count() from jcwb_dayplan;
四个sql的执行计划一样,都使用了二级索引,说明这四个sql执行效率应该差不多。前提是有设置二级索引才行。
c.
1.字段有索引:count()≈count(1)>count(字段)>count(主键 id) //字段有索引,count(字段)统计走二级索引,二级索引存储数据比主键索引少,所以count(字段)>count(主键 id)
2.字段无索引:count()≈count(1)>count(主键 id)>count(字段) //字段没有索引count(字段)统计走不了索引,count(主键 id)还可以走主键索引,所以count(主键 id)>count(字段)
count(1)跟count(字段)执行过程类似,不过count(1)不需要取出字段统计,就用常量1做统计,count(字段)还需要取出字段,所以理论上count(1)比count(字段)会快一点。
count() 是例外,mysql并不会把全部字段取出来,而是专门做了优化,不取值,按行累加,效率很高,所以不需要用count(列名)或count(常量)来替代 count(*)。
d.
count(id)会优先选择二级索引,而不是主键索引。为什么对于count(id),mysql最终选择二级索引而不是主键聚集索引?因为二级索引相对主键索引存储数据更少,检索性能应该更高,mysql内部做了点优化(应该是在5.7版本才优化)。
e.
count(1)会自动选择其中一个索引来统计数量,优先选择二级索引,没有二级索引就选主键索引。
f.
但是不管哪种方式,大数据量的count查询还是会慢的,具体多大数据量,可能要几百上千万。
大数据量优化方式。
可以使用中间表
30.MRR
(回表优化,拿到所有索引排完序后再回表)
MRR:Disk-Sweep Multi-Range Read (MRR,多范围读取)
MRR:回表优化 ,就是说在拿到二级索引主键列后,不立即回表,等拿到所有主键列后对主键列先进行排序,然后统一进行回表,这样查询更快。因为回表操作是随机io,如果拿到一个主键列就回表的话效率就会慢一些,相当于拿一次主键列就加载一页数据。下一次即使拿到的数据还是在同一页的时候,也会加载一次页的数据到内存中查找。如果排好序后,就可以知道哪些列是在同一个页的,就可以一次查找出同一页的数据,这样会比较快一些。
31.倒排索引
(mysql倒排索引对全文检索支持不是很好,一般不用这个,一般用专门全文检索引擎,如Elastic)
用于全文检索
我们比较熟知的Elasticsearch、Solr等就是全文检索引擎,底层都是基于Apache Lucene的。
倒排索引就是,将文档中包含的关键字全部提取处理,然后再将关键字和文档之间的对应关系保存起来,最后再对关键字本身做索引排序。
32.什么是密集索引(如innodb聚簇索引)和稀疏索引(innodb二级索引,mysiam都是稀疏索引)?
(密集索引中叶子节点除了保存键值还保存其他列信息,而稀疏索引只包含键值信息和主键值)
密集索引的定义:叶子节点保存的不只是键值,还保存了位于同一行记录里的其他列的信息,由于密集索引决定了表的物理排列顺序,一个表只有一个物理排列顺序,所以一个表只能创建一个密集索引。
稀疏索引:叶子节点仅保存了键位信息以及该行数据的地址,有的稀疏索引只保存了键位信息机器主键。
mysam存储引擎,不管是主键索引,唯一键索引还是普通索引都是稀疏索引,innodb存储引擎:有且只有一个密集索引。
所以,密集索引就是innodb存储引擎里的聚簇索引,稀疏索引就是innodb存储引擎里的普通二级索引。
33.辨析覆盖索引/索引覆盖(这不是索引类型,而是一种索引优化方式)
覆盖索引:InnoDB存储引擎支持覆盖索引(covering index,或称索引覆盖),即从辅助索引中就可以得到查询的记录,而不需要查询聚集索引中的记录。记住,覆盖索引可以视为索引优化的一种方式,而并不是索引类型的一种。
除了覆盖索引这个概念外,在索引优化的范围内,还有前缀索引、三星索引等一系列概念,都会在我们后面的课程中学习到。
34.索引合并
(使用多个索引完成一次查询,mysql内部优化方式)
a.MySQL中使用到多个索引来完成一次查询的执行方法称之为:索引合并/index merge。
索引合并不是联合索引。
b.Intersection交集合并
MySQL在某些特定的情况下才可能会使用到Intersection索引合并,哪些情况呢?
情况一:等值匹配
情况二:主键列可以是范围匹配
上边说的情况一和情况二只是发生Intersection索引合并的必要条件,不是充分条件。也就是说即使情况一、情况二成立,也不
一定发生Intersection索引合并,这得看优化器的心情。优化器只有在单独根据搜索条件从某个二级索引中获取的记录数太多,
导致回表开销太大,而通过Intersection索引合并后需要回表的记录数大大减少时才会使用Intersection索引合并。
c.Union并集合并
(是OR关系)
d.Sort-Union合并
35.是否走索引,不一定就是按规则来,还要看结果集这些来,索引判断是否走索引,除了看规则,还得explain才知道。这是在优化器中根据具体情况具体分析确定的。