写在后面

Xmind文件获取:GitHub 继续更新中,别忘了 star 喔~

@TOC
「Java学习+面试指南」思维导图,计算机自学指南,包含Java根底、JVM、数据库、mysql、redis、计算机网络、算法、数据结构、操作系统等,后盾技术栈/架构师之路/全栈开发社区,阿里,腾讯,百度,美团,头条等春招/秋招/校招/面试

思维导图(png格局可下载放大)

mysql

事务

四大个性(ACID)

  • 原子性

    • 要么全副实现,要么齐全不起作用
  • 一致性

    • 多个事务对同一个数据读取的后果是雷同的
  • 隔离性

    • 各并发事务之间数据库是独立的
  • 持久性

    • 数据的扭转是长久的

  • 脏读

    • A读,B读,A回滚,B不正确
  • 不可反复读

    • A读1,B写2,A读2
  • 幻读

    • A读2条,B删了1条,A读1条

四个隔离级别

  • READ-UNCOMMITTED(读取未提交)

    • 容许读取尚未提交的数据

      • 3
  • READ-COMMITTED(读取已提交)

    • 容许读取并发事务曾经提交

      • 阻止脏读
  • REPEATABLE-READ(可反复读)

    • 屡次读取后果都是统一

      • 阻止脏读和不可反复读
  • SERIALIZABLE(可串行化)

    • 顺次一一执行
  • 隔离机制的实现基于锁机制和并发调度
    (MVVC(多版本并发管制),通过保留批改的旧版本信息)
  • Mysql 默认采纳的 REPEATABLE_READ隔离级别,分布式事务SERIALIZABLE(可串行化)
    Oracle 默认采纳的 READ_COMMITTED隔离级别

  • Read Uncommitted

    • 不须要加共享锁,不会跟被批改的数据上的排他锁抵触
  • Read Committed

    • 加共享锁,语句执行完当前开释共享锁
  • Repeatable Read

    • 须要加共享锁,必须期待事务执行结束当前才开释共享锁
  • SERIALIZABLE

    • 锁定整个范畴的键,并始终持有锁,直到事务实现

粒度

  • 表级锁

    • 开销小,加锁快
    • 锁定粒度大,收回锁抵触的概率最高,并发度最低
    • MYISAM与INNODB
  • 行级锁

    • 开销大,加锁慢
    • 锁定粒度最小,产生锁抵触的概率最低,并发度也最高
    • INNODB
  • 页级锁

    • 开销和加锁工夫界于表锁和行锁之间
    • 一次锁定相邻的一组记录
    • 并发度个别

类别

  • 共享锁
    读锁

    • 能够同时加上多个
  • 排他锁
    写锁

    • 只能够加一个
    • 其余的排他锁,共享锁都相斥

  • 乐观锁

    • 数据库中的锁机制
    • 多写的场景下
  • 乐观锁

    • 应用版本号机制或CAS算法实现
    • 写比拟少的状况下(多读场景)

基础知识

三大范式

  • 第一范式 列不可再分
  • 第二范式 非主键齐全依赖主键,不能局部依赖
  • 第三范式 非主键只依赖主键,不依赖非主键

权限表

  • user 用户账号信息,全局
  • db 账号各数据库的操作权限
  • table_priv 表级操作权限
  • column_priv 列级操作权限
  • host 给定主机

binlog

  • statement 批改数据的sql:缩小日志量、解决io,需保留上下文,函数之类无奈被复制
  • row 记录每一行的改变:全部记下来,信息多日志量大
  • mixed 一般用statement,无奈应用用row
  • MySQL主从复制,Master把它的二进制日志传递给slaves来达到master-slave数据统一的目标
  • 数据恢复:通过应用 mysqlbinlog工具来使复原数据

数据类型

  • 整数类型

    • TINYINT、SMALLINT、MEDIUMINT、INT、BIGINT,别离示意1字节、2字节、3字节、4字节、8字节整数
    • 加上UNSIGNED示意无符号
    • 指定长度:INT(11)只影响显示字符,须要和UNSIGNED ZEROFILL才有意义
    • int(20)

      • 显示字符的长度。20示意最大显示宽度为20,但仍占4字节存储,存储范畴不变,int(1)和int(20)存储和计算均一样
      • 不影响外部存储,只是影响带 zerofill 定义的 int 时,后面补多少个 0,易于报表展现
  • 实数类型

    • DECIMAL能够用于存储比BIGINT还大的整型,能存储准确的小数。
    • 而FLOAT和DOUBLE是有取值范畴的,并反对应用规范的浮点进行近似计算。
    • 计算时FLOAT和DOUBLE相比DECIMAL效率更高一些,DECIMAL你能够了解成是用字符串进行解决。
    • FLOAT类型4字节,DOUBLE类型8字节
  • 字符串类型

    • VARCHAR

      • VARCHAR用于存储可变长字符串,它比定长类型更节俭空间。
      • VARCHAR应用额定1或2个字节存储字符串长度。列长度小于255字节时,应用1字节示意,否则应用2字节示意。
      • VARCHAR存储的内容超出设置的长度时,内容会被截断。
    • CHAR

      • CHAR是定长的,依据定义的字符串长度调配足够的空间。
      • CHAR会依据须要应用空格进行填充不便比拟。
      • CHAR适宜存储很短的字符串,或者所有值都靠近同一个长度。
      • CHAR存储的内容超出设置的长度时,内容同样会被截断。
      • 长度固定,所以存取速度要比varchar快很多,甚至能快50%
        长度固定,所以会占据多余的空间,是空间换工夫的做法
    • 综合

      • 对于常常变更的数据来说,CHAR比VARCHAR更好,因为CHAR不容易产生碎片。
      • 对于十分短的列,CHAR比VARCHAR在存储空间上更有效率。
      • 应用时要留神只调配须要的空间,更长的列排序时会耗费更多内存。
      • 尽量避免应用TEXT/BLOB类型,查问时会应用长期表,导致重大的性能开销。
      • 性能角度(char更快)和节俭磁盘空间角度(varchar更小
      • chart(10)和varchar(10)
        示意存储数据的大小,即示意存储多少个字符

        • char(10)示意存储定长的10个字符,有余10个就用空格补齐,占用更多的存储空间
        • varchar(10)示意存储10个变长的字符,存储多少个就是多少个
          空格也按一个字符存储,这一点是和char(10)的空格不同的,char(10)的空格示意占位不算一个字符
      • 明码散列,盐,用户身份证号等固定长度的字符串应该应用char而不是varchar来存储,这样能够节俭空间且进步检索效率。
  • 日期和工夫类型

    • 尽量应用timestamp,空间效率高于datetime,
    • 用整数保留工夫戳通常不不便解决。
    • 如果须要存储微秒,能够应用bigint存储。

关键字

in 和 exists

  • in

    • 表面和内表作hash 连贯
  • exists

    • 对表面作loop循环,每次loop循环再对内表进行查问。
  • 两个表大小相当,那么用in和exists差异不大
  • 子查问表大的用exists,子查问表小的用in
  • not in,那么内表面都进行全表扫描,没有用到索引
    not exists的子查问仍然能用到表上的索引

UNION与UNION ALL

  • UNION ALL,不会合并反复的记录行
  • 效率 UNION 高于 UNION ALL

drop、delete与truncate

  • Delete

    • 可回滚
    • 表构造还在,删除表的全副或者一部分数据行
    • 删除速度慢,须要逐行删除
  • Truncate

    • 不可回滚
    • 表构造还在,删除表中的所有数据
    • 删除速度快
  • Drop

    • 不可回滚
    • 从数据库中删除表,所有的数据行,索引和权限也会被删除
    • 删除速度最快
  • 不再须要一张表的时候,用drop;在想删除局部数据行时候,用delete;在保留表而删除所有数据的时候用truncate。

引擎

Innodb引擎

  • ACID事务的反对
  • 行级锁,并发量高
  • 外键的束缚
  • INSERT、UPDATE、DELETE
  • B+树索引,Innodb 是索引组织表,聚簇索引,主键索引叶子节点存储着行数据,非主键索引的叶子节点存储的是主键和其余带索引的列数据
  • 哈希索引
  • 按主键大小有序插入
  • 更多的内存和存储,会在主内存中建设其专用的缓冲池用于高速缓冲数据和索引

MyIASM引擎

  • 可被压缩,存储空间较小
  • SELECT,读写插入为主
  • B+树索引,myisam 是堆表,非聚簇索引,叶子节点存储的是行数据地址,再寻址一次
  • 全文索引
  • 按记录插入程序保留
  • 以文件的模式存储,在跨平台的数据转移中会很不便

索引

优缺点

  • 长处

    • 放慢检索速度
    • 应用优化暗藏器,进步零碎的性能
  • 毛病

    • 创立索引和保护索引要消耗工夫
    • 动静的保护,会升高增/改/删的执行效率
    • 占物理空间

应用场景

  • where
  • order by 没有用内部排序,有只有取出索引表某个范畴内的索引对应的数据
  • explain select……

    • possible_keys 可能
    • key 理论用到
  • 索引笼罩

    • 间接在索引表中查问而不会拜访原始数据(否则只有有一个字段没有建设索引就会做全表扫描)

类型

  • 主键索引: 不容许反复,不容许为NULL,一个表一个
  • 惟一索引: 不容许反复,容许为NULL值,一个表可多个
  • 一般索引: 没有唯一性的限度,容许为NULL值
  • 全文索引

数据结构

  • b+树

    • 不仅能够被用在=,>,>=,<,<=和between这些比拟操作符上,而且还能够用于like操作符
    • 非终端结点能够看成是索引局部
    • 叶子结点中蕴含了全副关键字的信息,及指向含这些关键字记录的指针
      数据对象的插入和删除仅在叶节点上进行
    • 2个头指针,一个是树的根节点,一个是最小关键码的叶节点
    • 人造反对范畴,有序
    • 防止不了回表查问数据,聚簇索引、笼罩索引间接通过索引
  • hash

    • 只能用于对等比拟
    • 等值查问更快

创立准则

  • 最左前缀匹配准则
    始终向右匹配直到遇到范畴查问
  • 较频繁作为查问条件
  • 更新频繁字段不适宜
  • 不能无效辨别数据的列不适宜
  • 有外键的数据列肯定要
  • 尽量的扩大索引,不要新建索引

创立形式

  • CREATE TABLE
  • ALTER TABLE
  • CREATE INDEX 不能创立PRIMARY KEY索引
  • 删除索引 alter table 表名 drop KEY 索引名

百万级别删除

  • 产生额定的对索引文件的操作,会升高增/改/删的执行效率
  • 能够先删除索引
  • 删除其中无用数据
  • 删除实现后从新创立索引

B树和B+树的区别

  • B树

    • 外部节点同时存储键和值,进步热点数据的查问效率
  • B+树

    • 外部节点只寄存键,一次性读入内存中能够查找的关键字也就越多,IO读写次数升高;
    • 由一条链相连,范畴查问;
    • 必须走一条从根节点到叶节点的路查问效率相当

聚簇索引与非聚簇索引

  • 聚簇索引

    • 数据存储与索引放到了一块
  • 非聚簇索引

    • 将数据存储于索引离开构造,回表查问
  • 在InnoDB中

    • 只有主键索引是聚簇索引
    • 如果没有主键,则筛选一个惟一键建设聚簇索引。
    • 如果没有惟一键,则隐式的生成一个键来建设聚簇索引。
    • 在聚簇索引之上创立的索引称之为辅助索引,总是须要二次查找,非聚簇索引都是辅助索引,像复合索引、前缀索引、惟一索引,辅助索引叶子节点存储的不再是行的物理地位,而是主键值
    • 非聚簇索引不肯定会回表查问,全副命中了索引不用

联结索引

  • 想要命中索引,须要依照建设索引时的字段程序挨个应用
  • 将查问需要频繁或者字段选择性高的列放在后面

其余

视图

  • 由根本表(实表)产生的表(虚表)
  • 建设和删除不影响根本表
  • 更新(增加,删除和批改)间接影响根本表
  • 来自多个根本表时,不容许增加和删除数据
  • 毛病

    • 性能
    • 批改限度

存储过程

预编译的SQL语句

  • 长处

    • 预编译过的,执行效率高
    • 间接寄存于数据库中,缩小网络通讯
    • 安全性高,有肯定权限
    • 能够重复使用
  • 毛病

    • 调试麻烦
    • 移植问题
    • 从新编译问题
    • 用户需要的减少会导致数据结构的变动

触发器

一段代码,当触发某个事件时,主动执行这些代码

关联查问

穿插连贯(笛卡尔积)

  • select r.,s. from r,s

内连贯

  • select r.,s. from r inner join s on r.c=s.c

左连贯

  • select r.,s. from r left join s on r.c=s.c

右连贯

  • select r.,s. from r right join s on r.c=s.c

全表连贯

mysql不反对

  • select r.,s. from r full join s on r.c=s.c
  • SELECT FROM A LEFT JOIN B ON A.id=B.id UNION SELECT FROM A RIGHT JOIN B ON A.id=B.id

优化

explain

  • 查看语句的执行打算
  • id

    • 示意一个查问中各个子查问的执行程序
      越大优先级越高,越先被执行
  • type

    • ALL 扫描全表数据
    • index 遍历索引
      索引物理文件全扫描,速度十分慢
    • range 索引范畴查找
    • ref 应用非惟一索引查找数据
    • consts 主键或者惟一索引
  • possible_keys

    • 可能应用的索引
  • key

    • 在查问中理论应用的索引

大表数据查问

  • 优化shema、sql语句+索引
  • 第二加缓存,memcached, redis
  • 主从复制,读写拆散
  • 垂直拆分,依据你模块的耦合度,将一个大的零碎分为多个小的零碎,也就是分布式系统
  • 程度切分,针对数据量大的表,这一步最麻烦,最能考验技术水平,要抉择一个正当的sharding key, 为了有好的查问效率,表构造也要改变,做肯定的冗余,利用也要改,sql中尽量带sharding key,将数据定位到限定的表下来查,而不是扫描全副的表;

超大分页

  • MySQL并不是跳过offset行,而是取offset+N行,而后返回放弃前offset行,返回N行,那当offset特地大的时候,效率就十分的低下
  • 先疾速定位须要获取的id段,而后再关联

    • SELECT a.* FROM 表1 a, (select id from 表1 where 条件 LIMIT 100000,20 ) b where a.id=b.id

分页

  • mysql> SELECT * FROM table LIMIT 5,10; // 检索记录行 6-15
  • mysql> SELECT * FROM table LIMIT 95,-1; // 检索记录行 96-last.
  • mysql> SELECT * FROM table LIMIT 5; //检索前 5 个记录行

慢查问日志

  • 用于记录执行工夫超过某个临界值的SQL日志
  • 配置项:slow_query_log
  • 优化

    • 是否load了额定的数据

      • 查问了多余的行并且摈弃掉了,可能是加载了许多后果中并不需要的列
    • 应用索引的状况
    • 数据量是否太大

      • 横向或者纵向的分表

自增ID还是UUID

  • 应用自增ID,不要应用UUID
  • 自增ID,那么只须要一直向后排列即可
  • UUID,因为到来的ID与原来的大小不确定,会造成十分多的数据插入,数据挪动
  • 没有主键,InnoDB会抉择一个惟一键来作为聚簇索引,如果没有惟一键,会生成一个隐式的主键。

定义为not null

  • null值会占用更多的字节,且会在程序中造成很多与预期不符的状况。

SQL语句优化

优化WHERE子句

  • 在 where 及 order by 波及的列上建设索引
  • 防止在 where 子句中对字段进行 null 值判断,否则将导致引擎放弃应用索引而进行全表扫描
  • 防止在 where 子句中应用!=或<>操作符
  • 防止在 where 子句中应用or 来连贯条件
  • in 和 not in 也要慎用
  • 防止在 where 子句中应用参数
  • 防止在 where 子句中对字段进行表达式操作
  • 防止在where子句中对字段进行函数操作

优化查问过程中的数据拜访

  • 查问不须要的数据

    • 应用limit解决
  • 多表关联返回全部列

    • 指定列名
  • 总是返回全部列

    • 防止应用SELECT *
  • 反复查问雷同的数据

    • 能够缓存数据

优化长难的查问语句

  • 应用尽可能小的查问是好的
  • 将一个大的查问分为多个小的雷同的查问
  • 合成关联查问

化特定类型的查问语句

  • count(*)会疏忽所有的列,不要应用count(列名)
  • 减少汇总表
  • 应用缓存

优化关联查问

  • ON或者USING子句中是否有索引
  • GROUP BY和ORDER BY只有一个表中的列

优化子查问

  • 优化GROUP BY和DISTINCT,应用索引来优化,是最无效的优化办法
  • 不须要ORDER BY,进行GROUP BY时加ORDER BY NUL

数据库优化

构造优化

  • 将字段很多的表分解成多个表
  • 减少两头表

    • 须要常常联结查问的表
  • 减少冗余字段

    • 表的规范化水平越高,表和表之间的关系越多,须要连贯查问的状况也就越多,性能也就越差。

cpu飙升

  • 看看外面跑的 session 状况,是不是有耗费资源的 sql 在运行

    • 找出耗费高的 sql,看看执行打算是否精确, index 是否缺失,或者切实是数据量太大造成

      • kill 掉这些线程

        • 进行相应的调整(比如说加索引、改 sql、改内存参数)之后,再从新跑这些 SQL
  • 每个 sql 耗费资源并不多,然而忽然之间,有大量的 session 连进来导致 cpu 飙升

    • 剖析为何连接数会激增,再做出相应的调整,比如说限度连接数等

大表优化

  • 限定数据的范畴
  • 读/写拆散

    • 主库负责写,从库负责读
  • 缓存

    • 应用MySQL的缓存,另外对重量级、更新少的数据能够思考应用利用级别的缓存
  • 分库分表

    • 垂直分区

      • 数据表列的拆分;某些列罕用,另外一些列不罕用
      • 使得行数据变小,在查问时缩小读取的Block数,缩小I/O次数
      • 会呈现冗余,须要治理冗余列,并会引起Join操作;对于应用层来说,逻辑算法减少开发成本
    • 程度分区

      • 数据表行的拆分,程度拆分最好分库
      • 长处

        • 升高在查问时须要读的数据和索引的页数,同时也升高了索引的层数,进步查问次数
        • 反对十分大的数据量存储,利用端革新也少
      • 毛病

        • 分片事务难以解决 ,跨界点Join性能较差,逻辑简单
        • 通常查问时须要多个表名,查问所有数据都需UNION操作
    • 数据库分片

      • 客户端代理

        • 分片逻辑在利用端,封装在jar包中,通过批改或者封装JDBC层来实现
      • 中间件代理

        • 在利用和数据两头加了一个代理层。分片逻辑对立保护在中间件服务中。
    • 问题

      • 事务反对

        • 数据库自身的分布式事务管理
        • 应用程序去帮助管制
      • 跨库join

        • 分两次查问实现。在第一次查问的后果集中找出关联数据的id,依据这些id发动第二次申请失去关联数据。
      • 跨节点的count,order by,group by以及聚合函数问题

        • 与解决跨节点join问题的相似,别离在各个节点上失去后果后在应用程序端进行合并
        • 能够并行执行,因而很多时候它的速度要比繁多大表快很多
      • ID问题

        • 自生成的ID无奈保障在全局上是惟一的
        • 在插入数据之前须要先取得ID,以便进行SQL路由,常见的主键生成策略
        • UUID

          • UUID十分的长,除占用大量存储空间外,最次要的问题是在索引上,在建设索引和基于索引进行查问时都存在性能问题。
      • 跨分片的排序分页

        • 排序字段非分片字段

          • 在不同的分片节点中将数据进行排序并返回,并将不同分片返回的后果集进行汇总和再次排序

主从复制

通过二进制日志(BINLOG)传输到从数据库上,而后将这些日志从新执行(重做);保持一致

作用

  • 主数据库呈现问题,能够切换到从数据库。
  • 能够进行数据库层面的读写拆散。
  • 能够在从数据库上进行日常备份。

解决问题

  • 数据分布:随便开始或进行复制,并在不同地理位置散布数据备份
  • 负载平衡:升高单个服务器的压力
  • 高可用和故障切换:帮忙应用程序防止单点失败
  • 降级测试:能够用更高版本的MySQL作为从库

流程

  • 主:binlog线程——记录下所有扭转了数据库数据的语句,放进master上的binlog中;
  • 从:io线程——在应用start slave 之后,负责从master上拉取 binlog 内容,放进本人的relay log中;
  • 从:sql执行线程——执行relay log中的语句;

解决方案

  • 应用mysql-proxy代理

    • 升高性能, 不反对事务
  • 应用AbstractRoutingDataSource+aop+annotation在dao层决定数据源

    • mybatis

      • 通过mybatis plugin拦挡sql语句,所有的insert/update/delete都拜访master库,所有的select 都拜访salve
        还须要重写一下DataSourceTransactionManager, 将read-only的事务扔进读库, 其余的有读有写的扔进写库
    • 应用AbstractRoutingDataSource+aop+annotation在service层决定数据源

      • 能够反对事务.