day1(2.19)
1. MySQL的索引类型有哪些?
MySQL里的索引就像是书的目录,能帮数据库快速找到你要的数据。以下是各种索引类型的通俗解释:
按数据结构分
- B+树索引:最常用的一种,数据像在一棵树上分层存放,能快速定位范围数据,比如查找某个分数区间内的学生成绩。
- 哈希索引:通过把数据变成哈希值来建立索引,查找速度特别快,但只适合精确查找,比如根据身份证号找特定的人,要是找某个范围的就不行了。
- 倒排索引(全文索引):主要用来处理文本数据,比如在一篇文章里找特定的词,它会记录每个词在哪些文档里出现过。
- R - 树索引:用于处理多维空间数据,比如地图上查找某个区域内的所有店铺。
基于InnoDB B+树索引分
- 聚簇索引:数据和索引是放在一起的,就像书的正文和目录装订在一起,一般主键会默认是聚簇索引,找数据时速度快。
- 非聚簇索引:数据和索引分开存放,就像书的正文和目录分开,查找到索引后还得再去查数据。
按索引性质分
- 普通索引:最基本的索引,用来加快查询速度,比如在学生表中给姓名字段建普通索引,查特定姓名的学生更快。
- 主键索引:特殊的唯一索引,每个表只能有一个,就像每个人的身份证号,不能重复且必须有,用来唯一标识一行数据。
- 联合索引:把多个字段组合起来建索引,比如在学生表中把班级和成绩两个字段建联合索引,查某个班级特定成绩范围的学生时会更高效。
- 唯一索引:保证索引列的值不能重复,但可以有NULL值,比如员工表中员工编号字段建唯一索引。
- 全文索引:上面按数据结构分的时候讲过,用于在文本中快速查找特定词汇。
- 空间索引:和R - 树索引类似,用于处理地理空间等数据,比如查找某个城市内的所有加油站。
2.MySQLInnoDB 引擎中的聚簇索引和非聚簇索引有什么区别?
聚簇索引
- “索引叶子结点存储的是数据行,可以直接访问完整数据”:就好比一本书,它的目录后面直接跟着对应的正文内容。在聚簇索引里,索引的最底层(叶子结点)存的不只是索引信息,而是整行的数据。所以当你通过聚簇索引去查找数据时,一下子就能拿到完整的一行数据,不用再去别的地方找。
- “每个表只能有一个聚簇索引,通常是主键索引,适合范围查询和排序”:每个表就像一本独特的书,只能有一份这种目录和正文紧密相连的结构,也就是只能有一个聚簇索引。一般情况下,主键就充当了这个聚簇索引,因为主键能唯一确定一行数据。如果要查找某个范围的数据,比如找成绩在80 - 90分之间的学生记录,或者要对数据进行排序,聚簇索引处理起来就比较高效,因为数据在物理存储上是按照一定顺序排列的。
非聚簇索引
- “索引叶子节点存储的是数据行的主键和对应的索引列,需通过主键才能访问完整的数据行”:非聚簇索引像是另外单独的一个小目录,这个小目录里记录的是数据行的主键信息以及对应的索引列信息。当你通过这个小目录找到对应的主键后,还得再去聚簇索引那里,根据主键把完整的数据行找出来,就好像你先在小目录里查到页码,还得去书的正文里找具体内容。
- “一个表可以有多个非聚簇索引(称之为非主键索引、辅助索引、二级索引),适用于快速查找特定列的数据”:一个表可以有很多个这样的小目录,也就是可以有多个非聚簇索引。当你只需要查找表中的某一个或几个特定列的数据时,用非聚簇索引就比较快。比如你只想查学生表中的学生姓名,在姓名字段上建了非聚簇索引的话,就能快速定位到这些姓名信息。
3. MySQL 的存储引擎有哪些?它们之间有什么区别?
InnoDB
- 支持事务、行级锁和外键:事务就像一个打包任务,要么全成功,要么全失败,比如转账时同时增减双方账户金额。行级锁是只锁定要处理的那一行数据,这样别人还能操作其他行,就像你在图书馆占一个座位,不妨碍别人坐其他座位。外键能把不同表的数据关联起来,比如学生表和成绩表通过学号关联。
- 提供高并发性能,适用于高负载的OLTP应用:可以同时处理很多人的操作请求,像银行系统很多人同时转账、查询等。
- 数据以聚集索引的方式存储,提高检索效率:数据存放方式让查找速度变快,就像书的目录和正文放一起,找内容方便。
MyISAM
- 不支持事务和外键,使用表级锁:没有事务打包功能,也不能关联不同表数据。表级锁是锁定整张表,就像你把整个图书馆占了,别人都不能用。
- 适合读取多、更新少的场景,如数据仓库:如果只是经常查数据,很少改数据,用它就挺好,像公司用来分析历史数据的数据仓库。
- 具有较高的读性能和较快的表级锁定:读数据速度快,锁定表也快。
MEMORY
- 数据存储在内存中,速度快,但数据在服务器重启后丢失:数据放在内存里,访问就像在眼前拿东西一样快。不过服务器一重启,内存里的数据就没了,就像电脑重启后没保存的临时文件没了。
- 适用于临时数据存储或快速缓存:比如存临时计算结果,或者做快速缓存来加快访问。
NDB (NDCluster)
- 支持高可用性和数据分布,适合大规模分布式应用:能保证服务一直可用,数据还能分散存,适合像大型电商平台那种大规模分布式系统。
- 提供行级锁和自动分区:行级锁不影响别人操作其他行,自动分区把数据分到不同地方存,提高性能。
ARCHIVE
- 用于存储大量历史数据,支持高效的插入和压缩:适合存公司多年的历史订单等大量历史数据,存数据快还能压缩节省空间。
- 不支持索引,适合日志数据存储:不能用索引快速查找,但存日志数据很合适,反正日志主要是按顺序记录。
day2(2.20)
1.MySQL 索引的最左前缀匹配原则是什么?
把 MySQL 索引想象成一本字典。字典前面有个目录,我们可以快速找到想要的字,MySQL 索引就和这目录类似,能帮数据库快速找到数据。最左前缀匹配原则,就像是查字典时按照顺序查一样。
联合索引就像多层目录
在 MySQL 里,如果我们给多个字段创建了联合索引,这就好比字典有个多层的目录。比如说,我们给一个表的姓、名这两个字段建了联合索引,这个联合索引就像是字典先按姓排了个顺序,在每个姓下面又按名排了顺序。
必须从最左边开始查找
最左前缀匹配原则要求我们查询的时候得从联合索引的最左边字段开始用。还拿姓和名的联合索引来说,如果我们只根据“名”去查,这个联合索引就帮不上忙了,因为索引是先按姓排的。只有先根据“姓”查,然后可能再根据“名”进一步缩小范围,索引才能发挥作用。
连续使用索引字段
再举个例子,如果联合索引是 (字段A, 字段B, 字段C) 。当我们查询条件是 “字段A = 某个值” 时,索引能用;当查询条件是 “字段A = 某个值 AND 字段B = 某个值” 时,索引也能用;当查询条件是 “字段A = 某个值 AND 字段B = 某个值 AND 字段C = 某个值” 时,索引还是能用。但要是查询条件是 “字段B = 某个值 AND 字段C = 某个值” ,没有最左边的字段A,索引就用不上了。而且查询时字段得连续用,要是查询条件是 “字段A = 某个值 AND 字段C = 某个值” ,跳过了字段B,那么索引也只能用到字段A,字段C那部分索引就不能用。
简单来说,最左前缀匹配原则就是在使用联合索引查询时,要从最左边的字段开始,按照顺序连续使用索引里的字段,这样索引才能高效地帮我们找到数据。
2.为什么 MySQL选择使用 B+树作为索引结构?
可以把 MySQL 里的数据想象成图书馆里的大量书籍,而索引就像是图书馆的目录,能让我们快速找到想要的书。MySQL 选择 B+树作为索引结构,主要有下面几个原因:
1. 查找效率高
B+树有个特点,它的所有数据都存放在叶子节点,而且叶子节点之间有指针相连,形成了一个有序链表。这就好比图书馆的目录,把同一类书按照编号排得整整齐齐。当我们要查找某条数据时,就像在目录里找对应的书编号,通过一层一层地比较节点上的值,能快速缩小查找范围,找到我们想要的数据。而且不管数据量有多大,查找的时间都比较稳定,不会因为数据变多就慢很多。
2. 适合范围查询
在实际应用中,我们经常需要查询某个范围内的数据,比如查询年龄在 20 到 30 岁之间的用户。B+树的叶子节点是有序的链表,这就方便极了。我们只要找到范围的起始点,然后顺着链表往后找,就能把这个范围内的数据都找出来。就像在图书馆目录里找到某一类书的起始编号,然后顺着编号顺序就能找到这一类里所有的书。
3. 磁盘读写性能好
数据库的数据通常存放在磁盘上,磁盘读写是比较耗时的操作。B+树的节点可以存储多个键值对,每个节点对应磁盘上的一个页。这样一来,一次磁盘读取能获取更多的数据,减少了磁盘 I/O 的次数。就好比我们去图书馆借书,一次能多拿几本,就不用来回跑那么多次了,效率自然就提高了。
4. 插入和删除操作稳定
在数据库里,数据是经常要进行插入和删除操作的。B+树在进行这些操作时,能通过节点的分裂和合并来保持树的平衡,不会因为频繁的插入和删除导致树的结构变得很混乱,影响查找效率。这就像图书馆的管理员,在不断地添加和拿走书籍后,还能把书架整理得井井有条,让我们还是能快速找到想要的书。
总的来说,B+树的这些优点让它很适合作为 MySQL 的索引结构,能让数据库在查找、插入、删除等操作上都有比较好的性能表现。
3.MySQL 三层 B+树能存多少数据?
要估算 MySQL 三层 B+ 树能存多少数据,我们需要先了解 B+ 树的结构特点,再分析每个节点大概能存储多少数据,最后得出三层 B+ 树的总存储量。
B+ 树结构基础
B+ 树是一种多路平衡查找树,在 MySQL 里,B+ 树的非叶子节点(索引节点)只存储索引信息,而数据都存放在叶子节点中。叶子节点之间通过指针相连,形成有序链表。我们可以把 B+ 树想象成一个多层的目录结构,非叶子节点是上层目录,叶子节点是最终存放具体内容的页面。
计算各层节点可存储的数据量
1. 假设前提
- 一个数据页的大小通常为 16KB(这是 MySQL InnoDB 存储引擎默认的数据页大小)。
- 非叶子节点(索引节点)主要存储索引键值和指向子节点的指针。假设一个索引键值和指针的组合大小为 8 字节(这只是为了方便计算做的假设,实际大小会因数据类型等因素而不同)。
- 叶子节点存储实际的数据记录,假设一条数据记录大小为 1KB(同样是假设值,实际大小取决于表结构)。
2. 计算非叶子节点可存储的子节点指针数量
由于一个数据页大小是 16KB(即 16 * 1024 = 16384 字节),一个索引键值和指针组合大小为 8 字节,那么一个非叶子节点能存储的子节点指针数量为:16384 ÷ 8 = 2048 个。
3. 分析三层 B+ 树的存储情况
- 第一层(根节点):根节点是一个非叶子节点,它能存储 2048 个指向第二层节点的指针。
- 第二层(中间层非叶子节点):每个第二层的非叶子节点同样能存储 2048 个指向第三层节点的指针。因为根节点有 2048 个指针指向第二层节点,所以第二层总共有 2048 个非叶子节点,那么第二层所有节点能指向的第三层节点数量为 2048 × 2048 个。
- 第三层(叶子节点):每个叶子节点存储实际的数据记录,假设一条记录大小为 1KB,一个叶子节点(数据页)能存储 16 条记录(16KB ÷ 1KB = 16)。由于第二层节点指向第三层的叶子节点数量为 2048 × 2048 个,所以三层 B+ 树能存储的数据记录总数为 2048 × 2048 × 16 = 67108864 条。(有待商榷,根据计算方式不同还有说是2千万条的)
需要注意的是,以上计算是基于假设的数据页大小、索引键值和指针大小以及数据记录大小得出的,实际情况中这些值会因表结构、数据类型等因素而有所不同,但通过这种方式能让你大致了解三层 B+ 树的存储量级。
day3(2.21)
1.在 MySQL 中建索引时需要注意哪些事项?
在 MySQL 里建索引就像是给书做目录,能让查找信息更快,但建的时候也有不少要留意的地方,需要有多重考虑:
考虑索引带来的开销成本
- 存储空间开销:索引会占用额外的磁盘空间。就好比书的目录越来越厚,书也会变得更厚一样。如果你给很多列都建索引,或者表的数据量特别大,那占用的空间就会很可观。所以别乱建索引,只给真正需要快速查找的列建。
- 插入、更新和删除变慢:每次往表里插入、更新或者删除数据时,MySQL 还得同时更新索引。这就像你往书里加了新内容,还得重新调整目录一样,会让这些操作变慢。所以对于那些经常需要更新数据的列,建索引就得谨慎点。
选好索引的列
- 选过滤性好的列:过滤性好的列,就是能让查询结果范围大大缩小的列。比如在一个员工表里,“部门”这个列可能就不如“员工编号”过滤性好。因为员工编号是唯一的,查起来一下子就能定位到具体的人;而部门可能有很多人,范围就大一些。所以优先给过滤性好的列建索引。
- 别给重复值多的列建索引:如果一个列里大部分值都是重复的,那建索引就没多大意义。比如一个“性别”列,就只有“男”和“女”两个值,建索引也不能让查询快多少。
组合索引的顺序很重要
- 最左前缀原则:如果你建的是组合索引,也就是给多个列一起建索引,那查询时要遵循最左前缀原则。就好比你查书的目录,得从最左边的标题开始查。比如你建了一个(A, B, C)的组合索引,那查询时只用 A,或者用 A 和 B,或者三个都用,索引才会生效;但如果只用 B 或者 C,索引就用不上了。
注意索引的维护
- 定期重建索引:随着数据的不断插入、更新和删除,索引可能会变得碎片化,就像书的目录被翻得乱七八糟,查找效率就会降低。这时候就需要定期重建索引,让它恢复“整齐”,提高查询效率。
2.MySQL中的回表是什么?
要理解MySQL中的回表,我们先得知道MySQL里数据是如何存储的,以及索引是干什么的。
在MySQL里,数据一般是存在磁盘上的一个个数据页里。为了能快速找到咱们想要的数据,就有了索引,索引就像是书的目录,能让咱们快速定位到数据的位置。
回表简单来说,就是在使用索引查找到数据所在的主键后,还得再通过这个主键去聚簇索引(可以理解为完整的数据存储结构)里把真正的数据给取出来。下面给你举个例子,假设咱们有一张员工表,表里有员工编号、姓名、年龄这些列,并且给员工编号建了索引。
有一天,你要查员工编号是100的员工的姓名。这时候,MySQL会先去员工编号的索引里找编号为100的记录,通过这个索引,它能很快定位到这个编号对应的主键。但是呢,这个索引里可能就只存了主键和员工编号这些信息,并没有姓名。所以,MySQL就得拿着这个主键,再去聚簇索引里把完整的员工记录找出来,这样才能拿到你想要的姓名信息。这个拿着主键再去聚簇索引里找数据的过程,就是回表。
回表会增加查询的时间,因为要多做一次查找操作。要是查询涉及到大量的回表,那查询效率就会明显下降。所以在设计表和写查询语句的时候,得尽量减少回表操作。
3.MySQL 中使用索引一定有效吗?如何排查索引效果?
索引不一定有效的原因
- 数据分布问题:如果列中数据重复性很高,比如“性别”列只有“男”“女”两种值,建立索引后过滤效果不佳,查询时可能不会走索引,全表扫描反而更高效。
- 查询条件不匹配:对于组合索引,若查询条件不满足最左前缀原则,索引无法有效利用。例如有组合索引 (col1, col2, col3),查询只涉及 col2 或 col3,索引就可能失效。
- 索引维护成本:当表数据频繁插入、更新、删除时,索引维护成本高,此时查询不一定能从索引中获益,甚至可能因索引维护影响性能。
排查索引效果的方法
- 查看执行计划:使用
EXPLAIN
语句,它能显示查询优化器如何执行查询,包括是否使用索引(key
字段显示使用的索引名称,若为NULL
则未使用索引)、索引类型、扫描行数等信息。例如EXPLAIN SELECT * FROM your_table WHERE your_column = 'value';
。 - 对比查询时间:分别在有索引和无索引的情况下执行相同查询,记录执行时间。可通过
SHOW PROFILE
语句获取更详细的查询执行时间信息,分析索引对查询速度的影响。 - 分析慢查询日志:开启 MySQL 的慢查询日志功能,它会记录执行时间超过指定阈值的查询语句。通过分析这些慢查询,找出未有效使用索引的语句,进一步优化。
day4(2.22)
1. MySQL 中的索引数量是否越多越好?为什么?
索引就像是书本的目录,能让我们快速找到想要的内容。在 MySQL 里,索引能帮助数据库更快地找到我们需要的数据。但索引数量并不是越多越好,原因主要如下:
- 占用存储空间:每创建一个索引,数据库都要额外的空间来保存这个索引的数据。就好比你每多做一份书本的目录,就得多用一些纸张。如果索引太多,会占用大量的硬盘空间,这不仅会增加成本,还可能导致磁盘空间不足。
- 插入、更新、删除操作变慢:当你往数据库里插入新数据,或者更新、删除已有的数据时,数据库不仅要处理这些数据本身,还要更新相关的索引。索引越多,更新索引的工作量就越大,这些操作的速度也就会变慢。就好像你在书本里添加、修改或者删除了一些内容,你得同时去修改好多份目录,这肯定会花更多时间。
- 维护成本高:随着数据的不断变化,索引也需要不断地维护。太多的索引会让数据库管理系统的负担加重,增加了维护的复杂性和成本。
2. 如何使用 MySQL 的 EXPLAIN 语句进行查询分析?
EXPLAIN
语句就像是一个“透视镜”,能让我们看到 MySQL 是如何执行一条 SQL 查询语句的。使用方法很简单,只需要在你要分析的 SELECT
语句前面加上 EXPLAIN
就可以了。
具体步骤和示例:
-- 假设我们有一个名为 users 的表,要查询 id 为 1 的用户信息
-- 正常的查询语句
SELECT * FROM users WHERE id = 1;-- 使用 EXPLAIN 分析这个查询语句
EXPLAIN SELECT * FROM users WHERE id = 1;
执行 EXPLAIN
语句后,MySQL 会返回一些关于查询执行的信息,这些信息包括:
- id:查询的序列号,用于标识查询中各个子查询的执行顺序。
- select_type:查询的类型,比如是简单查询、联合查询还是子查询等。
- table:查询涉及的表名。
- type:表示连接类型,它反映了查询使用索引的情况,这是评估查询性能的重要指标之一。
- possible_keys:可能使用的索引。
- key:实际使用的索引。
- key_len:使用的索引长度。
- ref:哪些列或常量被用于查找索引列上的值。
- rows:MySQL 估计为了找到所需数据而要读取的行数。
- Extra:一些额外的信息,比如是否使用了临时表、是否进行了文件排序等。
通过分析这些信息,我们可以了解查询的执行过程,判断是否使用了合适的索引,从而找出可能存在的性能问题。
3. MySQL 中如何进行 SQL 调优?
SQL 调优就是对 SQL 语句进行优化,让它执行得更快、更高效。
索引优化
- 创建合适的索引:根据查询条件和排序需求,在经常用于
WHERE
子句、JOIN
子句和ORDER BY
子句的列上创建索引。但要注意索引数量不要过多,前面已经说过原因啦。 - 避免使用不合理的索引:比如在选择性很低的列上创建索引,像性别列(只有男、女两种值),这样的索引对查询性能提升不大。
查询语句优化
- 避免使用
SELECT *
:只选择你需要的列,这样可以减少数据库读取和传输的数据量。 - 优化
WHERE
子句:尽量将过滤条件放在前面,避免使用OR
连接多个条件,因为这可能会导致索引失效。如果必须使用OR
,可以考虑使用UNION
来替代。 - 优化
JOIN
操作:确保JOIN
条件上有合适的索引,尽量使用INNER JOIN
而不是OUTER JOIN
,因为INNER JOIN
的性能通常更好。
数据库配置优化
- 调整
innodb_buffer_pool_size
:这个参数控制了 InnoDB 存储引擎用于缓存数据和索引的内存大小。适当增大这个值可以减少磁盘 I/O,提高查询性能。 - 调整
max_connections
:根据服务器的性能和实际需求,合理设置最大连接数,避免过多的连接导致服务器性能下降。
表结构优化
- 合理设计表的字段类型:选择合适的数据类型,比如使用
INT
而不是VARCHAR
来存储整数,这样可以减少存储空间,提高查询速度。 - 对大表进行分区:如果表的数据量非常大,可以考虑对表进行分区,将数据分散存储在不同的分区中,这样可以提高查询性能。