0
点赞
收藏
分享

微信扫一扫

MySQL经典100问

沈芏 2022-03-12 阅读 74

常规篇

1、说一下数据库的三大范式? 

第一范式:字段原子性,第二范式:行唯一,有主键列,第三范式:每列和主键列都相关。

实际应用中会通过冗余少量字段来少关联表,提升查询效率。

2、只查询一条数据,但是也执行非常慢,原因一般有哪些?

  • MySQL数据库本身被堵住了,比如:系统或网络资源不够
  • SQL语句被堵住了,比如:表锁,行锁等,导致存储引擎不执行对应的SQL语句
  • 确实是索引使用不当,没有走索引
  • 表中数据的特点导致的,走了索引,但回表次数庞大

3、count(*)、count(0)、count(id)实现方式的区别?

  • 对于count(*)count(常数)count(主键)形式的count函数来说,优化器可以选择扫描成本最小的索引执行查询,从而提升效率,它们的执行过程是一样的。
  • 而对于count(非索引列)来说,优化器选择全表扫描,说明只能在聚集索引的叶子结点顺序扫描。
  • count(二级索引列)只能选择包含我们指定的列的索引去执行查询,可能导致优化器选择的索引执行的代价并不是最小。

4、误删数据怎么办?

1)如果数据量比较大,用物理备份xtrabackup。定期对数据库进行全量备份,也可以做增量备份。

2)如果数据量较少,用mysqldump或者mysqldumper,再利用binlog来恢复或者搭建主从的方式来恢复数据,可以从以下几个点来恢复:

  • DML误操作语句:可以通过flashback,先解析binlog event,然后在进行反转。
  • DDL语句误操作:只能通过全量备份+应用binlog的方式来恢复数据。一旦数据量比较大,那么恢复时间就特别长。
  • rm 删除:使用备份跨机房,或者最好是跨城市保存。

5、drop、truncate 和 delete 的区别

  • DELETE语句执行删除的过程是每次从表中删除一行,并且同时将该行的删除操作作为事务记录在日志中保存以便进行进行回滚操作。
  • TRUNCATE TABLE 则一次性地从表中删除所有的数据并不把单独的删除操作记录记入日志保存,删除行是不能恢复的。并且在删除的过程中不会激活与表有关的删除触发器,执行速度快。
  • drop语句将表所占用的空间全释放掉。

6、MySQL大表查询为什么不会爆内存?

  • MySQL 是“边读边发的”,这就意味着,如果客户端接收得慢,会导致 MySQL 服务端由于结果发不出去,这个事务的执行时间变长。
  • 服务端并不需要保存一个完整的结果集。取数据和发数据的流程都是通过一个next_buffer来操作的。
  • 内存的数据页是在 Buffer Pool (BP) 中管理的。
  • InnoDB 管理 Buffer Pool 使用改进的 LRU 算法,是用链表来实现的。在 InnoDB 实现上,按照 5:3 的比例把整个 LRU 链表分成了 young 区域和 old 区域,确保大批量加载冷数据时不会冲掉热点数据。

7、深度分页(超大分页)怎么处理?

  • 用id优化:先找到上次分页的最大ID,然后利用id上的索引来查询,类似于select * from user where id>1000000 limit 100。
  • 用覆盖索引优化:Mysql的查询完全命中索引的时候,称为覆盖索引,是非常快的,因为查询只需要在索引上进行查找,之后可以直接返回,而不用再回表拿数据.因此我们可以先查出索引的ID,然后根据Id拿数据。
  • 在业务允许的情况下限制页数

8、日常开发中你是怎么优化SQL的?

  • 添加合适索引:对作为查询条件和order by的字段建立索引,对于多个查询字段的考虑建立组合索引,同时注意组合索引字段的顺序,将最常用作限制条件的列放在最左边,依次递减,索引不宜太多,一般5个以内。
  • 优化表结构:数字型字段优于字符串类型,数据类型更小通常更好,尽量使用 NOT NULL
  • 优化查询语句:分析SQl执行计划,是否命中索引等,如果SQL很复杂,优化SQL结构,如果表数据量太大,考虑分表

9、MySQL 的并发连接与并发查询什么区别?

  • 在执行show processlist的结果里,看到了几千个连接,指的是并发连接。
  • 而"当前正在执行"的语句,才是并发查询。
  • 并发连接数多影响的是内存。
  • 并发查询太高对CPU不利。一个机器的CPU核数有限,线程全冲进来,上下文切换的成本就会太高。
  • 需要注意的是,在线程进入锁等待以后,并发线程计数减一,所以等行锁或者间隙锁时的线程是不算在计数范围内的。也就是说进入锁等待的线程不吃CPU,从而避免整个系统锁死。

10、MySQL更新字段值为原来的值内部是怎么操作呢?

11、datetime和timestamp有什么区别?

  • datetime 的日期范围是 1001——9999 年;timestamp 的时间范围是 1970——2038 年
  • datetime 存储时间与时区无关;timestamp 存储时间与时区有关,显示的值也依赖于时区
  • datetime 的存储空间为 8 字节;timestamp 的存储空间为 4 字节
  • datetime 的默认值为 null;timestamp 的字段默认不为空(not null),默认值为当前时间(current_timestamp)

12、事务的隔离级别有哪些?

  • 「读未提交」(Read Uncommitted)最低级别,任何情况都无法保证
  • 「读已提交」(Read Committed)可避免脏读的发生
  • 「可重复读」(Repeatable Read)可避免脏读、不可重复读的发生
  • 「串行化」(Serializable)可避免脏读、不可重复读、幻读的发生
  • Mysql默认的事务隔离级别是「可重复读」(Repeatable Read)

13、在 MySQL 中有两个 kill 命令

  • kill query + 线程 id,表示终止这个线程中正在执行的语句
  • kill connection + 线程 id,这里 connection 可缺省,表示断开这个线程的连接

索引篇

1、索引分类有哪些?

  • 根据叶子节点的内容,索引类型分为主键索引和非主键索引。
  • 主键索引的叶子节点存的是整行数据。在 InnoDB 里,主键索引也被称为聚簇索引(clustered index)。
  • 非主键索引的叶子节点内容是主键的值。在 InnoDB 里,非主键索引也被称为二级索引(secondary index)。

3、InnoDB 为什么设计B+树,而不是B-Tree,Hash,二叉树,红黑树?

  • 哈希索引能够以 O(1) 的速度处理单个数据行的增删改查,但是面对范围查询或者排序时就会导致全表扫描的结果。
  • B树可以在非叶结点中存储数据,由于所有的节点都可能包含目标数据,我们总是要从根节点向下遍历子树查找满足条件的数据行,这个特点带来了大量的随机 I/O,造成性能下降。
  • B+树所有的数据行都存储在叶节点中,而这些叶节点可以通过『指针』依次按顺序连接,当我们在如下所示的 B+ 树遍历数据时可以直接在多个子节点之间进行跳转,这样能够节省大量的磁盘 I/O 时间。
  • 二叉树:树的高度不均匀,不能自平衡,查找效率跟数据有关(树的高度),并且IO代价高。

  • 红黑树:树的高度随着数据量增加而增加,IO代价高。

8、讲一讲聚簇索引与非聚簇索引?

  • 在InnoDB里,索引B+ Tree的叶子节点存储了整行数据的是主键索引,也被称之为聚簇索引,即将数据存储与索引放到了一块,找到索引也就找到了数据。
  • 而索引B+Tree的叶子节点存储了主键的值的是非主键索引,也被称之为非聚簇索引、二级索引。
  • 第一次索引一般是顺序IO,回表的操作属于随机IO。需要回表的次数越多,即随机IO次数越多,我们就越倾向于使用全表扫描 。

9、非聚簇索引一定会回表查询吗?

  • 不一定,这涉及到查询语句所要求的字段是否全部命中了索引,如果全部命中了索引,那么就不必再进行回表查询。一个索引包含(覆盖)所有需要查询字段的值,被称之为“覆盖索引”。

10、讲一讲MySQL的最左前缀原则?

  • 最左前缀原则就是最左优先,在创建多列索引时,要根据业务需求,where子句中使用最频繁的一列放在最左边。
  • MySQL会一直向右匹配直到遇到范围查询(>、<、between、like)就停止匹配,比如a = 1 and b = 2 and c > 3 and d = 4 如果建立(a,b,c,d)顺序的索引,d是用不到索引的,如果建立(a,b,d,c)的索引则都可以用到,a,b,d的顺序可以任意调整。
  • =和in可以乱序,比如a = 1 and b = 2 and c = 3 建立(a,b,c)索引可以任意顺序,MySQL的查询优化器会帮你优化成索引可以识别的形式。

11、什么是索引下推?

  • 满足最左前缀原则的时候,最左前缀可以用于在索引中定位记录。
  • 在 MySQL 5.6 之前,只能从ID开始一个个回表。到主键索引上找出数据行,再对比字段值。
  • 而 MySQL 5.6 引入的索引下推优化(index condition pushdown), 可以在索引遍历过程中,对索引中包含的字段先做判断,直接过滤掉不满足条件的记录,减少回表次数。

12、Innodb为什么要用自增id作为主键?

如果表使用自增主键,那么每次插入新的记录,记录就会顺序添加到当前索引节点的后续位置,当一页写满,就会自动开辟一个新的页。如果使用非自增主键(如果身份证号或学号等),由于每次插入主键的值近似于随机,因此每次新纪录都要被插到现有索引页得中间某个位置, 频繁的移动、分页操作造成了大量的碎片,得到了不够紧凑的索引结构,后续不得不通过OPTIMIZE TABLE(optimize table)来重建表并优化填充页面。

13、事务ACID特性的实现原理?

  • 「原子性」:是使用 undo log 来实现的,如果事务执行过程中出错或者用户执行了rollback,系统通过undo log日志返回事务开始的状态。
  • 「持久性」:使用 redo log 来实现,只要redo log日志持久化了,当系统崩溃,即可通过redo log把数据恢复。
  • 「隔离性」:通过锁以及 MVCC,使事务相互隔离开。
  • 「一致性」:通过回滚、恢复,以及并发情况下的隔离性,从而实现一致性。

方案篇

1、如何设计可以动态扩容缩容的分库分表方案?

停机扩容(不推荐):

2、一个6亿的表a,一个3亿的表b,通过外间tid关联,你如何最快的查询出满足条件的第50000到第50200中的这200条数据记录?

3、现在有一个未分库分表的系统,未来要分库分表,如何设计才可以让系统从未分库分表动态切换到分库分表上?

原理篇

1、一条 MySQL 语句执行步骤是什么样的?

2、order by 排序内部原理是什么样的?

  • MySQL会为每个线程分配一个内存(sort_buffer)用于排序该内存大小为sort_buffer_size。
  • 如果排序的数据量小于sort_buffer_size,排序将会在内存中完成。
  • 如果排序数据量很大,内存中无法存下这么多数据,则会使用磁盘临时文件来辅助排序,也称外部排序。
  • 在使用外部排序时,MySQL会分成好几份单独的临时文件用来存放排序后的数据,然后在将这些文件合并成一个大文件。

3、MVCC 实现原理?

4、change buffer是什么,有何作用?

5、MySQL是如何保证数据不丢失?

  • 只要 redolog 和 binlog 保证持久化磁盘就能确保 MySQL 异常重启后数据恢复 binlog 写入机制。
  • redolog确保系统异常后,丢失的数据可以重做,binlog将数据进行归档,确保丢失的数据可以恢复。
  • 事务执行前先写redolog,事务执行过程中,先把日志写到 binlog cache 里,事务提交的时候,再把 binlog cache 写到 binlog 文件中。

6、为什么删除了表,表文件的大小还是没变?

7、binlog三种格式对比

8、MySQL加锁规则

9、什么是脏读、不可重复读、幻读呢?

  • 「脏读」: 脏读指的是读到了其他事务未提交的数据,未提交意味着这些数据可能会回滚,也就是可能最终不会存到数据库中,也就是不存在的数据。读到了并不一定最终存在的数据,这就是脏读。
  • 「不可重复读」: 不可重复读指的是在一个事务内,最开始读到的数据和事务结束前的任意时刻读到的同一批数据出现不一致的情况。
  • 「幻读」: 幻读,并不是说两次读取获取的结果集不同,幻读侧重的方面是某一次的 select 操作得到的结果的数据状态无法支撑后续的业务操作。更为具体一些:select 某记录是否存在,不存在,准备插入此记录,但执行 insert 时发现此记录已存在,无法插入,此时就发生了幻读。

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

框架篇

1、Mysql 主从复制原理的是啥?

2、Mysql主从复制同步方式有哪些?

3、Mysql主从同步延时产生原因?怎么优化?

4、MySQL是如何保证主备同步的?

5、MySQL的一主一备和一主多从有什么区别?

6、主库出问题如何解决?

7、bin log/redo log/undo log是什么?

2、MyISAM和InnoDB实现B树索引方式的区别是什么?

  • InnoDB 存储引擎:B+ 树索引的叶子节点保存数据本身;

  • MyISAM 存储引擎:B+ 树索引的叶子节点保存数据的物理地址;

InnoDB,其数据文件本身就是索引文件,相比MyISAM,索引文件和数据文件是分离的,其表数据文件本身就是按B+Tree组织的一个索引结构,树的节点data域保存了完整的数据记录,这个索引的key是数据表的主键,因此InnoDB表数据文件本身就是主索引,这被称为“聚簇索引”或者聚集索引,而其余的索引都作为辅助索引,辅助索引的data域存储相应记录主键的值而不是地址,这也是和MyISAM不同的地方。

3、一条 MySQL 语句执行步骤

Server层按顺序执行sql的步骤为:

客户端请求 -> 连接器(验证用户身份,给予权限) -> 查询缓存(存在缓存则直接返回,不存在则执行后续操作)-> 分析器(对SQL进行词法分析和语法分析操作) -> 优化器(主要对执行的sql优化选择最优的执行方案方法) -> 执行器(执行时会先看用户是否有执行权限,有才去使用这个引擎提供的接口)-> 去引擎层获取数据返回(如果开启查询缓存则会缓存查询结果)。

4、InnoDB 为什么设计B+树?

  • 哈希虽然能够提供 O(1) 的单数据行操作性能,但是对于范围查询和排序却无法很好地支持,最终导致全表扫描;

  • B 树能够在非叶节点中存储数据,导致每个页存储的节点数有限,造成树的深度增加

  • 而 B+ 树的所有叶节点可以通过指针相互连接,能够减少顺序遍历时产生的额外随机 I/O;

5、索引有哪些分类?

1、根据叶子节点的内容,索引类型分为主键索引和非主键索引。

2、主键索引的叶子节点存的是整行数据。在 InnoDB 里,主键索引也被称为聚簇索引(clustered index)。

3、非主键索引的叶子节点内容是主键的值。在 InnoDB 里,非主键索引也被称为二级索引(secondary index)。 

6、有哪些场景会导致索引失效?

B+ 树提供的这个快速定位能力,来源于同一层兄弟节点的有序性。

  • 对索引使用左或者左右模糊匹配:也就是 like %xx 或者 like %xx% 这两种方式都会造成索引失效。原因在于查询的结果可能是「陈林、张林、周林」等之类的,所以不知道从哪个索引值开始比较,于是就只能通过全表扫描的方式来查询。

  • 对索引使用函数/对索引进行表达式计算:因为索引保存的是索引字段的原始值,而不是经过函数计算后的值,自然就没办法走索引了。

  • 对索引隐式类型转换:相当于用了新函数

  • WHERE 子句中的 OR:的含义就是两个只要满足一个即可,因此只有一个条件列是索引列是没有意义的,只要有条件列不是索引列,就会进行全表扫描。

举报

相关推荐

0 条评论