MySQL经典29问
创始人
2024-05-31 03:50:32
0

文章目录

  • 1. 为什么要尽量设定一个主键?
  • 2. 主键使用自增ID还是UUID?
  • 3. 字段为什么要求定义为not null?
  • 4. 如果要存储用户的密码散列,应该使用什么字段进行存储?
  • 5. MySQL支持哪些存储引擎?
  • 6. InnoDB和MyISAM有什么区别?
  • 7. MySQL中的varchar和char有什么区别?
  • 8. varchar(10)和int(10)代表什么含义?
  • 9. MySQL的binlog有几种录入格式?分别有什么区别?
  • 10. 超大分页怎么处理?
  • 11. 关心过业务系统里面的sql耗时吗?统计过慢查询吗?对慢查询都怎么优化过?
  • 12. 上面提到横向分表和纵向分表,可以分别举一个适合他们的例子吗?
  • 13. 什么是存储过程?有哪些优缺点?
  • 14. 什么是索引?
  • 15. 索引是个什么样的数据结构呢?
  • 16. Hash索引和B+树有什么区别和优劣呢?
  • 17. 上面提到了B+树在满足聚簇索引和覆盖索引的时候不需要回表查询数据,什么是聚簇索引?
  • 18. 非聚簇索引一定会回表查询吗?
  • 19. 在建立索引的时候,都有哪些需要考虑的因素呢?
  • 20. 联合索引是什么?为什么需要注意联合索引中的顺序?
  • 21. 创建的索引有没有被使用到?或者说怎么才可以知道这条语句运行很慢的原因?
  • 22. 那么在哪些情况下会发生针对该列创建了索引但是在查询的时候并没有使用呢?
  • 23. 什么是事务?
  • 24. ACID是什么?
  • 25. 同时有多个事务在进行会怎么样呢?
  • 26. 怎么解决这些问题呢?MySQL的事务隔离级别了解吗?
  • 27. Innodb使用的是哪种隔离级别呢?
  • 28. 对MySQL的锁了解吗?
  • 29. MySQL都有哪些锁呢?像上面那样子进行锁定岂不是有点阻碍并发效率了?

1. 为什么要尽量设定一个主键?

主键是数据库确保数据行在整张表唯一性的保障,即使业务上本张表没有主键,也建议添加一个自增长的ID列作为主键。

设定了主键之后,在后续的删改查的时候可能更加快速以及确保操作数据范围安全。

2. 主键使用自增ID还是UUID?

推荐使用自增ID,不要使用UUID。

因为在InnoDB存储引擎中,主键索引是作为聚簇索引存在的,也就是说,主键索引的B+树叶子节点上存储了主键索引以及全部的数据(按照顺序)。

如果主键索引是自增ID,那么只需要不断向后排列即可。

如果是UUID,由于到来的ID与原来的大小不确定,会造成非常多的数据插入,数据移动,然后导致产生很多的内存碎片,进而造成插入性能的下降。

总之,在数据量大一些的情况下,用自增主键性能会好一些。

3. 字段为什么要求定义为not null?

null值会占用更多的字节,且会在程序中造成很多与预期不符的情况。

4. 如果要存储用户的密码散列,应该使用什么字段进行存储?

密码散列、用户身份证号等固定长度的字符串应该使用char而不是varchar来存储,这样可以节省空间且提高检索效率。

5. MySQL支持哪些存储引擎?

MySQL支持多种存储引擎,比如InnoDB,MyISAM,Memory,Archive等等。在大多数的情况下,直接选择使用InnoDB引擎都是最合适的,InnoDB也是MySQL的默认存储引擎。

6. InnoDB和MyISAM有什么区别?

(1)InnoDB支持事物,而MyISAM不支持事物;

(2)InnoDB支持行级锁,而MyISAM支持表级锁;

(3)InnoDB支持MVCC, 而MyISAM不支持;

(4)InnoDB支持外键,而MyISAM不支持;

(5)InnoDB不支持全文索引,而MyISAM支持;

7. MySQL中的varchar和char有什么区别?

char是一个定长字段,假如申请了char(10)的空间,那么无论实际存储多少内容。该字段都占用10个字符,而varchar是变长的,也就是说申请的只是最大长度,占用的空间为实际字符长度+1,最后一个字符存储使用了多长的空间。

在检索效率上来讲,char > varchar,因此在使用中,如果确定某个字段的值的长度,可以使用char,否则应该尽量使用varchar。例如存储用户MD5加密后的密码,则应该使用char。

8. varchar(10)和int(10)代表什么含义?

varchar的10代表了申请的空间长度,也是可以存储的数据的最大长度,而int的10只是代表了展示的长度,不足10位以0填充。也就是说,int(1)和int(10)所能存储的数字大小以及占用的空间都是相同的,只是在展示时按照长度展示。

9. MySQL的binlog有几种录入格式?分别有什么区别?

有三种格式:statement、row、mixed。

statement模式下,记录单元为语句。即每一个sql造成的影响会记录。由于sql的执行是有上下文的,因此在保存的时候需要保存相关的信息,同时还有一些使用了函数之类的语句无法被记录复制。

row级别下,记录单元为每一行的改动,基本是可以全部记下来但是由于很多操作,会导致大量行的改动(比如alter table),因此这种模式的文件保存的信息太多,日志量太大。

mixed模式下, 一种折中的方案,普通操作使用statement记录,当无法使用statement的时候使用row。

此外,新版的MySQL中对row级别也做了一些优化,当表结构发生变化的时候,会记录语句而不是逐行记录。

10. 超大分页怎么处理?

超大的分页一般从两个方向上来解决:

数据库层面,这也是我们主要集中关注的(虽然收效没那么大),类似于select * from table where age > 20 limit 1000000,10这种查询其实也是有可以优化的余地的。这条语句需要load1000000数据然后基本上全部丢弃,只取10条当然比较慢。

当时我们可以修改为select * from table where id in (select id from table where age > 20 limit 1000000,10)

这样虽然也load了一百万的数据,但是由于索引覆盖,要查询的所有字段都在索引中,所以速度会很快。同时如果ID连续的好,我们还可以select * from table where id > 1000000 limit 10,效率也是不错的,优化的可能性有许多种,但是核心思想都一样,就是减少load的数据。

从需求的角度减少这种请求,主要是不做类似的需求(直接跳转到几百万页之后的具体某一页。只允许逐页查看或者按照给定的路线走,这样可预测,可缓存)以及防止ID泄漏且连续被人恶意攻击。

解决超大分页,其实主要是靠缓存,可预测性的提前查到内容,缓存至redis等k-V数据库中,直接返回即可。

11. 关心过业务系统里面的sql耗时吗?统计过慢查询吗?对慢查询都怎么优化过?

在业务系统中,除了使用主键进行的查询,其他的我都会在测试库上测试其耗时,慢查询的统计主要由运维在做,会定期将业务中的慢查询反馈给我们。

慢查询的优化首先要搞明白慢的原因是什么? 是查询条件没有命中索引?是load了不需要的数据列?还是数据量太大?

所以优化也是针对这三个方向来的:

首先分析语句,看看是否load了额外的数据,可能是查询了多余的行并且抛弃掉了,可能是加载了许多结果中并不需要的列,对语句进行分析以及重写。

分析语句的执行计划,然后获得其使用索引的情况,之后修改语句或者修改索引,使得语句可以尽可能的命中索引。

如果对语句的优化已经无法进行,可以考虑表中的数据量是否太大,如果是的话可以进行横向或者纵向的分表

12. 上面提到横向分表和纵向分表,可以分别举一个适合他们的例子吗?

横向分表是按行分表。

假设我们有一张用户表,主键是自增ID且同时是用户的ID。数据量较大,有1亿多条,那么此时放在一张表里的查询效果就不太理想。我们可以根据主键ID进行分表,无论是按尾号分,或者按ID的区间分都是可以的。

假设按照尾号0-99分为100个表,那么每张表中的数据就仅有100w。这时的查询效率无疑是可以满足要求的。

纵向分表是按列分表。

假设我们现在有一张文章表。包含字段id-摘要-内容。而系统中的展示形式是刷新出一个列表,列表中仅包含标题和摘要,当用户点击某篇文章进入详情时才需要正文内容。

此时,如果数据量大,将内容这个很大且不经常使用的列放在一起会拖慢原表的查询速度。

我们可以将上面的表分为两张。id-摘要,id-内容。当用户点击详情,那主键再来取一次内容即可。而增加的存储量只是很小的主键字段,代价很小。

当然,分表其实和业务的关联度很高,在分表之前一定要做好调研以及benchmark。不要按照自己的猜想盲目操作。

13. 什么是存储过程?有哪些优缺点?

存储过程是一些预编译的SQL语句。

(1)更加直白的理解:存储过程可以说是一个记录集,它是由一些T-SQL语句组成的代码块,这些T-SQL语句代码像一个方法一样实现一些功能(对单表或多表的增删改查),然后再给这个代码块取一个名字,在用到这个功能的时候调用他就行了。

(2)存储过程是一个预编译的代码块,执行效率比较高,一个存储过程替代大量T_SQL语句 ,可以降低网络通信量,提高通信速率,可以一定程度上确保数据安全

但是,在互联网项目中,其实是不太推荐存储过程的,比较出名的就是阿里的《Java开发手册》中禁止使用存储过程,我个人的理解是,在互联网项目中,迭代太快,项目的生命周期也比较短,人员流动相比于传统的项目也更加频繁,在这样的情况下,存储过程的管理确实是没有那么方便,同时,复用性也没有写在服务层那么好。

14. 什么是索引?

索引是一种数据结构,可以帮助我们快速的进行数据的查找。

15. 索引是个什么样的数据结构呢?

索引的数据结构和具体存储引擎的实现有关,在MySQL中使用较多的索引有Hash索引,B+树索引等,而我们经常使用的InnoDB存储引擎的默认索引实现为:B+树索引。

16. Hash索引和B+树有什么区别和优劣呢?

首先要知道Hash索引和B+树索引的底层实现原理:

hash索引底层就是hash表,进行查找时,调用一次hash函数就可以获取到相应的键值,之后进行回表查询获得实际数据。

B+树底层实现是多路平衡查找树,对于每一次的查询都是从根节点出发,查找到叶子节点方可以获得所查键值,然后根据查询判断是否需要回表查询数据。

那么可以看出他们有以下的不同:

(1)hash索引进行等值查询更快(一般情况下),但是却无法进行范围查询。因为在hash索引中经过hash函数建立索引之后,索引的顺序与原顺序无法保持一致,不能支持范围查询。而B+树的的所有节点皆遵循(左节点小于父节点,右节点大于父节点,多叉树也类似),天然支持范围。

(2)hash索引不支持使用索引进行排序,原理同上。

(3)hash索引任何时候都避免不了回表查询数据,而B+树在符合某些条件(聚簇索引,覆盖索引等)的时候可以只通过索引完成查询。

(4)hash索引虽然在等值查询上较快,但是不稳定。性能不可预测,当某个键值存在大量重复的时候,发生hash碰撞,此时效率可能极差。而B+树的查询效率比较稳定,对于所有的查询都是从根节点到叶子节点,且树的高度较低。

因此,在大多数情况下,直接选择B+树索引可以获得稳定且较好的查询速度,而不需要使用hash索引。

17. 上面提到了B+树在满足聚簇索引和覆盖索引的时候不需要回表查询数据,什么是聚簇索引?

在B+树的索引中,叶子节点可能存储了当前的key值,也可能存储了当前的key值以及整行的数据,这就是聚簇索引和非聚簇索引。

在InnoDB中,只有主键索引是聚簇索引,如果没有主键,则挑选一个唯一键建立聚簇索引。

如果没有唯一键,则隐式的生成一个键来建立聚簇索引。当查询使用聚簇索引时,在对应的叶子节点,可以获取到整行数据,因此不用再次进行回表查询。

18. 非聚簇索引一定会回表查询吗?

不一定,这涉及到查询语句所要求的字段是否全部命中了索引,如果全部命中了索引,那么就不必再进行回表查询。

举个简单的例子,假设我们在员工表的年龄上建立了索引,那么当进行select age from employee where age < 20的查询时,在索引的叶子节点上,已经包含了age信息,不会再次进行回表查询。

19. 在建立索引的时候,都有哪些需要考虑的因素呢?

建立索引的时候一般要考虑到字段的使用频率,经常作为条件进行查询的字段比较适合。

如果需要建立联合索引的话,还需要考虑联合索引中的顺序。

此外也要考虑其他方面,比如防止过多的索引对表造成太大的压力,这些都和实际的表结构以及查询方式有关。

20. 联合索引是什么?为什么需要注意联合索引中的顺序?

MySQL可以使用多个字段同时建立一个索引,叫做联合索引。在联合索引中,如果想要命中索引,需要按照建立索引时的字段顺序挨个使用,否则无法命中索引。

MySQL使用索引时需要索引有序,假设现在建立了"name,age,school"的联合索引,那么索引的排序为: 先按照name排序,如果name相同,则按照age排序,如果age的值也相等,则按照school进行排序。

当进行查询时,此时索引仅仅按照name严格有序,因此必须首先使用name字段进行等值查询,之后对于匹配到的列而言,其按照age字段严格有序,此时可以使用age字段用作索引查找,以此类推。

因此在建立联合索引的时候应该注意索引列的顺序,一般情况下,将查询需求频繁或者字段选择性高的列放在前面。此外可以根据特例的查询或者表结构进行单独的调整。

21. 创建的索引有没有被使用到?或者说怎么才可以知道这条语句运行很慢的原因?

MySQL提供了explain命令来查看语句的执行计划,MySQL在执行某个语句之前,会将该语句过一遍查询优化器,之后会拿到对语句的分析,也就是执行计划,其中包含了许多信息。

可以通过其中和索引有关的信息来分析是否命中了索引,例如possilbe_key,key,key_len等字段,分别说明了此语句可能会使用的索引,实际使用的索引以及使用的索引长度。

22. 那么在哪些情况下会发生针对该列创建了索引但是在查询的时候并没有使用呢?

(1)使用不等于查询;

(2)列参与了数学运算或者函数;

(3)在字符串like时左边是通配符,类似于’%aaa’;

(4)当mysql分析全表扫描比使用索引快的时候不使用索引;

(5)当使用联合索引,前面一个条件为范围查询,后面的即使符合最左前缀原则,也无法使用索引。

以上情况,MySQL无法使用索引。

23. 什么是事务?

事务是一个不可分割的数据库操作序列,也是数据库并发控制的基本单位,其执行的结果必须使数据库从一种一致性状态到另一种一致性状态。事务是逻辑上的一组操作,要么都执行,要么都不执行。

24. ACID是什么?

  1. 原子性(Atomicity)原子性是指事务是一个不可分割的工作单位,事务中的操作要么都发生,要么都不发生。
  2. 一致性(Consistency)事务前后数据的完整性必须保持一致。
  3. 持久性(Durability)持久性是指一个事务一旦被提交,它对数据库中数据的改变就是永久性的,接下来即使数据库发生故障也不应该对其有任何影响。
  4. 隔离性(Isolation)事务的隔离性是指多个用户并发操作数据库时,一个用户的事务不能被其它用户的事务所干扰,多个并发事务之间数据要相互隔离。 简单来说: 事务之间互不干扰。

25. 同时有多个事务在进行会怎么样呢?

多事务的并发进行一般会造成以下几个问题:

脏读:⼀个事务读取到另⼀个事务未提交的数据,称为脏读。
不可重复读:⼀个事务执⾏过程中,对同⼀条数据查询多次,会得到多个不同的结果。
幻读指的是:
⼀个事务添加的数据另⼀个事务看不到。
⼀个事务删除的数据另⼀个事务仍然可以查询到。

26. 怎么解决这些问题呢?MySQL的事务隔离级别了解吗?

MySQL的四种隔离级别如下:

  1. READ-UNCOMMITTED(读取未提交): 最低的隔离级别,允许读取尚未提交的数据变更,可能会导致脏读、幻读或不可重复读。
  2. READ-COMMITTED(读取已提交): 允许读取并发事务已经提交的数据,可以阻止脏读,但是幻读或不可重复读仍有可能发生。
  3. REPEATABLE-READ(可重复读): 对同一字段的多次读取结果都是一致的,除非数据是被本身事务所修改,可以阻止脏读和不可重复读,但幻读仍有可能发生。
  4. SERIALIZABLE(可串行化): 最高的隔离级别,完全服从ACID的隔离级别。所有的事务依次逐个执行,这样事务之间就完全不可能产生干扰,也就是说,该级别可以防止脏读、不可重复读以及幻读。

27. Innodb使用的是哪种隔离级别呢?

InnoDB默认使用的是可重复读隔离级别。

28. 对MySQL的锁了解吗?

当数据库有并发事务的时候,可能会产生数据的不一致,这时候需要一些机制来保证访问的次序,锁机制就是这样的一个机制。

就像酒店的房间,如果大家随意进出,就会出现多人抢夺同一个房间的情况,而在房间上装上锁,申请到钥匙的人才可以入住并且将房间锁起来,其他人只有等他使用完毕才可以再次使用。

29. MySQL都有哪些锁呢?像上面那样子进行锁定岂不是有点阻碍并发效率了?

从锁的类别上来讲,有共享锁和排他锁。

共享锁:又叫做读锁。当用户要进行数据的读取时,对数据加上共享锁。共享锁可以同时加上多个。

排他锁:又叫做写锁。当用户要进行数据的写入时,对数据加上排他锁。排他锁只可以加一个,他和其他的排他锁,共享锁都相斥。

用上面的例子来说就是用户的行为有两种,一种是来看房,多个用户一起看房是可以接受的。一种是真正的入住一晚,在这期间,无论是想入住的还是想看房的都不可以。

锁的粒度取决于具体的存储引擎,InnoDB实现了行级锁,页级锁,表级锁。

他们的加锁开销从大到小,并发能力也是从大到小。

相关内容

热门资讯

【NI Multisim 14...   目录 序言 一、工具栏 🍊1.“标准”工具栏 🍊 2.视图工具...
银河麒麟V10SP1高级服务器... 银河麒麟高级服务器操作系统简介: 银河麒麟高级服务器操作系统V10是针对企业级关键业务...
不能访问光猫的的管理页面 光猫是现代家庭宽带网络的重要组成部分,它可以提供高速稳定的网络连接。但是,有时候我们会遇到不能访问光...
AWSECS:访问外部网络时出... 如果您在AWS ECS中部署了应用程序,并且该应用程序需要访问外部网络,但是无法正常访问,可能是因为...
Android|无法访问或保存... 这个问题可能是由于权限设置不正确导致的。您需要在应用程序清单文件中添加以下代码来请求适当的权限:此外...
北信源内网安全管理卸载 北信源内网安全管理是一款网络安全管理软件,主要用于保护内网安全。在日常使用过程中,卸载该软件是一种常...
AWSElasticBeans... 在Dockerfile中手动配置nginx反向代理。例如,在Dockerfile中添加以下代码:FR...
AsusVivobook无法开... 首先,我们可以尝试重置BIOS(Basic Input/Output System)来解决这个问题。...
ASM贪吃蛇游戏-解决错误的问... 要解决ASM贪吃蛇游戏中的错误问题,你可以按照以下步骤进行:首先,确定错误的具体表现和问题所在。在贪...
月入8000+的steam搬砖... 大家好,我是阿阳 今天要给大家介绍的是 steam 游戏搬砖项目,目前...