文章目录
- 1. MySQL 支持哪些存储引擎?默认使⽤哪个?
- 2. MyISAM 和 InnoDB 有什么区别?
- 3. 事务的四大特性?
- 4. 并发事务带来了哪些问题?
- 5. 不可重复读和幻读有什么区别?
- 6. MySQL 事务隔离级别?默认是什么级别?
- 7. MySQL 的隔离级别是基于锁实现的吗?
- 8. InnoDB 对 MVCC 的具体实现
- 9. char 和 varchar 的区别是什么?
- 10. varchar(100)和 varchar(10)的区别是什么?
- 11. decimal 和 float/double 的区别是什么?存储⾦钱应该⽤哪⼀种?
- 12. 为什么索引能提高查询速度?
- 13. 为什么MySQL不建议使用NULL作为列默认值?
- 14. 聚集索引和非聚集索引的区别?非聚集索引⼀定回表查询吗?
- 15. 索引这么多优点,为什么不对表中的每一个列创建一个索引呢?(使用索引一定能提高查询性能吗?)
- 16. 索引底层的数据结构了解吗?Hash 索引和 B+树索引优劣分析
- 17. B+树做索引比红黑树好在哪里?
- 18. 最左前缀匹配原则了解吗?
- 19. 什么是覆盖索引?
- 20. 什么是回表?
- 21. 如何查看某条 SQL 语句是否用到了索引?
- 22. 表级锁和行级锁有什么区别?
- 23. 哪些操作会加表级锁?哪些操作会加行级锁?
- 24. MySQL中有哪些类型的锁?
- 25. 当前读和快照读有什么区别?
- 26. 乐观锁和悲观锁是什么?
- 27. MySQL自增主键一定是连续的吗?
- 28. MySQL 中常见的日志有哪些?
- 29. 数据库的三大范式是什么
- 30. 慢查询日志有什么用?
- 31. binlog 主要记录了什么?
- 32. binlog 和 redolog 有什么区别?
- 33. redolog 什么情况下会出现数据丢失
- 34. 如何保证redolog 和 binlog的一致性
- 35. undo log 如何保证事务的原子性?
- 36. binlog 有哪几种记录格式
- 37. 如何进行SQL调优
- 38. 如何实现读写分离?
- 39. 什么是MySQL的主从同步机制
- 40. 什么是分库分表
- 41. MySQL获取数据,是从磁盘读取的吗?
- 42. 什么情况下,不推荐为数据库建立索引?
- 43. 如何在MySQL中监控和优化慢SQL
内容参考:
https://javaguide.cn
、
https://t.zsxq.com/0bWeUrBVq
、
https://www.mianshiya.com
1. MySQL 支持哪些存储引擎?默认使⽤哪个?
MySQL 5.5.5 之前,MyISAM 是 MySQL 的默认存储引擎。5.5.5 版本之后,InnoDB 是 MySQL 的默认存储引擎。
MySQL支持的存储引擎中只有 InnoDB 是事务性存储引擎,也就是说只有 InnoDB 支持事务。
2. MyISAM 和 InnoDB 有什么区别?
-
InnoDB 支持行级别的锁粒度,MyISAM 不支持,只支持表级别的锁粒度。
-
MyISAM 不提供事务支持。InnoDB 提供事务支持,实现了 SQL 标准定义了四个隔离级别。
-
MyISAM 不支持外键,而 InnoDB 支持。
-
MyISAM 不支持 MVCC,而InnoDB 支持。
-
虽然 MyISAM 引擎和 InnoDB 引擎都是使用 B+Tree作为索引结构,但是两者的实现方式不太一样。
InnoDB 引擎中,其数据文件本身就是索引文件。相比 MyISAM,索引文件和数据文件是分离的,其表数据文件本身就是按 B+Tree 组织的一个索引结构,树的叶节点 data 域保存了完整的数据记录。
-
MyISAM 不支持数据库异常崩溃后的安全恢复,而 InnoDB 支持。
-
InnoDB 的性能比MyISAM 更强大。
3. 事务的四大特性?
原子性(Atomicity)
:事务是最小的执行单位,不允许分割。事务的原子性确保动作要么全部完成,要么完全不起作用;一致性(Consistency)
:执行事务前后,数据保持一致,例如转账业务中,无论事务是否成功,转账者和收款人的总额应该是不变的;隔离性(Isolation)
:并发访问数据库时,一个用户的事务不被其他事务所干扰,各并发事务之间数据库是独立的;持久性(Durability)
:一个事务被提交之后。它对数据库中数据的改变是持久的,即使数据库发生故障也不应该对其有任何影响。
只有保证了事务的持久性、原子性、隔离性之后,一致性才能得到保障。
4. 并发事务带来了哪些问题?
1) 脏读
事务A读取了事务B未提交的修改,随后事务B回滚,导致事务A读到的数据是无效的(“脏数据”)。
2) 丢失修改
在一个事务读取一个数据时,另外一个事务也访问了该数据,那么在第一个事务中修改了这个数据后,第二个事务也修改了这个数据。这样第一个事务内的修改结果就被丢失,因此称为丢失修改。
3) 不可重复读
事务A多次读取同一数据,期间事务B提交了修改,导致事务A两次读取结果不一致(针对已存在数据的修改)。
4) 幻读
幻读与不可重复读类似。它发生在一个事务读取了几行数据,接着另一个并发事务插入了一些数据时。在随后的查询中,第一个事务就会发现多了一些原本不存在的记录,就好像发生了幻觉一样,所以称为幻读。
例如:事务 2 读取某个范围的数据,事务 1 在这个范围插入了新的数据,事务 2 再次读取这个范围的数据发现相比于第一次读取的结果多了新的数据。
5. 不可重复读和幻读有什么区别?
对比维度 | 不可重复读 | 幻读 |
---|---|---|
操作对象 | 已存在的单行数据(值变化) | 满足条件的多行数据(行数变化) |
触发操作 | UPDATE、DELETE | INSERT、DELETE |
表现形式 | 同一行数据的值不同 | 结果集的行数不同 |
6. MySQL 事务隔离级别?默认是什么级别?
READ-UNCOMMITTED(读取未提交)
:最低的隔离级别,允许读取尚未提交的数据变更,可能会导致脏读、幻读或不可重复读。READ-COMMITTED(读取已提交)
:允许读取并发事务已经提交的数据,可以阻止脏读,但是幻读或不可重复读仍有可能发生。REPEATABLE-READ(可重复读)
默认
:对同一字段的多次读取结果都是一致的,除非数据是被本身事务自己所修改,可以阻止脏读和不可重复读,但幻读仍有可能发生。SERIALIZABLE(可串行化)
:最高的隔离级别,完全服从 ACID 的隔离级别。所有的事务依次逐个执行,这样事务之间就完全不可能产生干扰,也就是说,该级别可以防止脏读、不可重复读以及幻读。
隔离级别 | 脏读 | 不可重复读 | 幻读 |
---|---|---|---|
READ-UNCOMMITTED | √ | √ | √ |
READ-COMMITTED | × | √ | √ |
REPEATABLE-READ | × | × | √ |
SERIALIZABLE | × | × | × |
7. MySQL 的隔离级别是基于锁实现的吗?
是基于锁
和MVCC
共同实现的,MVCC主要是解决读和写两种操作之间的冲突,提高并发事务的处理速度
写与写之间的冲突还是要加锁来解决,只不过在不同的隔离级别下加的锁不同
读(普通的 select)和写之间的冲突在RC和RR隔离级别下依靠MVCC快照读
解决了
另一类 SELECT... FOR UPDATE
、SELECT ... LOCK IN SHARE MODE
在RU、RC会加行锁,在RR、S隔离级别加临键锁(Next-Key Lock,行锁 + 间隙锁)
SELECT... FOR UPDATE
的行锁是X锁,SELECT ... LOCK IN SHARE MODE
的行锁是S锁
这种是显式上锁的读(主要目的是显式上锁),都是当前读,UPDATE和DELETE都会隐式上锁,那为啥有隐式上锁还要有显式上锁呢?假设我们读取账号余额(必须保证读取的数据是最新的,在扣减余额的时候不能被其他事务影响),如果没有显示上锁,我们只能直接通过UPDATE/DELETE上锁,但是我都不知道账户余额够不够扣减的,直接执行UPDATE肯定不行,如果没有显示上锁,先通过普通select查询余额,发现余额够,然后去执行UPDATE,在这之间,余额被其他并发事务扣过一次了,结果当前事务在发现余额够的情况下扣减余额成负的了,这显然不合理
隔离级别 | 锁的参与 | MVCC 的参与 | 解决的问题 |
---|---|---|---|
读未提交(RU) | 写操作加排他锁,读操作无锁 | ❌ 不使用 | 无(脏读、不可重复读、幻读) |
读已提交(RC) | 写操作加排他锁 | ✅ 每次 SELECT 生成新快照 | 脏读 |
可重复读(RR) | 写操作加排他锁 + 间隙锁 | ✅ 使用事务开始时的快照 | 脏读、不可重复读、幻读(InnoDB) |
串行化(S) | 所有操作加共享锁/排他锁 | ❌ 不使用 | 所有并发问题(但性能差) |
8. InnoDB 对 MVCC 的具体实现
InnoDB 的 MVCC 通过隐藏字段(事务ID和回滚指针)、Undo Log 版本链和 Read View 实现读写并发控制。在内部实现中,InnoDB 通过数据行的 事务ID
和 Read View
来判断数据的可见性,如不可见,则通过数据行的 回滚指针
找到 undo log 中的历史版本。每个事务读到的数据版本可能是不一样的,在同一个事务中,用户只能看到该事务创建 Read View 之前已经提交的修改和该事务本身做的修改
9. char 和 varchar 的区别是什么?
主要区别:CHAR 是定长字符串,VARCHAR 是变长字符串。
CHAR 在存储时会在右边填充空格以达到指定的长度,检索时会去掉空格;
VARCHAR 在存储时需要使用 1 或 2 个额外字节记录字符串的长度,检索时不需要处理。
CHAR(M) 和 VARCHAR(M) 的 M 都代表能够保存的字符数的最大值,
无论是字母、数字还是中文,每个都只占用一个字符。
10. varchar(100)和 varchar(10)的区别是什么?
VARCHAR(100)和 VARCHAR(10)都是变长类型,表示能存储最多 100 个字符和 10 个字符。
VARCHAR(100)和 VARCHAR(10)能存储的字符范围不同,但二者存储相同的字符串,所占用磁盘的存储空间其实是一样的。
不过,VARCHAR(100) 会消耗更多的内存。这是因为 VARCHAR 类型在内存中操作时,通常会分配固定大小的内存块来保存值,即使用字符类型中定义的长度。
11. decimal 和 float/double 的区别是什么?存储⾦钱应该⽤哪⼀种?
DECIMAL 是定点数,FLOAT/DOUBLE 是浮点数。DECIMAL 可以存储精确的小数值,FLOAT/DOUBLE 只能存储近似的小数值。
DECIMAL 用于存储具有精度要求的小数,例如与货币相关的数据,可以避免浮点数带来的精度损失。
12. 为什么索引能提高查询速度?
无索引时
:数据库需要逐行扫描整个表(全表扫描),时间复杂度为 O(n)。
有索引时
:通过特定的数据结构(如 B+Tree)预先组织数据,查询时只需扫描索引结构(如 B+Tree 的高度通常很小),时间复杂度降低到 O(log n)。帮助数据库快速定位到目标数据的位置,避免全表扫描。例如,2000 万行数据的 B+Tree 索引可能只需 3-4 次磁盘 I/O 即可定位数据。
分析:每个数据页16KB,假设是聚簇索引,key和指针占16B(非叶节点),key和数据占1KB(叶节点),一个三层的B+树,可以存1000*1000*16条数据,定位这1600万条数据只需要3次IO
13. 为什么MySQL不建议使用NULL作为列默认值?
- 唯一索引(UNIQUE)允许多个NULL值(除非显式声明NOT NULL),可能导致逻辑歧义。
- 索引中的NULL值会降低查询效率。例如,WHERE column IS NULL可能无法有效利用索引,而NOT NULL列可通过索引直接定位数据。
- COUNT(column)会忽略NULL值,而COUNT(*)统计所有行。若列允许NULL,统计结果可能不符合预期。
- 在用=,!= 比较时,开发者需额外注意IS NULL/IS NOT NULL的用法,否则易引发逻辑错误。
14. 聚集索引和非聚集索引的区别?非聚集索引⼀定回表查询吗?
聚簇索引(聚集索引)
:索引结构和数据一起存放的索引,InnoDB 中的主键索引就属于聚簇索引。
非聚簇索引(非聚集索引)
:索引结构和数据分开存放的索引,二级索引(辅助索引)就属于非聚簇索引。二级索引的叶子节点存放的是主键,根据主键再回表查数据。
二级索引(辅助索引)属于非聚簇索引。MySQL 的 MyISAM 引擎,不管主键还是非主键,使用的都是非聚簇索引。
非聚簇索引不一定回表查询。如果要查询的数据正好是非聚簇索引的key,就无需回表查询。
聚簇索引和非聚簇索引的区别:
15. 索引这么多优点,为什么不对表中的每一个列创建一个索引呢?(使用索引一定能提高查询性能吗?)
大多数情况下,索引查询都是比全表扫描要快的。但是如果数据库的数据量不大,那么使用索引也不一定能够带来很大提升。因为:
- 创建和维护索引需要耗费许多时间。当对表中的数据进行增删改的时候,如果数据有索引,那么索引也需要动态地修改,这会降低 SQL 执行效率。
- 索引需要使用物理文件存储,也会耗费一定空间。
16. 索引底层的数据结构了解吗?Hash 索引和 B+树索引优劣分析
索引的底层数据结构通常有两种常见实现:B+树和哈希表。
B+树是一种多路平衡查找树,它的内部节点仅存储键值和指向子节点的指针,而叶子节点存储实际数据或指向数据的指针,叶子节点之间通过链表连接,这使得B+树天然支持高效的范围查询和顺序访问。比如数据库中的范围查询(如WHERE age > 20)或排序操作(ORDER BY)可以直接通过遍历叶子节点的链表完成,同时B+树的树高较低,能减少磁盘I/O次数,非常适合磁盘存储的场景,这也是为什么像MySQL的InnoDB引擎默认使用B+树索引的原因。
而哈希索引基于哈希表实现,通过哈希函数将键值映射到固定桶中,理想情况下查询时间复杂度为O(1),等值查询(如WHERE id = 123)非常高效。但它不支持范围查询,因为数据是无序存储的,例如WHERE age BETWEEN 10 AND 20需要全表扫描。
17. B+树做索引比红黑树好在哪里?
B+树通过多路平衡结构(每个节点可容纳大量键值)大幅降低树高,使得百万级数据仅需3-4层即可覆盖,显著减少磁盘I/O次数;其叶子节点形成有序链表,使得范围查询无需回溯中间节点即可线性遍历,而红黑树作为二叉树在相同数据量下树高更高且范围查询需复杂遍历。同时,B+树的节点大小与磁盘页对齐,单次I/O能加载更多有效数据,且插入/删除操作引发的节点分裂合并具有更好的局部性,减少了随机磁盘访问,而红黑树的旋转操作可能导致分散的磁盘写入(因为要修改父节点或者兄弟节点的指针,他们的数据可能存在不同的数据块中,要分散读取到内存中)。
18. 最左前缀匹配原则了解吗?
最左前缀匹配原则指的是在使用联合索引时,MySQL 会根据索引中的字段顺序,从左到右依次匹配查询条件中的字段。如果查询条件与索引中的最左侧字段相匹配,那么 MySQL 就会使用索引来过滤数据,这样可以提高查询效率。
最左匹配原则会一直向右匹配,直到遇到范围查询(如 >、<)为止。对于 >=、<=、BETWEEN 以及前缀匹配 LIKE 的范围查询,不会停止匹配
19. 什么是覆盖索引?
如果一个索引包含(或者说覆盖)所有需要查询的字段的值,我们就称之为 覆盖索引。覆盖索引即需要查询的字段正好是索引的字段,那么直接根据该索引,就可以查到数据了,而无需回表查询。
20. 什么是回表?
在 InnoDB 存储引擎中,非主键索引的叶子节点包含的是主键的值。这意味着,当使用非主键索引进行查询时,数据库会先找到对应的主键值,然后再通过主键索引来定位和检索完整的行数据。这个过程被称为“回表”。
21. 如何查看某条 SQL 语句是否用到了索引?
我们可以使用 EXPLAIN 命令来分析 SQL 的 执行计划 ,这样就知道语句是否命中索引了。执行计划是指一条 SQL 语句在经过 MySQL 查询优化器的优化会后,具体的执行方式。EXPLAIN 并不会真的去执行相关的语句,而是通过 查询优化器 对语句进行分析,找出最优的查询方案,并显示对应的信息。
22. 表级锁和行级锁有什么区别?
表级锁
: MySQL 中锁定粒度最大的一种锁(全局锁除外),一般是用来针对非索引字段加的锁,对当前操作的整张表加锁,实现简单,资源消耗也比较少,加锁快,不会出现死锁。不过,触发锁冲突的概率最高,高并发下效率极低。表级锁和存储引擎无关,MyISAM 和 InnoDB 引擎都支持表级锁。
行级锁
: MySQL 中锁定粒度最小的一种锁,一般是针对索引字段加的锁 ,只针对当前操作的行记录进行加锁。 行级锁能大大减少数据库操作的冲突。其加锁粒度最小,并发度高,但加锁的开销也最大,加锁慢,会出现死锁。行级锁和存储引擎有关,是在存储引擎层面实现的。
23. 哪些操作会加表级锁?哪些操作会加行级锁?
表级锁
:
- DDL 操作
修改表结构时(如 ALTER TABLE、DROP TABLE、TRUNCATE TABLE)会加表级锁。 - 显式锁表
使用 LOCK TABLES 命令显式锁定表。 - MyISAM 引擎的读写
MyISAM 默认对写操作加表级排他锁,读操作加表级共享锁。 - 无索引的更新(InnoDB 锁升级)
如果 UPDATE/DELETE 未使用索引,InnoDB 可能升级为表级锁。
行级锁
:
- 事务中的写操作(InnoDB)
UPDATE、DELETE 默认对符合条件的行加排他锁(X 锁)。 - 显式行级锁查询
SELECT … FOR UPDATE 加排他锁,SELECT … LOCK IN SHARE MODE 加共享锁。
24. MySQL中有哪些类型的锁?
行级锁
:仅对特定的行加锁,允许其他事务并发访问不同的行,适用于高并发场景。
表级锁
:对整个表加锁,其他事务无法对该表进行任何读写操作,适用于需要保证完整性的小型表。
共享锁
:允许多个事务并发读取同一资源,但不允许修改。只有在释放共享锁后,其他事务才能获得排它锁。
排他锁
:只允许一个事务对资源进行读写,其他事务在获得排它锁之前无法访问该资源。
间隙锁
:针对索引中两个记录之间的间隙加锁,防止其他事务在这个间隙中插入新记录,以避免幻读。间隙锁不锁定具体行,而是锁定行与行之间的空间。
临键锁
:是行级锁和间隙锁的结合,锁定具体行和其前面的间隙,确保在一个范围内不会出现幻读。常用于支持可重复读的隔离级别。
意向锁
:一种表锁,用于表示某个事务对某行数据加锁的意图,分为意向共享锁(IS)和意向排它锁(IX),主要用于行级锁与表级锁的结合。
插入意向锁
:一种特殊的间隙锁(Gap Lock),允许不同事务在同一个间隙的不同位置并发插入数据,从而减少锁冲突。
25. 当前读和快照读有什么区别?
主要区别就是在于读的时候锁不锁定
快照读(一致性非锁定读)
就是普通的 SELECT 语句
只有在事务隔离级别 RC(读取已提交) 和 RR(可重读)下,InnoDB 才会使用一致性非锁定读:
- 在 RC 级别下,对于快照数据,一致性非锁定读总是读取被锁定行的最新一份快照数据。
- 在 RR 级别下,对于快照数据,一致性非锁定读总是读取本事务开始时的行数据版本。
当前读 (一致性锁定读)
就是给行记录加 X 锁或 S 锁
# 对读的记录加一个X锁
SELECT...FOR UPDATE
# 对读的记录加一个S锁
SELECT...LOCK IN SHARE MODE#(旧版,已弃用)
# 对读的记录加一个S锁
SELECT...FOR SHARE#(新版)
# 对修改的记录加一个X锁
INSERT...
UPDATE...
DELETE...
26. 乐观锁和悲观锁是什么?
悲观锁
:
假设并发冲突一定会发生,因此在操作数据前先加锁,确保操作过程中数据不会被其他事务修改。
实现方式
- 数据库内置锁机制:如行锁、表锁、共享锁(S锁)、排他锁(X锁)。
乐观锁
假设并发冲突很少发生,因此不加锁直接操作数据,仅在提交时检查数据是否被修改。若冲突则重试或报错。
实现方式
- 版本号机制:通过版本号或时间戳标记数据版本。
- CAS(Compare and Swap):原子操作更新数据前检查当前值是否符合预期。
27. MySQL自增主键一定是连续的吗?
详细分析:https://javaguide.cn/database/mysql/mysql-auto-increment-primary-key-continuous.html
不一定,在以下情况可能不连续:
- 自增初始值和自增步长设置不为 1
- 唯一键冲突
- 事务回滚
- 批量插入(如 insert…select 语句)
28. MySQL 中常见的日志有哪些?
MySQL中常见的日志主要包括错误日志、通用查询日志、慢查询日志、二进制日志(Binlog)
、事务日志(Redo Log 和 Undo Log)
、中继日志以及DDL日志。
二进制日志(Binlog)记录了所有对数据的修改操作,支持主从复制和数据恢复,是实现高可用架构的基础。
事务日志中的Redo Log确保事务的持久性,崩溃恢复时重放未落盘的操作,而Undo Log保存事务前的数据快照,支持回滚和MVCC机制。
29. 数据库的三大范式是什么
- 1NF(第一范式):属性不可再分。
- 2NF(第二范式):2NF 在 1NF 的基础之上,消除了非主属性对于码的部分函数依赖。
- 3NF(第三范式):3NF 在 2NF 的基础之上,消除了非主属性对于码的传递函数依赖 。
30. 慢查询日志有什么用?
慢查询日志主要是用来帮我们揪出数据库里那些执行特别慢的SQL语句,比如有时候系统突然卡了或者用户反馈页面加载慢,这时候就可以去翻翻慢查询日志,看看是不是哪条查询拖了后腿。比如说,如果一条SQL执行了十几秒甚至更久,它会被自动记录到日志里,这样我们就能快速定位到问题语句,而不是像大海捞针一样去排查整个系统。
31. binlog 主要记录了什么?
Binlog(二进制日志)可以理解为数据库的“操作流水账”,它主要记录了MySQL服务器运行期间所有对数据库结构或数据产生修改的操作,比如插入、更新、删除这些写动作。
这样一来,binlog就有了两个核心用途:一个是主从复制,从库可以通过拉取主库的binlog来逐条重放这些操作,保持数据同步;另一个是数据恢复,比如哪天误删了数据或者数据库崩溃,可以通过binlog“回放”某个时间点之后的所有操作,把数据追到最新状态。
32. binlog 和 redolog 有什么区别?
binlog主要用于数据库还原,属于数据级别的数据恢复,主从复制是binlog最常见的一个应用场景。redolog主要用于保证事务的持久性,属于事务级别的数据恢复。
33. redolog 什么情况下会出现数据丢失
- redolog写入log buffer但还未写入page cache,此时数据库崩溃,就会出现数据丢失;
- redolog已经写入pagecache但还未写入磁盘,操作系统奔溃,也可能出现数据丢失。
34. 如何保证redolog 和 binlog的一致性
InnoDB用两阶段提交来保证Redolog和Binlog的一致性。事务提交时,先写Redolog到prepare状态,再写Binlog,最后把Redolog标记为commit。这样如果中途崩溃,重启时会检查Binlog是否完整——如果Binlog有记录,就说明事务应该提交,用Redolog恢复数据;如果Binlog没记录,就回滚事务。这样避免了主从库数据不一致或者恢复后数据错乱的问题。
35. undo log 如何保证事务的原子性?
Undo log通过记录事务执行前的数据状态来确保原子性。在事务执行过程中,每一条修改数据的操作都会生成对应的undo log记录,这些记录保存了数据修改前的原始值。如果事务在执行期间遇到错误或被显式回滚,数据库系统会依据undo log中的逆向操作链条,逐条撤销已完成的修改,将数据恢复到事务开始前的状态。
36. binlog 有哪几种记录格式
statement
指定statement,记录的内容是SQL语句原文。row
(5.7之后默认)
直接记录数据变化mixed
对上述两种方式的折中,默认情况下记录SQL语句(STATEMENT模式),但当检测到可能引发数据歧义的操作(如使用不确定函数或触发器)时,自动切换为ROW格式记录具体的数据变更。
37. 如何进行SQL调优
平时进行SQL调优,主要是通过观察慢SQL,然后利用explain分析查询语句的执行计划,识别性能瓶颈,优化查询语句。
- 合理设计索引,利用联合索引进行覆盖索引的优化,避免回表的发生,减少一次查询和随机I/O
- 避免SELECT*,只查询必要的字段
- 避免在SQL中进行函数计算等操作,使得无法命中索引
- 避免使用LIKE %,导致全表扫描
- 注意联合索引|需满足最左匹配原则
- 不要对无索引字段进行排序操作
- 连表查询需要注意不同字段的字符集是否一致,否则也会导致全表扫描
除此之外,还可以利用缓存来优化,一些变化少或者访问频繁的数据设置到缓存中,减轻数据库的压力,提升查询的效率。
还可以通过业务来优化,例如少展示一些不必要的字段,减少多表查询的情况,将列表查询替换成分页分批查询等等。
38. 如何实现读写分离?
读写分离就是读操作和写操作从以前的一台服务器上剥离开来,将主库压力分担一些到从库。本质上是因为访问量太大,主库的压力过大,单机数据库无法支撑并发读写。然后一般而言读的次数远高于写,因此将读操作分发到从库上,这就是常见的读写分离。
读写分离时可以让主库不建查询的索引,从库建查询的索引。
因为索引是需要维护的,比如你插入一条数据,不仅要在聚簇索引上面插入,对应的二级索引也得插入,修改也是一样的。所以将读操作分到从库了之后,可以在主库把查询要用的索引删了,减少写操作对主库的影响。
39. 什么是MySQL的主从同步机制
MySQL的主从同步机制是一种数据复制技术,用于将主数据库(Master)上的数据同步到一个或多个从数据库(Slave)中。
主要是通过二进制日志(BinaryLog,简称binlog)实现数据的复制。主数据库在执行写操作时,会将这些操作记录到binlog中,然后推送给从数据库,从数据库重放对应的日志即可完成复制。
40. 什么是分库分表
分库分表是数据库性能优化的一种方法,通过将数据分散存储在多个数据库或表中,来提高系统的可扩展性、性能和可用性。
分库分表的类型(或策略)包括:
1)水平分表:
将同一张表的数据按行划分,分散到多个表中。例如,可以按用户ID的范围将数据分为多个表(如user_1、user_2)。
2)垂直分表:
将一张表的不同列拆分到多个表中,以减少每张表的字段数量和提高查询效率。例如,用户表可以分为基本信息表和详细信息表。
3)水平分库:
将相同的表结构复制一份到另一个库中,每个库的表结构是一样的,可以减少单一数据库的读写压力,在大数量的情况下提高读写性能。例如,database1、database2。
4)垂直分库:
将数据分散到不同的数据库实例中。可以根据业务功能或模块进行分库,如将用户数据、订单数据分别存储在不同的数据库中。
41. MySQL获取数据,是从磁盘读取的吗?
在MySQL中,获取数据并不总是直接从磁盘读取。MySQL使用缓存机制,比如InnoDB存储引擎,会将常用的数据和索引缓存在内存中,以提高读取性能。当查询数据时,系统首先会检查缓存(如缓冲池),如果数据存在于内存中,则直接从内存中读取;如果不在,则会从磁盘读取并加载到缓存中。
42. 什么情况下,不推荐为数据库建立索引?
1)对于数据量很小的表
当表的数据量很小(如几百条记录)时,建立索引并不会显著提高查询性能,反而可能增加管理的复杂性。
2)频繁更新的表
对于频繁进行插入、更新和删除操作的表,索引会导致额外的维护开销,因为每次数据变更时都需要更新索引,这会影响性能。
3)低选择性字段(高度重复值的列)
当索引字段的取值重复度高(如性别字段“男”、“女”),索引的效果不明显,且会增加存储空间的浪费。
4) 长文本字段
会影响每个数据页存放key的数量,导致B+树变高,磁盘IO次数变多
43. 如何在MySQL中监控和优化慢SQL
可以利用MySQL自带的slow_query_log来监控慢SQL,它是MySQL提供的一个日志功能,用于记录执行时间超过特定阈值的SQL语句。
对于慢查询,再使用EXPLAIN分析执行计划,查看查询的执行顺序、使用的索引、扫描的行数等,以识别潜在的性能瓶颈。