目录
1. DDL,DML,DCL的区别?
2. ACID是什么?事务是什么?
3. InnoDB和MyISAM的区别
4. 索引有哪些类型?
5. 为什么InnoDB存储引擎选用B+树而不是B树?
6. 什么情况索引会失效?
7. MySQL排查问题的手段有哪些?
8. MySQL性能优化方式?
9. SQL内连接和外连接的区别?
10. MySQL有哪些搜索引擎?
11. 百万数据如何快速查询?
12. 数据库三范式?
13. 索引如何优化?
14. MySQL的事务隔离级别? 并发情况下引起的问题:
15. MySQL怎么恢复半月前的数据?
16. MySQL有哪些部分组成,分别用来做什么?
17. MySQL中有哪几种锁?
18. char和varchar的区别?
19. 可以使用多少列创建索引
20. MySQL支持事务吗?
21. 简单描述下MySQL中,索引,主键索引,唯一索引,联合索引的区别,对数据库有什么影响(读写方面)
22. 哪种count性能最好?
23. MySQL存储IP地址?
24. select语句的完整执行流程顺序
25. 数据库设计规范
25. 聚簇索引和非聚簇索引的区别?
1. DDL,DML,DCL的区别?
- DDL:数据定义语言: 一般用来堆数据库表进行结构调整,例如: Create, Drop, Alter
- DML:数据操作语言: 对数据进行增删改查操作,Insert,Delete,Update,Select
- DCL:数据控制语言: grant, commit, rollback
2. ACID是什么?事务是什么?
A(Atomictiy ): 原子性, 事务要么被全部执行,要么全不执行
C(Consistency): 一致性, 事务执行使得数据库从一种正确状态转换到另一种正确状态
I(ISolation): 隔离性, 在事务正确提交前, 不允许把该事务对数据的改变提供给其他事物
D(Durability): 持久性, 事务正确提交后,永久保存在数据库, 即使事务提交后有其他故障, 事务处理结果也会保存.
可以这么理解事务: 事务就是被绑定在一起作为一个逻辑工作单元的SQL语句分组 如果任何一个语句操作失败,那么整个操作被失败,以后操作就会有回滚到操作前的状态,或者上一节点. 为了确保要么执行,要么不执行,可以使用事务. 要将有组语句作为事务考虑,就需要通过ACID测试,即原子性,一致性,隔离性,持久性.
事务: 事务是作为一个单元的一组有序的数据库操作,组中所有的数据成功,则事务操作成功,组中有一个失败,则事务不成功. 所有操作完成,则事务提交,其修改将作用于所有其他数据库进程. 如果一个操作失败, 则事务回滚, 该事务的所有操作将被取消.
3. InnoDB和MyISAM的区别
MySQL默认InnoDB存储引擎,它的事务隔离级别为可重复读,适合比较庞大的应用场景.
4. 索引有哪些类型?
5. 为什么InnoDB存储引擎选用B+树而不是B树?
- B+树是基于B树和叶子节点顺序访问指针进行的,它具有B树的平衡性,并且通过顺序访问指针来提高区间查询的性能.
- 在B+树中,一个节点中的key从左到右非递减排列,如果某个指针的左右相邻key分别是key i和key i+1,并且不为null,则该指针指向节点的所有key大于等于key i 且小于等于key i+1.
- 进行查找操作时,首先在根节点进行二分查找,找到一个key所在的指针,然后递归地在指针所指向的节点进行查找.直到查到叶子节点,然后在叶子节点上进行二分查找,找出key所对应的data.
- 总结:用B+树不用B树考虑的是IO对性能的影响,B树的每个节点都会存储数据,而B+树只有叶子节点才存储数据,所以查找相同的数据量的情况下,B树的高度就会更高,IO更加频繁,数据库索引是存储在磁盘上的,当数据量大时,就不能把整个索引全部加载到内存了,只能逐一加载每一个磁盘页(对应索引树的节点)
6. 什么情况索引会失效?
- 索引列参与表达式计算: select 'sname' from 'stu' where 'age'+10 = 50;
- 函数运算: select 'sname' from 'stu' where left('date',4) > 2000;
- %在前的 模糊查询: select 'sname' from 'stu' where 'sname' like '%张'; -- 不走索引
- 字符串与数字比较: select * from 'stu' where 'phone' = 1888 --不走索引
- 查询条件中有or,即使其中有条件字段带索引也不会走索引,除非所有条件字段都带索引:
- 正则表达式不走索引
- MySQL优化器不使用索引
7. MySQL排查问题的手段有哪些?
- 使用Explain 查询SQL执行计划
- 开启慢查询日志,查看慢查询的SQL
- 使用show processlist 查看当前所有的连接信息
8. MySQL性能优化方式?
- 服务器优化(更换高性能cpu,内存,网络,磁盘等硬件)
- 表设计的优化: 字段长度控制.增加必要的索引
- SQL优化: 避免SQL不命中索引的情况
- 架构部署优化: 一主多从集群的方式部署
- 编码优化实现读写分离
9. SQL内连接和外连接的区别?
- 内连接: inner join 或 join 利用了where子句对多表连接形成的笛卡尔积进行筛选,说白了内连接就是获取两个表之间的公共部分
- 左外连接: 获取左表的内容使用左外
- 右外连接: 获取右表的内容使用右外
10. MySQL有哪些搜索引擎?
- InnoDB: 它是一个事务安全的存储引擎,它具备提交,回滚以及崩溃恢复的功能用于保护用户数据,InnoDB的行级锁定以及Oracle风格的一致性无锁读提升了它的多用户并发数及性能.InnoDB将用户数据存储在聚集索引以减少查询带来的IO开销,为了保证数据的完整性,InnoDB还支持外键约束
- MyISAM:它既不支持事务也不支持外键,优点是访问速度快,但是表级别的锁定限制了它在读写负载方面的性能,因此它经常用于只读或者以读为主的数据场景
- Memory: 在内存中存储所有的数据,应用于非关键数据快速查找的场景,它的表访问非常快,因为存放在内存中,并且默认使用HASH索引,但是服务一旦关闭,表中数据丢失
11. 百万数据如何快速查询?
- 方式一: 直接使用数据库提供的SQL语句 select * from 表名 limit x,y ;
- 方式二: 建立主键索引或唯一索引,利用索引
- 方式三: 基于索引再排序
- 此方法需要用到limit分页,MySQL大数据量使用limit分页,随着页码增大,效率会越低下.后续对limit分页优化:
- 优化方案: 对于有where条件又走limit的,必须设计一个索引,将where放在第一位,limit主键放到第二位,并且只能select 主键 select* from 表 where id > #{id} limit #{limit} (有序id)
- 方案二: 分表: 按数据库id分成多个小表,每个小表设置索引.查询接口根据id指向小表.如果数据量非常大,考虑分库
12. 数据库三范式?
- 第一范式: 属性不可再分
- 第二范式: 在第一范式的基础上,要求每行必须唯一,通常需要加一列,存储唯一标识 被称为主键
- 第三范式: 在第二范式基础,数据库中不包含其他表存在的非主键信息;
1. 每列只有一个值,
2.每行都能被区分
3. 每个表都不包含其他表非主键信息
13. 索引如何优化?
- 尽量使用主键查询,聚簇索引上存储了全部数据,相比普通索引,减少了回表消耗
- mysql5.6以后引入了索引下推优化, 通过适当的联合索引减少回表消耗
- 频繁查询某些数据,考虑使用覆盖索引
- 联合索引将高频字段放在最左边
14. MySQL的事务隔离级别?
并发情况下引起的问题:
- 脏读(Dirty read): 当一个事务正在访问数据并且对其进行了修改,但是还没提交事务,这时另外一个事务也访问了这个数据,然后使用了这个数据,因为这个数据还没提交到数据库,所以另外一个事务读取的数据就是"脏数据", 这种行为就是"脏读", 依据"脏数据"所做的操作可能是会出现问题的.
- 修改丢失(Lost of modify):是指一个事务读取一个数据时,另外一个数据也访问了该数据,那么在第一个事务修改了这个数据之后,第二个事务也修改了这个数据.这样第一个事务内的修改结果就被丢失,这种情况被称为修改丢失. 例如: 事务A从表中读取a=10,事务B也读取a=10,事务A修改a=a+1,事务B也修改a=a+1,最终结果都是11,但是A的修改记录丢失了.
- 不可重复读(Unrepeatableread): 在一个事务内多次读取同一个数据,在这个事务还没结束时,另一个事务也访问了这个数据并对这个数据进行了修改,那么就可能造成第一个事务两次读取的数据不一致,这种情况被称为不可重复读.
- 幻读(Phantom read): 幻读与不可重复读类似,幻读是指一个事务读取了几行数据,这个事务还没结束,接着另外一个事务插入了一些数据,随后的查询中,事务读取到了的数据就会比原本读的多,就好像发生幻觉一样,所以称之为幻读.
不可重复读和幻读的区别:
- 不可重复读重点是修改,幻读重点是新增或者删除.
- 例一: 事务1的A员工读取自己的工资为4100的操作还没结束,事务2的B员工修改A员工的工资为3000,A员工再读自己工资的时候就变成3000,这就是不可重复读.
- 例二: 例如工资表中大于2000的有10人, 事务1读取大于2000的人查询到10条记录. 事务2查询大于2000的人,事务1再查询就有11条记录,这就是幻读.
事务的特性:
- 读未提交(RU): 一个事务还没提交,它做的变更就能被别的事物看到 (可能造成脏读,不可重复读,幻读)
- 读提交(RC): 一个事务提交后,做的变更才会被其他事务看到 (避免脏读,但是可能造成不可重复读,幻读)
- 可重复读(RR): 一个事务执行过程中看到的数据,总是跟这个事务在启动时看到的数据一致,当然在可重复读隔离级别下,未提交变更对其他事务也是不可见的 (避免脏读,不可重复读,可能造成幻读)
- 串行化(S): 对于同一行记录,读写都会加锁,出现读写锁冲突时,后访问的事务必须等待前面的事务执行完成才能执行 (避免脏读,不可重复读,幻读 )
-
隔离级别 |
脏读 |
不可重复读 |
幻读 |
读未提交 |
√ |
√ |
√ |
读提交 |
× |
√ |
√ |
可重复读 |
× |
× |
√ |
可串行化 |
× |
× |
× |
15. MySQL怎么恢复半月前的数据?
通过整库的备份+binlog进行恢复,前提要有定期整库备份且保存了binlog日志
16. MySQL有哪些部分组成,分别用来做什么?
- Service:
- 连接器: 管理连接,权限验证
- 分析器: 词法分析, 语法分析
- 优化器: 执行计划生成,索引的选择
- 执行器:操作存储引擎,返回执行结果
- 存储引擎: 存储数据,提供读写接口
17. MySQL中有哪几种锁?
- 表级锁: 开销小,加锁快,不会出现死锁;锁粒度大,发生锁冲突概率最高,并发度低
- 行级锁: 开销大,加锁慢,会出现死锁,锁粒度小,冲突概率最低,并发度最高
- 页面锁: 开销和加锁时间介于表锁和行锁之间,会出现死锁;粒度介于之间,并发度一般
18. char和varchar的区别?
- char和varchar类型存在存储的检索的不同
- char为声明时固定长度,范围是1到255,当char值被存储,会用空格填充到特定长度.
19. 可以使用多少列创建索引
20. MySQL支持事务吗?
- 默认模式下,mysql是autocommit模式,所有数据库更新操作自动提交,不支持事务
- MySQL表类型是InnoDB Tables或者BDB tables 可以使用事务,使用Set,autocommit = 0就可以使用MySQL允许非autocommit模式,在非autocommit模式下,必须使用commit提交更改,或者使用rollback回滚.
21. 简单描述下MySQL中,索引,主键索引,唯一索引,联合索引的区别,对数据库有什么影响(读写方面)
- 索引是一种特殊文件(InnoDB数据表上的索引是表空间的组成部分),包含对数据表里所有数据的指针
- 普通索引(由key或者index定义的索引)的唯一任务是加快数据访问速度
- 主键,是一种特殊的唯一索引, 在一张表中只能定义一个主键索引,主键用于标识一条记录,使用关键字primary key创建
- 索引可以覆盖多个数据列,如index(A,B)索引,这就是联合索引
- 索引可以极大的提高查询速度,降低插入,删除,更新表的速度,因为执行这些操作,还需要操作所索引文件
22. 哪种count性能最好?
按照性能排序: count(*) = count(1) > count(主键) > count(字段)
23. MySQL存储IP地址?
可以将IP地址转换成整形数据存储,性能更好,占用更小.
mysql提供两个方法处理ip :
- INET_ATON(); 把ip转为无符号整型(4--8位)
- INET_NTOA(): 把整形ip转换为地址
插入数据前,先用INET_ATON()把ip转换为整型,显示数据,使用INET_NTOA()把整型ip转为地址
24. select语句的完整执行流程顺序
- from 子句组装来自不同数据源的数据
- where子句基于指定的条件对记录进行筛选
- group by子句将数据划为多个分组
- 使用聚合数进行计算
- 使用having子句筛选分组
- 计算所有表达式
- select 的字段
- 使用order by 排序
25. 数据库设计规范
- 基础规范
- 表存储引擎必须使用InnoDB,表字符默认utf8,必要的时候使用utf8mb4(存储表情符号)
- 禁止使用存储过程,视图,触发器,Event
- 禁止数据库存大文件,譬如照片,可以在数据库中存储路径
- 禁止线上做压力测试
- 测试,开发,线上数据库环境必须隔离
- 命名规范
- 库名,表名,列名必须小写,采用下划线分隔
- 库名,表名,列名长度不要超过32字符
- 库备份必须以bak为前缀,日期为后缀
- 从库必须-s为后缀
- 备份库以-ss为后缀
- 表设计规范
- 单实例表个数控制在2000以内
- 单表个数控制在1024以内
- 表必须有主键,推荐使用UNSIGNED整数为主键(无符号整数)
- 禁止使用外键
- 建议将大字段,访问频度低的字段拆分到单独的表存储
- 列设计规范
- 根据业务区分使用tinying/int/bigint,分别占用1/4/8字节
- 根据业务使用char/varchar(字段长度基本固定推荐char,字段长度相差大用varchar)
- 必须把字段定义为notnull并设置默认值
- 根据业务使用datetime/timestamp
- 使用int unsigned存储ipv4地址
- 使用varchar(20)存储手机号
- 索引规范
- 唯一索引使用 uniq_[字段名] 来命名
- 非唯一索引使用 idx_[字段名]
- 单张表索引控制在5个内
- 组合索引字段不超过5个
- 不建议在频繁更新的字段上加索引
- 非必要不join查询,如果join查询,被join的字段必须类型相同,并建立索引
- SQL规范
- 禁止使用select *
- insert必须指定字段, 禁止insert into T values()
- 隐式类型转换使索引失效,导致全表扫描
- 禁止where条件使用函数或表达式
- 禁止负向查询以及%开头的模糊查询
- 禁止大表join和子查询
- 同一字段or必须改为in,in的值必须少于50个
- 应用程序必须捕获SQL异常
25. 聚簇索引和非聚簇索引的区别?
都是B+树的数据结构
- 聚簇索引: 将数据存储与索引放在一块,并且按照一定顺序组织的,找到索引也就找到了数据,数据的物理存放顺序与索引顺序一致,即: 只要索引是相邻的,那么对应的数据也一定是相邻的存放在磁盘上
- 非聚簇索引: 叶子节点不存放数据,存储的是数据行地址,也就是说根据索引查找到数据行的位置再取磁盘查找数据,这个类似书的目录.我们要找哪一章的哪一节 就找到页码再去寻找
- 优点:
- 查询通过聚簇索引可以直接获取数据,相比非聚簇索引需要第二次查询效率高.
- 聚簇索引对于范围查询效率很高,因为数据是按照大小排列的
- 聚簇索引适合在排序的场合,非聚簇索引不适合
- 缺点;
- 维护索引很昂贵,特别是插入新行或主键被更新导致需要分页的时候.建议大量插入后,选择在负载较低的时间段,通过OPTIMIZETABLE优化表,因为必须移动的行数据可能造成碎片
- 表因为使用uuid(随机id)作为主键,使数据存储稀疏, 就会出现聚簇索引可能比全表扫描更慢,所以建议使用int的auto_increment作为主键
- 如果主键比较大,那么辅助索引会更大,因为辅助索引的叶子存储的使主键值,过长的主键会导致非叶子节点占用更多的物理空间.