常见数据库优化面试题

Posted coderyeah

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了常见数据库优化面试题相关的知识,希望对你有一定的参考价值。


常见数据库面试题

一.在项目中如何定位慢查询

  • 通过 druid 连接池的内置监控来定位慢 SQL。
  • 通过 mysql 的慢查询日志查看慢 SQL。
  • 通过 show processlist,查看当前数据库 SQL 执行情况来定位慢 SQL。

二.如何查看sql语句索引命中情况

在 SQL 语句前加上 explain,结果中的 key 就是实际用到的索引

三.说说数据库锁表的场景和解决方法

  1. 产生场景

    锁表通常发生在 DML( insert 、update 、delete )语句中,例如:程序 A 对 A 表的 a 数据 进行修改,修改过程中产生错误,没有 commit 也没有 rollback ,这个时候程序 B 对 A 表的 a 数据进行修改,会产生资源正忙的异常,也就是锁表。

    DDL也会引发锁表,例如在 MySql 操作一张大表,利用 alter 语句修改或新增字段的时候,恰巧有一个长事务(包括读)在操作此表,会触发修改等待,造成锁表。

  2. 原因

    当多个事务处理对多个资源同时访问时,若双方已锁定一部分资源但也都需要对方已锁定的资源时,无法在有限的时间内完全获得所需的资源,就会处于无限的等待状态,从而造成其对资源需求的死锁,导致锁表。

  3. MySQL解决办法

    • 执行SQL

      select * from information_schema.processlist where command not in ('Sleep') ORDER BY time desc
      
    • sql 已经按照阻塞时长从大到小排序,找到耗时长的记录 id ,kill 即可:

      kill pid
      

四.truncate和delete的区别

1.delete是DML语句,truncate是DDL语句;

2.delete后面可以有where条件,truncate后面不能加where条件;

3.delete操作后,事务提交后才会生效,truncate操作后立即生效,所以truncate要比delete得执行效率高(数据量大的话就比较明显了);

4.delete操作后,是按行删除,原数据会放到rollback segment中,可进行回滚。truncate执行是立即生效的,不记录行删除信息,而是直接重构表,所以不能回滚;

5.delete执行后,会产生数据碎片,只删除数据,不会改变表空间大小。truncate执行后,数据库表会恢复至初始状态。

五.union与union all的区别

1、union: 对两个结果集进行并集操作, 不包括重复行,相当于distinct, 同时进行默认规则的排序;会对获取的结果进行排序操作

2、union all: 对两个结果集进行并集操作, 包括重复行, 即所有的结果全部显示, 不管是不是重复;不会对获取的结果进行排序操作

union all只是合并查询结果,并不会进行去重和排序操作,在没有去重的前提下,使用union all的执行效率要比union高

六.left join,right join inner join区别

  • LEFT JOIN 左连接,以左侧表为主,右侧表与其相匹配,匹配不上的记录 ,以null 做替补;

  • RIGHT JOIN右连接,以右侧表为主,左侧表与其相匹配,匹配不上得记录,以null做替补;

  • INNER JOIN内连接,取交集。

七.MySQL执行流程

  1. 客户端发起 SQL 查询,首先通过连接器,它会检查用户的身份,包括校验账户密码,权限,然后会查询缓存,如果缓存命中直接返回,如果没有命中再执行后续操作,但是MySQL8.0 之后已经删除了缓存功能;
  2. 接下来到达分析器,主要检查语法词法,比如 SQL 有没有写错,总共有多少关键字;要查询哪些东西;
  3. 然后到达优化器,他会以自己的方式优化我们的 SQL;
  4. 最后到达执行器,调用存储引擎执行 SQL 并返回结果。

八.MySQL语句执行顺序

from->on->join->where->group by->having->select->distinct->order by->limit

九.说说数据库设计三范式

  1. 第一范式:任何一张表都应该有自己的主键,并且每一个字段的原子性都是不可再分的。
    • 列唯一,每一个字段具有原子性不可再分;
    • 每一张表都有主键。
  2. 第二范式:在第一范式的基础上,要求所有的非主键字段完全依赖主键,不能产生部分依赖。
    • 行唯一
  3. 第三范式:在第二范式的基础上,所有非主键只能依赖于主键,不能产生传递依赖。
    • 存在外键,比如学生表中可以有班级表的主键进行关联。

十.CHAR 和 VARCHAR 的区别

char是一种固定长度的类型,无论储存的数据有多少都会固定长度,如果插入的长度小于定义长度,则可以用空格进行填充。而varchar是一种可变长度的类型,当插入的长度小于定义长度时,插入多长就存多长。

  1. char最大长度是255字符,varchar最大长度是65535个字节。
  2. char是定长的,不足的部分用隐藏空格填充,varchar是不定长的。
  3. char会浪费空间,varchar会更加节省空间。
  4. char查找效率会很高,varchar查找效率会更低。
  5. 尾部空格:char插入时可省略,varchar插入时不会省略,查找时省略。

十一.DDL,DML优化手段有哪些,批量插入

  1. DDL:在导入数据时,可以通过禁用索引来提高导入数据性能 。这个操作主要针对有数据的表,追加数据。

  2. DML:变多次事务提交为一次事务提交。批量插入

    insert into test values(1,2),(1,3),(1,4);
    

十二.MySQL存储引擎

  1. InnoDB存储引擎

    InnoDB是事务型数据库的首选引擎,支持事务安全表(ACID),支持行锁定和外键。

    • 支持事务,行锁,表锁,不支持全文索引,数据库宕机后可以恢复数据。
  2. MyISAM存储引擎

    MyISAM拥有较高的插入、查询速度,但不支持事物

    • 不支持外键,数据崩溃后无法恢复,只支持表锁。
  3. MEMORY存储引擎

    不支持事务

    表级锁定

    读写相互阻塞,写入不能读,读时不能写

    只缓存索引

    不支持外键约束

    不支持聚簇索引

    读取数据较快,占用资源少

    不支持MVCC 高并发 (多版本并发控制机制)

    崩溃恢复性较差

    mysql 5.5.5 前的默认数据引擎(show engines; 查看)

    • 不支持外键
    功 能MYISAMMemoryInnoDBArchive
    存储限制256TBRAM64TBNone
    支持事物NoNoYesNo
    支持全文索引YesNoNoNo
    支持数索引YesYesYesNo
    支持哈希索引NoYesNoNo
    支持数据缓存NoN/AYesNo
    支持外键NoNoYesNo

十三.MySQL行锁与表锁

  1. 行锁:MySQL中锁定粒度最细的一种锁,表示只针对当前操作的行进行加锁。行级锁能大大减少数据库操作的冲突。其加锁粒度最小,但加锁的开销也最大。行级锁分为共享锁和排他锁InnoDB存储引擎默认采用行锁InnoDB与MyISAM的最大不同有两点:一是支持事务(TRANSACTION);二是采用了行级锁。

    特点:行锁开销大,加锁慢;会出现死锁;锁定粒度最小,发生锁冲突的概率最低,并发度也最高。

  2. 表锁:MySQL中锁定粒度最大的一种锁,表示对当前操作的整张表加锁,它实现简单,资源消耗较少,被大部分MySQL引擎支持。最常使用的MyISAM与InnoDB都支持表级锁定。表级锁定分为表共享读锁(共享锁)与表独占写锁(排他锁)。

    特点:表锁开销小,加锁快,无死锁,锁定粒度大,发生锁冲突的概率最高,并发最低。

十四.MySQL索引有哪些类型

  1. 普通索引:允许重复的值
  2. 唯一索引:不允许有重复的值
  3. 主键索引:数据库自动为我们的主键创建索引,如果我们没有指定主键,它会根据没有 null 的唯一索引创建主键索引,否则会默认根据一个隐藏的 rowId 作为主键索引
  4. 全文索引,用来对文本域进行索引,比如 text,varchar,只针对 MyISAM 有效

十五.索引方式有哪些

B+树和 hash,Myisam 和 innodb 都不支持 hash。

十六.索引失效的情况有哪些

  1. like 以%开头,索引无效;当like前缀没有%,后缀有%时,索引有效。
  2. or语句前后没有同时使用索引。
    • 当or左右查询字段只有一个是索引,该索引失效,只有当or左右查询字段均为索引时,才会生效
  3. 组合索引,不是使用第一列索引,索引失效。
  4. 如果列类型是字符串,那一定要在条件中将数据使用引号引用起来,否则不使用索引
    • 数据类型出现隐式转化。如varchar不加单引号的话可能会自动转换为int型,使索引无效,产生全表扫描。
  5. 在索引列上使用 IS NULL 或 IS NOT NULL操作。
    • 索引是不索引空值的,所以这样的操作不能使用索引
  6. 在索引字段上使用not,<>,!=。
    • 不等于操作符是永远不会用到索引的,因此对它的处理只会产生全表扫描。 优化方法: key<>0 改为 key>0 or key<0。
  7. 对索引字段进行计算操作、字段上使用函数。
  8. 当全表扫描速度比索引速度快时,mysql会使用全表扫描,此时索引失效。
    • 如果mysql估计使用全表扫描要比使用索引快,则不使用索引

十七.MySQL索引的数据结构,B+树的特点

  1. 数据结构:B+树,HASH。
  2. 特点
    • 非叶子节点仅具有索引作用,也就是说,非叶子节点只能存储Key,不能存储value
    • 树的所有叶节点构成一个有序链表,可以按照key排序的次序依次遍历全部数据。

十八.MySQL主从复制原理

  1. 主要依靠 binlog 来实现的,它记录的是所有的 DDL,DML,TCL 操作
  2. 当主库的数据发生改变时,会将改变记录保存到 binloga2 中
  3. 主库新开一个线程将 binlog 内容发送到从库
  4. 从库会发起一个 I/O 线程请求主库的 binlog,并保存到中继日志中
  5. 从库新开一个 SQL 线程,读取中继日志并解析成具体操作,从而将主库更新的内容写到了从库中

十九.集群模式有哪些,分别有什么优缺点?

  1. 主从复制:一主一从,一主多从,主负责读写,从只能读,一对一或一对多关系。
  2. 哨兵模式:基于主从模式,哨兵实际上是一个单独进程,用来监听主服务是否宕机,如果宕机则将从转为主,并且通知其他的服务器修改配置文件,让它们切换主机。哨兵模式也可配置多哨兵,多哨兵之间互相监控。
  3. 集群模式:集群是将应用复制成多个相同应用,分散在不同服务器,每个服务器都独立运行相同的代码,可以分散服务器压力解决高并发问题,同时也能预防单点节点故障,就是一台服务器故障并不影响其他服务器正常运行,但没有解决单体应用代码臃肿,业务复杂,维护性差等问题。

常见的MySQL面试题有哪些?

本文主要介绍我在公司招聘的时候,主要问应聘者的一些问题,希望对换工作的同行及在使用过程中有些疑问的同行有所帮助

1. MySQL海量数据优化

优化问题主要从SQL优化、事务级别调整、MySql配置参数调整做起

1.1. SQL优化

  • 避免使用OR
  • 不要使用like %xx %在左边时索引失效
  • 使用复合索引时没有遵循最左匹配原则
  • 不要让数据类型出现隐式转化
  • 不要在索引字段上使用not,<>,!=,一样会导致索引失效
  • 分解关联查询
  • 小表驱动大表 即小的数据集驱动大的数据集

1.2. 事务级别调整

首先了解下事务的隔离级别,数据库共定义了四种隔离级别:

  • Serializable:可避免脏读、不可重复读、虚读情况的发生。(串行化)
  • Repeatable read:可避免脏读、不可重复读情况的发生。(可重复读)
  • Read committed:可避免脏读情况发生(读已提交)。
  • Read uncommitted:最低级别,以上情况均无法保证。(读未提交)

可以通过 set transaction isolation level 设置事务隔离级别来提高性能

1.3. MySql配置参数

#基础配置
datadir=/data/datafile
socket=/var/lib/mysql/mysql.sock
log-error=/data/log/mysqld.log
pid-file=/var/run/mysqld/mysqld.pid
character_set_server=utf8#允许任意IP访问
bind-address = 0.0.0.0#是否支持符号链接,即数据库或表可以存储在my.cnf中指定datadir之外的分区或目录,为0不开启#symbolic-links=0#支持大小写
lower_case_table_names=1#二进制配置
server-id = 1
log-bin = /data/log/mysql-bin.log
log-bin-index =/data/log/binlog.index
log_bin_trust_function_creators=1
expire_logs_days=7
sql_mode=STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION#InnoDB存储数据字典、内部数据结构的缓冲池,16MB已经足够大了。
innodb_additional_mem_pool_size = 16M#InnoDB用于缓存数据、索引、锁、插入缓冲、数据字典等#如果是专用的DB服务器,且以InnoDB引擎为主的场景,通常可设置物理内存的60%#如果是非专用DB服务器,可以先尝试设置成内存的1/4
innodb_buffer_pool_size = 4G#InnoDB的log buffer,通常设置为 64MB 就足够了
innodb_log_buffer_size = 64M#InnoDB redo log大小,通常设置256MB 就足够了
innodb_log_file_size = 256M#InnoDB redo log文件组,通常设置为 2 就足够了
innodb_log_files_in_group = 2
innodb_file_per_table = 1#InnoDB共享表空间初始化大小,默认是 10MB,改成 1GB,并且自动扩展
innodb_data_file_path = ibdata1:1G:autoextend#设置临时表空间最大4G
innodb_temp_data_file_path=ibtmp1:500M:autoextend:max:4096M#启用InnoDB的status file,便于管理员查看以及监控
innodb_status_file = 1#当设置为0,该模式速度最快,但不太安全,mysqld进程的崩溃会导致上一秒钟所有事务数据的丢失。#当设置为1,该模式是最安全的,但也是最慢的一种方式。在mysqld 服务崩溃或者服务器主机crash的情况下,binary log 只有可能丢失最多一个语句或者一个事务。#当设置为2,该模式速度较快,也比0安全,只有在操作系统崩溃或者系统断电的情况下,上一秒钟所有事务数据才可能丢失。
innodb_flush_log_at_trx_commit = 1
max_connections=600
max_connect_errors=1000
max_user_connections=400#设置临时表最大值,这是每次连接都会分配,不宜设置过大 max_heap_table_size 和 tmp_table_size 要设置一样大
max_heap_table_size = 100M
tmp_table_size = 100M#每个连接都会分配的一些排序、连接等缓冲,一般设置为 2MB 就足够了
sort_buffer_size = 2M
join_buffer_size = 2M
read_buffer_size = 2M
read_rnd_buffer_size = 2M#建议关闭query cache,有些时候对性能反而是一种损害
query_cache_size = 0
key_buffer_size = 8M
long_query_time = 120
slow_query_log=1 #开启mysql慢sql的日志
log_output=table,File #日志输出会写表,也会写日志文件,为了便于程序去统计,所以最好写表
slow_query_log_file=/data/log/slow.log
innodb_buffer_pool_dump_at_shutdown=1
innodb_buffer_pool_load_at_startup=1#打印deadlock日志
innodb_print_all_deadlocks=1

2. MySql数据表分区如何设计

数据表分区主要是解决监控数据过大造成的单表数据量过大,在存储及查询的过程中对性能造成影响,通过数据表分区,减小数据文件的大小,提高磁盘读写性能。

分区设计:

  • 时间阀值需求,指标明细保留90天,趋势数据保留3年
  • 监控的指标数据需要能查询90天内的明细,所以原始明细数据保留90天,指标多及监控间隔时间短,必然产生大量的数据
  • 每天一个分区存储原始数据
  • 统计趋势数据,及删除超过90天的明细数据

数据表分区规划示意图

常见的MySQL面试题有哪些?_查询缓存

3. 如何启用Mysql查询缓存

数据库优化中,除了Sql本身之外,数据库本身的优化也是很重要的一个环节,缓存就是其中一项。

查看查询缓存情况:

mysql> show variables like %query_cache%; 
(query_cache_type 为 ON 表示已经开启)
+------------------------------+----------+| Variable_name | Value |
+------------------------------+----------+
| have_query_cache | YES || query_cache_limit | 1048576 |
| query_cache_min_res_unit | 4096 || query_cache_size | 20971520 |
| query_cache_type | ON || query_cache_wlock_invalidate | OFF |
+------------------------------+----------+

如果不是ON,修改/etc/my.cnf配置文件以开启查询缓存:

[mysqld]中添加:

query_cache_size = 20M
query_cache_type = ON

重启mysql服务使配置查询缓存配置生效:

> service mysql restart

4. MySQL配置文件字符集可以通过指令改吗?

可以的,MySql8.x支持动态修改配置参数

1、可以的,通过 set global 命令直接修改,不用重启mysql

2、要是8.x 可以用 set persist 新特性

示例:

mysql> set persist max_connections=default;
Query OK, 0 rows affected (0.00 sec)

mysql> select * from performance_schema.persisted_variables;
+-----------------+----------------+
| VARIABLE_NAME | VARIABLE_VALUE |
+-----------------+----------------+
| max_connections | 151 |
+-----------------+----------------+
1 row in set (0.00 sec)
mysql> show variables like %max_connections%;
+------------------------+-------+
| Variable_name | Value |
+------------------------+-------+
| max_connections | 151 |
| mysqlx_max_connections | 100 |
+------------------------+-------+
2 rows in set (0.01 sec)

主要分享低代码、微服务、容器化、SAAS‬、系统架构方面的的‬内容‬‬,希望‬大家‬点赞‬,评论,关注‬。

以上是关于常见数据库优化面试题的主要内容,如果未能解决你的问题,请参考以下文章

面试题:在日常工作中怎么做MySQL优化的?

面试题:在日常工作中怎么做MySQL优化的?

Mysql面试题及千万级数据查询优化

:MySQL数据库第21节:MySQL - 必知必会(上)

MySQL面试题之如何优化一条有问题的SQL语句?

mysql索引优化面试题