- 索引的实现形式
- B-Tree索引,Hash索引,全文索引,单值索引、唯一索引、复合索引、聚簇索引、非聚簇索引等等,以及它们各自的特点
- 常见的优化手段,编码时有哪些要注意的
- 不要用select *
- 索引,最左原则,最好用覆盖索引
- 建表是注意字段长度,各系统对齐,不浪费字段,不常用的字段及大字段可以考虑单独建一张表(可以减少磁盘IO)
- 不要多张表join
- 不使用UUID作为主键
- B树与B+树的区别,与跳表的区别
- B+树是怎么保持平衡的
- MyISAM与Innodb的区别
- 事务 MyISAM不支持事务
- 锁 MyISAM只支持表锁,InnoDB支持行锁
- MVCC实现原理
- 表中只有(id =1 ,a=0)一条数据,下述操作结果是怎么样的
时刻 | Session A | Session B |
---|---|---|
时刻1 | begin select a from test where id = 1; | |
时刻2 | update test set a = a+1 where id = 1(此时这条数据加了行锁,sessionB无法更改,只有sessionA commit后才其他事务才可以修改) | |
时刻3 | select a from test where id = 1; | |
时刻4 | update test set a = a+1 where id = 1 | |
时刻5 | select a from test where id = 1; | |
时刻6 | commit; | |
时刻7 | select a from test where id = 1; |
-
常见的分库的方法
- range方法,根据时间段分库
- 京东接单框架的数据每天分一个表
- hash方法,根据业务字段进行hash
- range方法,根据时间段分库
-
mysql主从同步是怎么实现的,主从延迟怎么解决
- 优化网络
- 升级Slave硬件配置
- Slave调整参数,关闭binlog,修改innodb_flush_log_at_trx_commit参数值
- 升级MySQL版本到5.7,使用并行复制
-
数据库扩容,怎么迁移数据,迁移数据的注意事项。数据迁移中产生的脏数据怎么里。怎么校验数据的迁移结果
-
什么场景考虑分库分表,分库分表的缺点
-
MySQL的事务隔离级别
-
MySQL如何解决幻读问题,间隙锁是怎么加的,什么时间加的
-
索引不适用的条件
索引列上有函数,不满足最左前缀,使用了不等号,使用了范围查询,值类型不匹配等等
索引的分类 -
为什么mysql使用b+树而不是红黑树或者hashmap或者跳表
- 不使用红黑树是因为:
- 在增删改查的过程中,时间复杂度为log2n,而b+是logmN,体现在内存和磁盘的IO上,代价比较大。
- 特别是插入的时候,红黑树需要进行节点颜色调整,对于频繁的插入而言,这是一个耗时的过程,而b+树仅仅是页分裂问题。另外从并发交付来说,要么线程不安全,要么加锁虽然线程安全,但是牺牲了效率。
- 区间查找而言,b+树的叶子节点带有双向链表,因此比较方便。对于红黑树而言,虽然可以实现,比如通过中序遍历的方式,但是实现起来比较复杂。
- 不使用hashmap是因为
- 假设瓶颈不在hash数组上(hashmap由数组加链表构成),一方面,对于庞大数据量的链表来说,查找的时间复杂度为O(n)
- 另一方面从磁盘IO性能考虑,链表足够长,频繁的io会导致极差的性能
- 没有办法进行范围查找
- 不使用跳表是因为
- 虽然在区间查找上两者不相上下,如果纯粹基于内存工作,那就是redis。两者的主要区别,那就是一个是关系型,另一个是非关系型,redis是基于某个key进行排序构造的,如果像mysql哪样建立二级索引,那么每一个都是“聚簇索引”,得不偿失,维护也麻烦(就是说跳表无法解决索引问题)
- 还是数据关系型的问题,虽然说跳表这个结构也可以以Json格式来存储数据库的行数据,但是类似主外键关系、模糊查找等功能,无法提供或者提供起来较为繁琐
- 如果考虑到足够大的数据,大到需要使用硬盘的话,内存和磁盘进行io的内容会是什么?是跳表的每一层数据,前几层可能还好,越往下,可能不是一次页交换可以容纳下的,那么跳表在查找上的优势尽失,反观mysql,每次交换出来的非叶子节点都是索引,可查找范围大,io次数少,性能高
- 不使用红黑树是因为:
-
为什么redis使用跳表而不是红黑树或者hashmap
-
由上面分析可知,红黑树在内存工作效率更高,但是同样基于内存的redis为什么不用红黑树,区别在于红黑树范围查询太费劲,插入元素时进行的节点颜色调整太费解,同样的操作,跳表仅仅需要更新前后下三个指针即可,而且,红黑树这样做来保持平衡带来的查找优势对跳表来说并不明显
-
不使用hashmap,也是因为链表的操作太费时,远不如跳表这种链表的折半查找来的快
-
读写分离
- 为什么要读写分离
- 扩展读能力
- 怎么读写分离
MySQL原生支持主从复制,主库写数据,写binlog,从库同步主库的数据,向外提供读服务
- 为什么要读写分离
-
MySQL主从复制的原理
IO线程读binlog日志(记录了增删改操作),写入从库的relaylog中,从库的SQL线程,见relaylog 写入数据,从库读取binlog 写relay log ,写数据都是串行的 -
主从延迟相关
- 主库的并发越高,延迟就越大
- semi-sync 半同步复制 从库写到relay log即返回成功
- 主从延迟的解决方式:
- 将主库拆分,减少并发,减少延迟
- 打开并行复制(并行复制什么?)
- 代码层面的处理: 如 写后直接更新,而不要 “写”--> "查"--> "更新"
- 如果确实存在写后立即查询的场景,可以强制查“主库”,但这样就失去了读写的分离的意义,不推荐
-
分库分表中间件
- proxy方式的中间件 (有维护成本)
- cobar
- atlas(360公司开源)
- mycat
- client方式的中间件
- TDDL
- sharding-jdbc (支持分布式事务)
- proxy方式的中间件 (有维护成本)
-
分库分表的方式
- range方式, 按时间来分
- 优点
- 缺点
- hash方式: 选定一个键,进行hash
- 优点
- 缺点
- range方式, 按时间来分
-
分库分表数据迁移
- 停机迁移
- 不停机迁移:
- 双写: 既写老库也写新库
-
数据库动态扩容
- 数据库中间件
- 停机扩容:
- 从单库单表迁移到多库多表时经常使用
- 不停机扩容
- 初始设计时就设计大一点,如 32个库,每个库32张表,只扩数据库服务器,不扩表,可以减少代码修改
路由规则: id%32=库 (id/32)%32=表
- 初始设计时就设计大一点,如 32个库,每个库32张表,只扩数据库服务器,不扩表,可以减少代码修改
-
分布式id怎么生成
- 向全局数据库中生成id(支持的并发低但数据多)
- UUID
- 获取当前时间,并发高时容易出问题-->改进 时间戳+用户ID+业务含义编码
- 雪花算法: 64位 long型ID--》二进制(0|时间戳|机房|机器ID)
- 利用redis自增 (jd使用)
评论区