第一章 索引
1.什么是索引
提到索引,我们想到的是查询慢了设置索引呗!但是索引为什么起作用?设置了索引为什么还是慢我们其实不是很清楚。在关系数据中,索引是一种数据结构,他将数据提前按照一定的规侧进行排序和组织,能够帮助快速定位到数据记录的数据,加快数据库表中数据的查找和访问速度。像书籍的目录、文件夹、标签、房号…都可以帮助我们快速定位,都可以视为索引。能实现快速定位数据的一种存储结构,其设计思想是以空间换时间。
2.索引的种类
不同存储引擎不同的索引类型和实现
按照数据结构:B+ tree索引、Hash索引、full-text索引
按照物理存储:聚集索引、非聚集索引
按照字段特性:主键索引(PRIMARY KEY)、唯一索引(UNIQUE)、普通索引(INDEX)、全文索引(FULLTEXT)
按照字段个数:单列索引、联合索引(复合索引/组合索引)
3.按照数据结构分类索引
二叉树、红黑树、B树、B+树
区别:树的高度影响获取数据的性能(每一个树节点都是一次磁盘/O)
二叉树
特点:每个节点最多两个子节点,大在左,小在右,数据随机性情况下树杈越明显
如果数据是按顺序依次进入:
树的高度则会很高(就是一个链表结构),此时元素的查找效率就等于链表查询O(),数据检索效率将极为低下。
极端的情况下就是一个链表结构(如上图),此时元素的查找效率就等于链表查询O(n)
红黑树(平衡二叉树)
通过自旋平衡,子节点会自动分叉为2个分支,从而减少树的高度,当数据有序插入时比二叉树数据检索性能更佳。但是如果数据量过大,节点个数就越多,树高度也会增高(也就是树的深度越深),增加磁盘1/O次数,影响查询效率。
B-树
B树的出现可以解决树高度的问题。之所以是B树,而并不是名称中”XX二叉树",就是它不再限制一个父节点中只能有两个子节点,而是允许M个子节点(M>2)。不仅如此,B树的一个节点可以存储多个元素,相比较于前面的那些二叉树数据结构又将整体的树高度降低了。
最多有几个分支 -> 阶 一个节点最多存储 阶数-1
个数据,超出就会上升成父节点
mysql -> 16阶的B+树 -> 一个节点最多15个元素
对范围的查找支持比较差 -> 每次都回到根节点查找
B+-树
B+tree是在B树基础上的一种优化,其更适合做存储索引结构。在B+tree中,非叶子节点上仅存储键值,不存储数据;而所有数据记录均存储在叶子节点上,并且数据是按照顺序排列的。此外在B+tree中各个数据页之间是通过双向链表连接的,叶子节点中的数据是通过单向链表连接的。B+tree的结构图如下:
所有数据在叶子节点
非叶子节点不妨数据
叶子节点上有双向指针
Hash索引
Hash索引其实用的不多,最主要是因为最常见的存储引擎InnoDB不支持显示地创建Hash索引,只支持自适应Hash索引。虽然可以使用sql语句在InnoDB显示声明Hash索引,但是其实是不生效的。
对name字段建立Hash索引,但是通过show index from表名
就会发现实际还是B+树
在存储引擎中,Memory引擎支持Hash索引。Hash索引其实有点像Java中的HashMap底层的数据结构,他也有很多的槽,存的也是键
值对,键值为索引列,值为数据的这条数据的行指针,通过行指针就可以找到数据.
假设现在user表用Memory存储引擎,对name字段建立Hash索引,表中插入三条数据
Hash索引会对索引列name的值进行Hash计算,然后找到对应的槽下面,如下图所示
当遇到name字段的Hash值相同时,也就是Hash冲突,就会形成一个链表,比如有name=张三
有两条数据,就会形成一个链表。之后如果要查name=李四
的数据,只需要对李四进行Hash计算,找到对应的槽,遍历链表,取出name=李四
对应的行指针,然后根据行指针去查找对应的数据。
4.按照物理存储分类索引
按物理存储分类:InnoDB的存储方式是聚集索引,MyISAM 的存储方式是非聚集索引。
聚簇索引:数据本身和索引放在同一个文件中。
非聚簇索引:数据本身和索引放在不同的两个文件中。
4.1二级索引
除了主键的索引都是二级索引
在MySQL中,创建一张表时会默认为主键创建聚簇索引,B+树将表中所有的数据组织起来,即数据就是索引主键所以在InnoDB里,主键索引也被称为聚簇索引,索引的叶子节点存的是整行数据。而除了聚簇索引以外的所有索引都称为二级索引,二级索引的叶子节点内容是主键的值。
CREATE TABLE
users(id INT NOT NULL,name VARCHAR(20)NOT NULL,age INT NOT NULL,PRTMARY KEY(id)
)
#新建一个以age字段的二级索引:
ALTER TABLE users ADD INDEX(index age(age);
#MySQL会分别创建主键id的聚簇索引和age的二级索引:
4.2回表
讲完二级索引,接下来讲一讲如何使用二级索引查找数据。这里假设对name
字段创建了一个索引,并且表里就存了上面示例中的几条数据,例如执行下面这条sq则需要进行回表:
SELECT * FROM users WHERE age = 35;
由于查询条件是name=赵六
,所以会走name
索引,整个过程大致分为以下几个步骤:
从根节点开始,21<35
定位右边存储指针
在索叶子节点找到35的第一条记录,也就是id=9
的那条
由于是select*
,·还要查其它字段,此时就会根据id=9
到聚簇索引(主键索引)中查找其它字段数据,这个查找过程前面说了很多次了,这个根据id=4
到聚簇索引中查找数据的过程就被称为回表。
4.3回表的应用——覆盖索引
上一节说当执行select * from user where age=35;
这条sql的时候,会先从索引页中查出来age=35
对应的主键 id 之后再回表,到聚簇索引中查询其它字段的值,那么当执行下面这条sql,又会怎样呢?
select id from user where age 35;
所以还是跟前面一样了,先从索引页中查出来age=35
对应的主键 id 之后,惊讶的发现,sql 中需要查询字段的 id 值已经查到了,那此时压根就不需要回表了,已经查到 id 了,还回什么表。而这种需要查询的字段都在索引列中的情况就被称为覆盖索引,索引列覆盖了查询字段的意思。
当使用覆盖索引时会减少回表的次数,这样查询速度更快,性能更高。所以,在日常开发中,尽量不要select *
,需要什么查什么,如果出现覆盖索引的情况,查询会快很多。
4.4回表的优化——索引下推
索引下推( INDEX CONDITION PUSHDOWN,简称ICP ) 是在MySQL5.6针对扫描二级索引的一项优化改进。用来在范围查询时减少回表的次数。ICP 适用于 MYISAM 和 INNODB。
ALTER TABLE `test'.`user` ADDINDEX (`name`,`age`)
不使用索引下推实现:
每查一条就回表一次
使用索引下推实现
Explain SELECT * FROM user1 WHERE name LIKE `A%` and age = 40;
接下来执行如下的 sql:
select * from `user` where name > `王五` and age > 22;
在MySQL5.6(不包括5.6)之前,整个 sql 大致执行步骤如下:
1)先根据二分查找,定位到name>'王五'
的第一条数据,也就是id=4
的那个赵六
2)之后就会根据id=4
进行回表操作,到聚簇索引中查找id=4
其它字段的数据,然后判断数据中的age
是否大于22
,是的话就说
明是我们需要查找的数据,否则就不是
3)之后顺着链表,继续遍历,然后找到一条记录就回一次表,然后判断age
,如此反复下去,直至结束
所以对于图上所示,整个搜索过程会经历5
次回表操作,两个赵六
,两个刘七
,一个王九
,最后符合条件的也就是id=6
的赵六
那
条数据,其余age
不符和。
虽然这么执行没什么问题,但是不知有没有发现其实没必要进行那么多次回表,因为光从上面的索引图示就可以看出,符合name>'王五 ' and age>22
的数据就id=6
的赵六那条数据所以在MySQL5.6之后,对上面的age>22
判断逻辑进行了优化:
前面还是一样,定位查找到id=4
的那个赵六,之后就不回表来判断age
了,因为索引列有age
的值了,那么直接根据索引中age
判
断是否大于22
,如果大于的话,再回表查询剩余的字段数据(因为是select*
),然后再顺序链表遍历,直至结束所以这样优化之后,回表次数就成1
了,相比于前面的5
次,大大减少了回表的次数。而这个优化,就被称为索引下推,就是为了减少回表的次数。
之所以这个优化叫索引下推,其实是跟判断age > 22
逻辑执行的地方有关,这里就不过多赘述了。
4.5回表的优化——索引合并
索引合并 ( index merge ) 是从MySQL5.1开始引入的索引优化机制,在之前的 MySQL 版本中,一条 sql 多个查询条件只能使用一
个索引,但是引入了索引合并机制之后,MySQL在某些特殊的情况下会扫描多个索引,然后将扫描结果进行合并。
结果合并会为下面三种情况:
1)取交集(intersect)
2)取并集(union)
3)排序后取并集(sort-union)
为了不耽误演示,删除之前所有的索引,然后为name
和age
各自分别创建一个二级索引idx_name
和idx_age
取交集(intersect)
当执行下面这条sq就会出现取交集的情况
select * from `user` where name = `赵六` and age = 22;
查看执行计划
type
是index merge
,并且possible key
和key
都是idx name
和idx age
,说明使用了索引合并,并且Extra
有Using intersect(idx age,idx name)
,intersect
就是交集的意思。
整个过程大致是这样的,分别根据idⅸname
和idx age
取出对应的主键id
,之后将主键id
取交集,那么这部分交集的id
一定同时满
足查询ame='赵六' and age=22
的查询条件(仔细想想),之后再根据交集的id
回表。不过要想使用取交集的联合索引,需要满足各自索引查出来的主键id
是排好序的,这是为了方便可以快速的取交集。
比如下面这条sq就无法使用联合索引:
select * from `user`where name = `赵六` and age > 22;
只能用name
这个索引,因为age>22
查出来的id
是无序的,前面在讲索引的时候有说过索引列的排序规则,由此可以看出,使用联合索引条件还是比较苟刻的。
取并集(union)
取并集就是将前面例子中的and
换成or
select * from `user` where name = `赵六` or age > 22;
前面执行的情况都一样,根据条件到各自的索引上去查,之后对查询的取并集去重,之后再回表。同样地,取并集也要求各自索引查出来的主键id
是排好序的,如果查询条件换成age>22
时就无法使用取并集的索引合并。
排序后取并集(sort-union)
虽然取并集要求各自索引查出来的主键id
是排好序的,但是如果遇到没排好序的情况,mysql 会自动对这种情况进行优化,会先
对主键id
排序,然后再取并集,这种情况就叫排序后取并集(sort-union)。
比如上面提到的无法直接取并集的sql就符合排序后取并集(sort-union)这种情况
select from 'user' where name =` 赵六` or age > 22`;
5.按照字段个数分类索引
5.1单列索引
ALTER TABLE `test`.`user` ADD INDEX(`name`);
假设,我们现在对name
字段加了一个普通非唯一索引,那么name
就是索引列,同时name
这个索引也就是单列索引,此时如果往表中插入三条数据,那么name索引的叶子节点存的数据就如下图所示:
mysql会根据name字段的值进行排序,这里我假设张三排在李四前面,当索引列的值相同时,就会根据id排序,所以索引实际
上已经根据索引列的值排好序了。
这里肯定有小伙伴疑问,name
字段存储的中文也可以排序么?答案是可以的,并且 mysql 支持很多种排序规侧,我们在建数据库或是建表的时候等都可以指定排序规则,并且后面文章涉及到的字符串排序都是我随便排的,实际情况可能不一样。
对于单个索引列数据查找也是跟前面说的聚簇索引一样,也会对数据分组,之后可以根据二分查找在单个索引列来查找数据。当数据不断增多,一个索引页存储不下数据的时候,也会用多个索引页来存储,并且索引页直接也会形成双向链表。
当索引页不断增多时,为了方便在不同索引页中查找数据,也就会抽取一个索引页,除了存页中 id ,同时也会存储这个 id 对应索引列的值。
当数据越来越多越来越多,还会抽取,也会形成三层的一个B+树,这里我就不画了。
5.2联合索引
ALTER TABLE `test`.`use`r ADD INDEX(`name`,`ag`e,`id`);
除了单列索引,联合索引其实也是一样的,只不过索引页存的数据就多了一些索引列。比如,在name
和age
上建立一个联合索引,此时单个索引l页就如图所示:
先以name
排序,name
相同时再以age
排序,如果再有其它列,依次类推,最后再以id
排序。相比于只有name
一个字段的索引来说,索引页就多存了一个索引列。最后形成的B+树简化为如下图:
5.3最左前缀原则
顾名思义是最左优先,以最左边的为起点任何连续的索引都能匹配上。如果没有第一列的话,直接访问第二列,那第二列肯定是无序的,直接访问后面的列就用不到索引了当创建(a,b,c)复合索引时,想要索引生效的话,只能使用a
和ab
、ac
和abc
三种组合
面试问:使用acb
索引会不会生效?为什么(这个真被问过)。
第二章 优化
1.优化方法
上图所示的金字塔,从下往上列了4个查询的优化手段,依次是:SQL及索引优化、库表结构优化、系统配置优化、硬件优化。对于单个 MySQL 来讲,从下往上优化,成本是逐步提升的,但效果反而越来越差。通常来说,SQL及索引调优往往
不需要花费过多成本,却可以取到显著效果。
关于SQL优化方法,包括5点
1)创建索引减少扫描量;
2)调整索引减少计算量;
3)索引覆盖(减少不必访问的列,避免回表查询);
4)干预执行计划;
5)SQL改写;
2.通过Explain干预执行计划
3.SQL改写
准备工作
创建 student 表
创建 scores 表
添加索引
插入数据
3.1 避免使用SELECT *
查看执行计划,select *
走全表扫描,没有用到任何索引,查询效率非常低;查询列都是索引列那么这些列被称为覆盖索引。这种情况下查询的相关字段都能对索引,索引查询的效率相对较高。
通过show warnings
语句查看查询列*号替换成表所有字段。
总结:
查询时需要先将星号解析成表的所有字段然后在查询,增加查询解析器的成本;
select*
查询一般不走覆盖索引会产生大量的回表查询;
在实际应用中我们通常只需要使用某几个字段,其他不需要使用的字段也查出来浪费CPU、内存资源;
文本数据、大字段数据数据传输增加网络消耗。
3.2 小表驱动大表
小表驱动大表就是指用数据量较小、索引比较完备的表,然后使用其索引和条件对大表进行数据筛选,从而减少数据计算量,提高查询效率。比如说student
表有30条数据,scores
表有80w条数据。
Join Buffer
(连接缓冲区)是优化器用于处理连接查询操作时的临时缓冲区。简单来说当我们需要比较两个或多个表的数据进行join
操作时,Join Buffert
可以帮助 MySQL 临时存储结果,以减少磁盘读取和 CPU 负担,提高查询效率。需要注意的是每个join
都有一个单独的缓冲区。
Block nested-loop join
(BNL算法)会将驱动表数据加载到join buffer
里面,然后再批量与非驱动表进行匹配;如果驱动表数据量较大,join buffer
无法一次性装载驱动表的结果集,将会分阶段与被驱动表进行批量数据匹配,会增加被驱动表的扫描次数,从而降低查询效率。所以开发中要遵守小表驱动大表的原则。
分阶段匹配过程如下:
1)先把student表前15条数据读到join buffer中。
2)然后用scores表去匹配join buffer中的前15条。
3)记录下匹配结果。
4)清空join buffer。
5)再把student表后15条读取join buffert中。
6)然后用scores表去匹配join buffer中的后15条。
7)记录下匹配结果
3.3用连接查询代替子查询
mysql 需要在两张表以上获取数据的方式有两种:第一种通过连表查询获取,第二种通过子查询获取。
模拟一个真实场景,同样student
表有30条数据,scores
表有80w条数据,我们想查看学号小于15的学员各科分数信息:
因为子查询需要执行两次数据库查询,一次是外部查询,一次是嵌套子查询。因此,使用连接查询可以减少数据库查询的次数,提高查询的效率。
连接查间可以更好地利用数据库索引,提高查间的性能。子查间通常会使用临时表或内存表,而连接查询可以直接利用表上的索引。这意味着连接查间可以更快地访问表中的数据,减少查间的资源消耗。对于大型数据集,使用连接查询通常比使用子查询更高效。子查询通常需要扫描整个表,而连接查询可以利用索引加速读取操作。
使用连接查询可以更快地执行查间操作,减少数据库的负载,提高查询的性能和效率。
3.4提升GroupBy效率
创建索引:如果你使用group by
的列没有索引,那么查询可能会变得很慢。因此,可以创建一个或多个适当的索引来加速查询。
添加索引前:
添加索引后:
调整查询:查询的写法也会影响group by
的效率。可以尝试不使用子查询或临时表,或者可以使用JOIN
或EXISTS
来代替IN
子查询。
限制结果集的数量:如果你只需要查看一小部分结果,可以在查询中添加LIMIT
子句,以便只返回一定数量的结果。
3.5批量操作
批量插入或批量删除数据,比如说现在需要将1W+数据插入到数据库,大家是一条一条处理还是批量操作呢?建议是批量操作,逐个处理会频繁的与数据库交互,损耗性能。
反例:
在循环中逐条插入数据。
该操作需要多次请求数据库,才能完成这批数据的插入。
但众所周知,我们在代码中,每次远程请求数据库,是会消耗一定性能的。而如果我们的代码需要请求多次数据库,才能完成本次业务功能,势必会消耗更多的性能。那么如何优化呢?
正例:
提供一个批量插入数据的方法。
这样只需要远程请求一次数据库,Sq性能会得到提升,数据量越多,提升越大。但需要注意的是,不建议一次批量操作太多的数据,如果数据太多数据库响应也会很慢。批量操作需要把握一个度,建议每批数据尽量控制在500以内。如果数据多于500,则分多批次处理。
3.6使用limit
提高查询效率:一个查询返回成千上万的数据行,不仅占用了大量的系统资源,也会占用更多的网络带宽,影响查询效率。使用LIMIT
可以限制返回的数据行数,减轻了系统负担,提高了查询效率。
避免过度提取数据:对于大型数据库系统,从数据库中提取大量的数据可能会导致系统崩溃。使用LIMIT
可以限制提取的数据量,避免过度提取数据,保护系统不受影响。
优化分页查询:分页查询需要查询所有的数据才能进行分页处理,这会浪费大量的系统资源和时间。使用LIMIT
优化分页查询可以只查询需要的数据行,缩短查询时间,减少资源的浪费。
简化查询结果:有时我们只需要一小部分数据来得出决策,而不是整个数据集。使用LIMIT
可以使结果集更加精简和易于阅读和理解。
限制行数非常有用,因为它可以提高查询性能、减少处理需要的时间,并且只返回我们关心的列。
3.7用union all代替union
union all:获取所有数据但是数据不去重,包含重复数据;
union:获取所有数据且数据去重,不包含重复数据。
那么union all
与union
如果当然它业务数据容许出现重复的记录,我们更推荐使用union all
,因为union
去重数据需要遍历、排序和比较,它更耗时,更消耗CPU资源,但是数据结果最完整。
3.8join的表不宜过多
查间效率下降:多表JOIN
查间数据对比时间边长
系统负载增加:JOIN
操作需要进行大量的计算,因此会导致系统负载增加
维护难度加大:在一个连接了多个表的查间中,如果需要修改其中一个表的结构或内容,就可能会需要同时修改其他表的结构或内容。因此,在数据库设计时,应该尽量减少JOIN
操作的使用频率,并且简化表之间的关系,以提高查询效率和系统的性能。
除上述优化之外,通常在建表还需要注意以下内容:
控制索引数量
选择合理的字段类型
3.9总结
SQL优化是提高数据库性能的重要方法,在实际开发中我们的SQL要尽量遵守以下几点原则,避免留下技术债:
1.减少数据扫描
2.返回更少数据
3.减少交互次数
4.减少服务器CPU及内存开销
4.索引优化
示例:
4.1全值匹配
MySQL全值匹配是指在使用复合索引时,查询条件要包含索引的所有列,才能最大程度地利用索引。
查看索引长度是74=(3*24+2)
,可以算出联合索引中只使用了name
前缀索引。
查看索引长度是78=(3*24+2)+4
,可以算出联合索引中只使用了name
和age
前缀索引
查看索引长度是140=(3*24+2)+4+(3*20+2)
,可以算出联合索引中只使用了完整的联合索引
4.2最左前缀法则
如果索引了多列,要遵守最左前缀法则。指的是查询从索引的最左前列开始并且不跳过索引中的列。
一一带头大哥不能死,中间兄弟不能断:
4.3不在索引列上做操作
计算、函数、(自动o手动)类型转换,会导致索引失效而转向全表扫描
4.4存储引擎不能使用索引中范围条件右边的类
范围查间会使后面字段无序,造成部分索引失效——范围之后全失效
4.5尽量使用覆盖索引
只访问索引的查询(索引列包含查询列),减少select*
语句——覆盖索引不写星;
4.6不等、空值、NULL导致索引失效
mysql 在使用不等于 (!=或者<>),not in
、not exists
的时候无法使用索引会导致全表扫描。
<小于、>大于、<=、>=这些,mysql 内部优化器会根据检索比例、表大小等多个因素整体评估是否使用索引
is nul
l、is not null
一般情况下也无法使用索引
少用or
或in
,用它查询时,mysql 不一定使用索引,mysql 内部优化器会根据检索比例、表大小等多个因素整体评估是否使用索引,详见范围查询优化
4.7LIKE模糊查询
百分查询模糊条件放在最右(第一个都不确定不如给你全扫描)
问题:解决like%字符串%
索引不被使用的方法?
a-> 使用覆盖索引,查询字段必须是建立覆盖索引字段
b-> 如果不能使用覆盖索引则可能需要借助搜索引擎
4.8字符串不加单引号索引失效
触发了类型转换
4.9范围查询优化
给年龄添加单值索引
没走索引原因:mysql 内部优化器会根据检索比例、表大小等多个因素整体评估是否使用索引。比如这个例子,可能是由于单次数据量查询过大导致优化器最终选择不走索引
优化方法:可以将大的范围拆分成多个小范围
还原最初索引状态
10.总结
全值匹配我最爱,最左前缀要遵守;
带头大哥不能死,中间兄弟不能断:
索引列上少计算,范围之后全失效:
Like百分写最右,覆盖索引不写星;
不等空值还有「,索引失效要少用:
VAR引号不可丢,SQL高级也不难!
第三章 面试题(补充中)
面试题1:
B树和B+树的区别,MySQL为什么要选择B+树作为默认的数据结构
B+tree结构实现数据索引具有如下优点:
a.非叶子节点上可以存储更多的键值,相应的树的阶数(节点的子节点树)就会更大,树也就会变得更矮更胖。这样一来我们查找数据进行磁盘I/O的次数就会大大减少,数据查询的效率也会更快。
b.所有数据记录都有序存储在叶子节点上,就会使得范围查找,排序查找,分组查找以及去重查找变得异常简单。
C.数据页之间、数据记录之间都是通过链表链接的,有了这个结构的支持就可以方便的在数据查询后进行升序或者降序操作。
面试题2:
如果一个表没有主键索那还会创建B+树吗?
答案是会的!!!
InnoDB是MySQL中的一种存储引擎,它会为每个表创建一个主键索引。如果表没有明确的主键索引,InnoDB会使用一个隐藏的、自动生成的主键来创建索引。这个隐藏的主键索引使用的就是B+树结构。因此,在InnoDB中,即使表没有明确的主键索引l,也会创建一个B+树索引。
面试题3:
Hash索引优缺点
hash索引只能用于等值比较所以查询效率非常高
不支持范围查询,也不支持排序,因为索引列的分布是无序的
面试题4:
单列索引联合索引分别什么场景创建,优势是什么
联合索引的优势
1.减少开销:建一个联合索引(a,b,c),实际相当于建了(a)、(a,b)、(a,b,c) 三个索引。每多一个索引,都会增加写操作的开销和磁盘空间的开销对于大量数据的表,使用联合索引会大大的减少开销。
2.覆盖索引:对联合索引(a,b,c),如果有如下sql的select a,b,c from table where a='xxx'and b='xx'
,那么 mysql 可以直接通过遍历索引取得数据,而无需回表,这减少了很多的随机 io 操作。减少 io 操作,特别是随机 io 其实是 DBA 主要的优化策略。所以,在真正的实际应用中,覆盖索引是主要的提升性能的优化手段。
3.效率高:索引列多,通过联合索引筛选出的数据越少。
比如有1000w条数据的表,有如下sql:select col1,col2,col3 from table where col1=1 and col2=2 and col3=3;
假设每个条件可以筛选出10%的数据
A:如果只有单列索引,那么通过该索引能筛选出1000w*10%=100w
条数据,然后再回表从100w
条数据中找到符合col2=2 and col33=3
的数据,然后再排序,再分页,以此类推(递归);
B:如果是(col1,Col2,col3)
联合索引,通过三列索引筛选出1000w*10%*10%*10%=1w
,效率提升可想。
面试题5:
索引的优缺点,什么时候该用和不该用
优点:
1.提高检索效率
2.降低排序成本,索引对应的字段是会有一个自动排序功能的,默认是升序 asc。
它缺点是 :
1.创建索引和维护索引要耗费时间,这种时间随着数据量的增加而增加。
2,索引需要占用物理空间,数据量越大,占用空间越大
3,会降低表的增删改的效率,因为每次增删改索引,都需要进行动态维护
面试题6:
竟然索引有坏有好,什么时候需要索引,什么时候不需要?
适合:
1.较频繁的作为查询条件的字段应该创建索引
不适合:
1.字段值的唯一性太差不适合单独做索引
2.更新非常频繁的字段不适合
3.不会出现在where句中的字段不适合。
徐庶—MySQL调优实践最全!必懂!知识点一站式掌握 (yuque.com)
pwd:nfyq