京东

1. 数据库的事务

事务是逻辑上的一组操作,要么都执行,要么都不执行。

何为 ACID 特性呢?

  1. 原子性Atomicity
  2. 一致性Consistency
  3. 隔离性Isolation
  4. 持久性Durability

InnoDB 引擎使用 redo log(重做日志) 保证事务的持久性,使用 undo log(回滚日志) 来保证事务的原子性,通过 锁机制MVCC 等手段来保证事务的隔离性( 默认支持的隔离级别是 REPEATABLE-READ )。

2. 建索引的注意事项

  1. 选择合适的字段创建索引:

    • 不为 NULL 的字段 :对于数据为 NULL 的字段,数据库较难优化
    • 被频繁查询的字段
    • 被作为条件查询的字段
    • 频繁需要排序的字段
    • 被经常频繁用于连接的字段
  2. 被频繁更新的字段应该慎重建立索引。

  3. 尽可能的考虑建立联合索引而不是单列索引: 磁盘空间

  4. 注意避免冗余索引 。

  5. 考虑在字符串类型的字段上使用前缀索引代替普通索引。

3. MySQL中的隔离级别

  • READ-UNCOMMITTED (读取未提交): 最低的隔离级别,允许读取尚未提交的数据变更
  • READ-COMMITTED (读取已提交): 允许读取并发事务已经提交的数据
  • REPEATABLE-READ (可重复读): 对同一字段的多次读取结果都是一致的,除非数据是被本身事务自己所修改
  • SERIALIZABLE (可串行化): 完全服从 ACID,所有的事务依次逐个执行
隔离级别脏读不可重复读幻读
READ-UNCOMMITTED
READ-COMMITTED×
REPEATABLE-READ××
SERIALIZABLE×××

不可重复读和幻读区别:

不可重复读的重点是修改比如多次读取一条记录发现其中某些列的值被修改,幻读的重点在于新增或删除比如多次查询同一条查询语句(DQL)时,记录发现记录增多或减少了。

4. 索引相关问题、组合索引、聚簇索引和非聚簇索引

image-20220314151525248

  • 二级索引又称为辅助索引,是因为二级索引的叶子节点存储的数据是主键。也就是说,通过二级索引,可以定位主键的位置。
  • 聚集索引即索引结构和数据一起存放的索引。主键索引属于聚集索引。
  • 非聚集索引即索引结构和数据分开存放的索引

5. SQL优化思路有哪些?如何定位低效的SQL,如何优化?explain的字段

6. B树与B+树的区别、哈希索引和B+ 的区别?

多路平衡查找树

  1. B 树& B+树两者有何异同呢?

    • B 树的所有节点既存放键(key) 也存放 数据(data),而 B+树只有叶子节点存放 key 和 data,其他内节点只存放 key。
    • B 树的叶子节点都是独立的;B+树的叶子节点有一条引用链指向与它相邻的叶子节点。
    • B 树的检索的过程相当于对范围内的每个节点的关键字做二分查找,可能还没有到达叶子节点,检索就结束了。而 B+树的检索效率就很稳定了,任何查找都是从根节点到叶子节点的过程,叶子节点的顺序检索很明显。
  2. 为什么MySQL 没有使用其作为索引的数据结构呢?

    • Hash 冲突问题

    • Hash 索引不支持顺序和范围查询:无法对表中的数据进行排序或者进行范围查询

7. InnoDB和Myisam的区别

区别InnoDBMyisam
是否支持行级锁行级锁表级锁
是否支持事务×
是否支持外键×
数据库异常崩溃后的安全恢复redo log×
是否支持 MVCC×

作者:代码界的小白 链接:https://leetcode-cn.com/circle/discuss/KLnm9d/

联合索引最左前缀匹配

我们都知道索引的底层是一颗B+树,那么联合索引当然还是一颗B+树,只不过联合索引的健值数量不是一个,而是多个。构建一颗B+树只能根据一个值来构建,因此数据库依据联合索引最左的字段来构建B+树。

最左前缀匹配原则

在mysql建立联合索引时会遵循最左前缀匹配的原则,即最左优先,在检索数据时从联合索引的最左边开始匹配,示例: 对列col1、列col2和列col3建一个联合索引

1
KEY test_col1_col2_col3 on test(col1,col2,col3);

联合索引 test_col1_col2_col3 实际建立了(col1)、(col1,col2)、(col,col2,col3)三个索引。

1
SELECT * FROM test WHERE col1=1 AND clo2=2 AND clo4=4

上面这个查询语句执行时会依照最左前缀匹配原则,检索时会使用索引(col1,col2)进行数据匹配。

注意

索引的字段可以是任意顺序的,如:

1
2
SELECT * FROM test WHERE col1=“1” AND clo2=“2”
SELECT * FROM test WHERE col2=“2” AND clo1=“1”

这两个查询语句都会用到索引(col1,col2),mysql创建联合索引的规则是首先会对联合合索引的最左边的,也就是第一个字段col1的数据进行排序,在第一个字段的排序基础上,然后再对后面第二个字段col2进行排序。其实就相当于实现了类似 order by col1 col2这样一种排序规则。

有人会疑惑第二个查询语句不符合最左前缀匹配:首先可以肯定是两个查询语句都包含索引(col1,col2)中的col1、col2两个字段,只是顺序不一样,查询条件一样,最后所查询的结果肯定是一样的。既然结果是一样的,到底以何种顺序的查询方式最好呢?此时我们可以借助mysql查询优化器explain,explain会纠正sql语句该以什么样的顺序执行效率最高,最后才生成真正的执行计划。

为什么要使用联合索引

  • 减少开销。建一个联合索引(col1,col2,col3),实际相当于建了(col1),(col1,col2),(col1,col2,col3)三个索引。每多一个索引,都会增加写操作的开销和磁盘空间的开销。对于大量数据的表,使用联合索引会大大的减少开销!
  • 覆盖索引。对联合索引(col1,col2,col3),如果有如下的sql: select col1,col2,col3 from test where col1=1 and col2=2。那么MySQL可以直接通过遍历索引取得数据,而无需回表,这减少了很多的随机io操作。减少io操作,特别的随机io其实是dba主要的优化策略。所以,在真正的实际应用中,覆盖索引是主要的提升性能的优化手段之一。
  • 效率高。索引列越多,通过索引筛选出的数据越少。有1000W条数据的表,有如下sql:select from table where col1=1 and col2=2 and col3=3,假设假设每个条件可以筛选出10%的数据,如果只有单值索引,那么通过该索引能筛选出1000W10%=100w条数据,然后再回表从100w条数据中找到符合col2=2 and col3= 3的数据,然后再排序,再分页;如果是联合索引,通过索引筛选出1000w10% 10% *10%=1w,效率提升可想而知!