基本概念

  • 数据库管理系统(DBMS):用于数据的存储、 检索、管理和处理的数据库软件
  • 数据库(database):保存有组织的数据的容器(通常是一个文件或一组文件)。区分于DBMS(数据库管理系统),数据库是通过DBMS操作和创建的容器。
  • 数据库实例(instance):数据库由后台线程以及一个共享内存区组成,共享内存可以被运行的后台线程所共享,数据实例才是真正操作数据库文件的,在系统表现上是一个进程。
  • 表(table):某种特定类型数据的结构化清单。储存在表中的数据是一种类型的数据或清单,例如表可以保存客户清单、产品目录等。
  • 模式(schema):关于数据库和表的布局及特征信息。表具有一些特征,定义了数据在表中如何存储,描述这组信息的是模式。有时模式用作数据库的同义词
  • 列(column):表中的一个字段。所有表都是由一个或多个列组成的。
  • 数据类型(datatype):所容许的数据的类型。每个表列都有相 应的数据类型,它限制(或容许)该列中存储的数据。
  • 行(row):表中的一个记录。 也称记录(record)
  • 主键(primary key):一列(或一组列),其值能够唯一区分表中每个行。也被称为“键码”或“键”。
  • SQL(Structured Query Language):一种专门用来与数据库通信的结构化查询语言。几乎所有重要DBMS都支持SQL。 SQL不是一种专利语言,而且存在一个标准委员会,他们试图定义可供所有DBMS使用的SQL语法,但 事实上任意两个DBMS实现的SQL都不完全相同
  • MySQL:一种客户机-服务器数据库软件(DBMS)。优势在于成本(开源&免费)、性能、可信赖、简单
  • 字段(field):基本上与列(column)的意思相同,经常互换使用,不过数据库列一般称为列,而术语字段通常用在计算字段的 连接上
  • 数据库:是OLTP(联机事务处理)应用的场景,其存储的主要是与业务直接相关的数据,强调准确、低时延、高并发,如果没有特别强调,基本上数据库里只会去存储与业务相关的数据。
  • 数据仓库:OLAP(联机分析处理)是数据仓库系统的主要应用,其支持的对象只要是面向分析场景的应用,提供结构化的、主题化的数据提供给运营,做业务反馈和辅助决策用,同时,有些场景下,也可以由数据仓库对业务进行支持。(数据库一般用作实时服务,数据都是一些业务相关的紧凑的数据;数据仓库一般用作分析而不影响线上流量/业务,数据一般还包含例如点击记录等非用户服务的信息)

数据库操作

表连接

表连接方式可以分为三种:自联结、自然联结和外部联结。

  • 自联结:表与自身连接做查询。自联结通常作为外部语句用来替代从相同表中检索数据时使用的子查询语句(速度更快)

  • 自然联结

  • 外部联结:许多联结将一个表中的行与另一个表中的行相关联。但有时候会需 要包含没有关联行的那些行。

左(外)连接,左表的记录将会全部表示出来,而右表只会显示符合搜索条件的记录。右表记录不足的地方均为NULL

MySQL逻辑架构

  1. 连接管理(Connection Pool):每个客户端连接都会在服务器进程中拥有一个线程,服务器负责缓存线程(因此不需要为每个连接新增/删除线程,MySQL5.5提供API支持线程池插件实现少量线程应对大量连接);服务器对客户端基于用户名、主机信息、密码进行认证
  2. 管理服务和工具组件(Management Service & Utillties):备份,恢复,安全,复制,元数据
  3. SQL接口组件(SQL Interface):DML(Data Definition Language 数据库定义语言,create/alter/drop等),DDL(Data Manipulation Language 数据库操作语言,insert/update/delete等),视图,触发器等
  4. 查询分析器组件(Parser):语句的翻译,MySQL解析查询,并创建内部数据结构(解析树)
  5. 优化器(Optimizer):进行各种优化(重写查询、决定表读取顺序、选择合适的索引等)
  6. 缓冲组件(Caches & Buffers)
  7. 插件式存储引擎(Pluggable Storage Engines):内存,索引存储管理
  8. 物理文件(Files & Logs):Redo,Undo,数据,索引,二进制文件

存储引擎

存储引擎是基于表的(不同表可以选择不同存储引擎)存储引擎以InnoDB为例,他的存储架构如下图,由:后台线程 + InnoDB存储引擎内存池 + 文件三部分组成。

后台线程:

  • Master Thread:核心后台线程,负责将缓冲池数据异步刷新到磁盘(脏页刷新、合并并插入缓冲等)
  • IO Thread:负责存储引擎AIO的IO请求回调处理(write、read、insert buffer、log IO Thread)
  • Purge Thread:负责事务提交后undolog的回收,独立的线程减轻Master Thread的工作
  • Page Cleaner Thread:负责脏页刷新操作

内存池:

缓冲池:记录按页存储,并将其中的记录按照页的方式管理。缓冲池在内存中通过LRU(定制的LRU,最新访问不放首部放中间位置约5/8,一定时间后从new列表到old列表,这是为了防止一次查询的页覆盖了缓冲池的数据页导致热数据被汰换)进行管理

Insert Buffer:5.5后被称为change buffer

merge 的执行流程:

  1. 从磁盘读入老版本数据页
  2. 从 change buffer中找出和该数据页关联的记录,依次应用,得到新版数据页
  3. 写 redo log,记录数据的变更和 change buffer 的变更

InnoDB关键特征

  • 插入缓冲:针对插入不连续的非聚集索引树的插入操作。会先插入到缓冲池的Insert buffer(一个B+数结构),一定时间后会跟磁盘中的数据进行树的合并
  • 两次写:解决页写入磁盘部分成功问题,将记录备份两次,实现数据可靠性
  • 自适应哈希索引:对于一些常用的非范围的等值查询,引擎自优化生成哈希索引,达到查询O(1)的优化
  • 异步IO(AIO):多次的IO合并成一次IO;多个IO互相并行非阻塞
  • 刷新邻接页:当刷新一个脏页时, InnoDB存储引擎会检测该页所在区( extent)的所有页,如果是脏页,那么一起进行刷新

日志

bin log

  • bin log是server层的日志,跟redo、undo log这种存储引擎层的不同(应用所有存储引擎,而redolog只是用于支持事务的innodb)。它是基于行格式的记录方式,其本质也还是逻辑的SQL设置,如该行记录的每列的值是多少(它记录所有修改操作的逻辑日志,先于存储引擎层日志的记录),而redo log是在物理格式上的日志,它记录的是数据库中每个页的修改
  • bin log一般在事务提交后将一系列操作一起写入,如果非事务操作则操作前直接写入
  • 有三种记录方式:statement、row、mixed(前两种格式的混合)。statement记录sql语句内容性能好可能有主备数据一致性问题,row记录行变化内容可能会产生大量日志

redo log

  • 用于记录事务操作的变化,记录的是数据修改之后的值,不管事务是否提交都会记录下来。用于保证数据完整性,如突然断电可以通过日志进行数据恢复
  • 主要分为两部分:在内存中易失的redo log buffer和持久化在磁盘上的redo log file。
  • 它的结构是环形的,方便文件重复利用,如果写的速度追上刷盘清除的速度(即write指针追上checkpoint),会强制执行刷盘

操作步骤:

  1. 事务开始,生成全局唯一事务id
  2. 对某一行进行操作,数据页从磁盘读到buffer pool,新的数据操作内容放入redo buffer pool数组,这里保存记录所在数据页的修改信息(此时与磁盘数据不一致)
  3. 数据操作记录到bin log cache
  4. 事务commit操作,先将redo buffer pool数组内容写redo log(事务的持久化,防止内存数据丢失),返回客户端成功。这一步称为redo log prepare(因为数据还没有跟bin log同步)
  5. bin log cache内容写入磁盘成为bin log;并向redo log结尾处写入end trx=xxx,这步操作叫做redo log commit(即两阶段提交保证redolog和binlog的一致性)
  6. 如果出现redo log写满、刷盘时间点等事件,引擎执行数据刷盘,即内存数据同步到磁盘(此时如果commit会先等刷盘后再写入操作因此会有延迟时间)
  7. 刷盘首先根据日志记录的事务数据去内存找,找到则同步到磁盘(由于在用户空间,会先写到内核空间再写到磁盘);若没找到可能是宕机过数据丢失,则从磁盘读取改了再写回去
  8. 刷盘完后释放日志空间标记处理可后续重复利用;如果日志没有事务结束标志说明事务没有成功则直接忽略并释放

redo log方案针对一致性和ACID的持久化D:

  • 持久化指事务一旦提交,对数据库改变是持久化的不会丢失。当MySQL宕机内存中的事务修改会丢失,但是由于有redo log可以重做;如果在写redo log之前宕机则commit时发现redo log日志只有start没有end就会报错,错误返回客户端
  • 一致性这里指bin log和redo log间的数据一致性。通过类似两阶段提交实现,先binlog在redolog防止部分成功而从库和主库数据不一致。如果MySQL在commit前宕机,此时数据都在内存且没有写磁盘,没有影响;如果在bin log写入成功前宕机,redo log只记录了prepare,带着trx_id没有找到bin log,此时回滚;如果在bin log写入成功回写redo log失败,则会根据trx_id反查bin log,如果在磁盘上则继续做完

undo log

undo log是指事务开始之前,在操作任何数据之前,首先将需操作的数据备份到一个地方 (Undo Log)。在执行事务的时候,我们知道当调用roll back命令的时候,数据就会还原,这里用到的原理就是undo,也是实现事务原子性的原理。用于保证数据原子性;MVCC多版本控制通过undo log做旧数据的快照

索引

主要讨论MySQL的InnoDB引擎所使用的B+树索引

索引数据结构需要满足的条件:

  1. 根据某个值精确查找
  2. 根据某个区间查找
  3. 支持排序的快速顺/逆序查找

优点:

  1. 减少服务器扫描数据量
  2. 帮助服务器避免排序和临时表
  3. 将随机I/O变为顺序I/O

索引类型

散列表

根据关键码值(Key value)而直接进行访问的数据结构,它让码值经过哈希函数的转换映射到散列表对应的位置上。散列表记录索引列计算出的哈希码,散列表每个元素有指向数据行的指针。

例如对name进行索引,name值经过hash函数得到一个散列表对应的key,根据key找到与之对应的数据行。

优点:只存储哈希值,索引结构紧凑;查询速度快

缺点:索引只有精准匹配才生效(AB为索引时,使用A查询则索引不生效);索引存储无序,无法排序和区间查找,只支持等值查询;索引仅包含哈希值&行指针,无法避免读取行

哈希索引只适用特殊场合,例如Memory引擎显式支持哈希索引(默认,同时也支持B-Tree )。InnoDB引擎中,有“自适应哈希索引”,如果 InnoDB 注意到某些索引列值被频繁使用时,它会在内存基于 B+ 树索引之上再创建一个哈希索引,这样就能让 B+树也具有哈希索引的优点,比如快速的哈希查找

链表

空间数据索引(R-Tree)

MyISAM存储引擎支持空间索引,可以用于存储地理数据。无需前缀查询,可以实现任意维度组合查询,空间索引会从所有维度来索引数据。GIS相关函数用于维护数据,开源关系数据库中PostgreSQL的PostGIS对GIS的解决方案做的比较好

全文索引

特殊类型的索引,查找的文本中的关键词,而不是直接比较索引中的值,类似搜索引擎(现在全文索引主流还是elasticsearch这种搜索引擎平台,阿里则用OpenSearch)。同一列创建全文索引和基于值的B-Tree索引不冲突,全文索引适用MATCH AGAINST操作,而不是普通的WHERE操作。

B+树

B+树是InnoDB存储引擎默认的索引数据结构,它在B树的基础上做出了一些改变:根到每个叶子节点路径长度一样、叶子节点间增加了链表(获取所有节点不需要中序遍历)。查询插入删除B-Tree索引的过程可以参考:https://blog.csdn.net/Fmuma/article/details/80287924。它作为索引的优点是:

  • 很适合磁盘存储,能够充分利用局部性原理,磁盘预读;
  • 很低的树高度,能够存储大量数据;
  • 索引本身占用的内存很小;
  • 能够很好的支持单点查询,范围查询,有序性查询;

B-Tree索引又主要分为两大类:聚集索引普通索引

InnoDB聚集索引的叶子节点存储行记录,因此, InnoDB必须要有,且只有一个聚集索引:默认是定义的primary key,若没定义则是第一个not null unique列,若还是没有则创建一个隐藏的row-id。(所以primary key查询很快)优点是:减少磁盘I/O(相关数据在一起)、访问速度快(数据&索引在一个B-Tree中);缺点是:更新索引成本高、页分裂导致更多磁盘占用、全表扫描慢(行稀疏时,页分裂导致数据存储不连续)

InnoDB普通索引的叶子节点存储主键值。(MyISAM的叶子节点则存储着对应记录的指针)

聚簇和非聚簇的区别如下图:

(page):在计算机里,无论是内存还是磁盘,操作系统都是按页的大小进行读取的(页大小通常为 4 KB,磁盘存储最小单元是扇区512Bytes,文件系统最小单位是块4KB,就是说一个文件只有1字节也会占用磁盘空间4KB),磁盘每次读取都会预读,会提前将连续的数据读入内存中,这样就避免了多次 IO,这就是计算机中有名的局部性原理,即我用到一块数据,很大可能这块数据附近的数据也会被用到,干脆一起加载,省得多次 IO 拖慢速度, 这个连续数据有多大呢,必须是操作系统页大小的整数倍,这个连续数据就是 MySQL 的页,默认值为 16 KB,也就是说对于 B+ 树的节点,最好设置成页的大小(16 KB),这样一个 B+ 树上的节点就只会有一次 IO 读。InnoDB 是通过内存中的缓存池(pool buffer)来管理从磁盘中读取的页数据的。页太大的话,很快就把这个缓存池撑满了,可能会造成页在内存与磁盘间频繁换入换出,影响性能

下图为聚簇索引的局部记录,索引的叶子页(leaf page)存放数据行,叶子页包含指向下一个叶子页的链接。也就是说InnoDB聚簇索引就是表,不想MyISAM那样需要独立的行存储。

索引作用域

索引失效的情况有

  • 索引列是表达式/函数的一部分,索引失效导致全表扫描,如:
SELECT book_id FROM BOOK WHERE book_id + 1 = 5;
SELECT book_id FROM BOOK WHERE TO_DAYS(CURRENT_DATE) - TO_DAYS(gmt_create) <= 10
  • 隐式类型转换,如表中索引类型为varchar,等值查询时用了数字类型,会发生隐式类型转换,类似索引为函数一部分,导致索引失效
  • 隐式编码转换,如两个表字符集不同(一个为utf8一个为utf8mb4),则在等值连接时数据库会做隐式的转换
  • order by造成全表扫描,select * order by 索引,导致回表查询(先定位主键值,再定位行记录,它的性能较扫一遍索引树更低),MySQL会认为回表查询代价更大而选择全表扫描,不使用索引。可以通过覆盖索引、加上limit字段避免
  • 不按照最左前缀:不是从最左列开始查找(比如查找第二列+第三列)、跳过索引中列(比如第一列+第三列,只能使用第一列索引)、查询中有某个列范围查询,其右列索引全部失效(比如like或范围查找)

索引有效的查询包括

  • 全值匹配:以index(id,name,date)为例,则匹配这三个列会使用到索引
  • 最左前缀匹配:只匹配id这一列的值,只匹配索引的第一列
  • 列前缀匹配:只匹配id前缀为“w”的,也是使用了索引的第一列(根据最左前缀,匹配第一列以某个字母结尾的id是不行的)
  • 范围值匹配:匹配id以“a”开头到以“b”开头的记录
  • 精确匹配一行并范围匹配另一行:即id全匹配,name可以匹配以“A”开头到以“C”开头的记录
  • 只访问索引的查询:即无需访问数据行,仅访问索引,我们常说的“覆盖索引”

索引选择

前缀索引:当索引值是很长的字符串,索引过大可能造成插入变慢/占用存储大,影响性能。前缀索引即截取该列值前几位作为索引值,比如name(4)为前缀索引,则记录name为abcdef时就会取abcd作为索引值

索引选择性:不重复的索引值(也称为基数,cardinality)和数据表的记录总数的比值,比值越高,代表索引的选择性越好,唯一索引的选择性是最好的,比值是 1。适用前缀索引、联合索引顺序等的选择

前缀索引注意事项

  • 选取前缀要足够多(否则选择性很低,重复率很高失去了索引的意义),同时也不能太高(就是为了缩短索引才引入的前缀索引,否则失去意义)
  • 前缀索引无法group by和order by,也无法使用前缀索引做覆盖扫描,毕竟他只是列值的一部分
  • 不能滥用前缀索引,有时候会增加扫描行数。比如前缀重复率太高,不仅要把重复的都扫描一遍,还要回表查询再比对字段值。比如身份证,可能省内前面几位都是相同的,这种情况用前缀索引,可能通过反转字符串再做索引的方式来实现

多列索引:通常给每个列分别加一个索引并不是好事,最好的情况是满足一星索引,其性能比最优的索引差好几个数量级。多列独立建单列索引大部分情况不能提升查询性能,MySQL5.0后引入“索引合并”策略,使用表上多个单列索引来定位指定的行。对于多列索引来说,一般选择索引选择性高的索引放在前列

三星索引:一种索引的设计原则

  1. 第一颗星:WHERE 后面参与查询的列可以组成了单列索引或联合索引(窄索引片,即把把查询中的等值谓词取出来放在前面)。索引小,一页能存放更多的索引,减少IO

  2. 第二颗星:避免排序,即如果 SQL 语句中出现 order by colulmn,那么取出的结果集就已经是按照 column 排序好的,不需要再生成临时表(即把语句中order by后的取出作为索引)

  3. 第三颗星:SELECT 对应的列应该尽量是索引列,即尽量避免回表查询(避免每一行索引都要单独去聚簇索引进行随机IO查询)。宽索引,即把查询中所有需要查询的列取出。

三星索引栗子

select id, name, sex, age, score from user where sex='b' and score=80 order by age; 

第一颗星,选择sex和score两个等值过滤列;第二颗星,选择age;第三颗星,选择id、name、sex、age、score,已有sex、score、age所以只取出id、name

select id, name, sex, age, score from user where sex='b' and score between 80 and 90 order by age;

在这个sql语句中,由于score是范围查询,如果按(sex, score, age, id, name)设计的话,就不能满足第二颗星了,因为在按第一颗星那样找出满足sex=‘b’,对score进行范围匹配后,就还需对age进行排序;如果按(sex, age, score, id, name)设计的话,则不能满足第一颗星,因为先满足sex与age后,没有先对score进行范围匹配,则不是最小化的索引片。故在设计时需要权衡满足第一颗星牺牲第二颗星较好还是满足第二颗星满足第一颗星较好。第三颗星的话倒是很容易实现的。

存储引擎区别:MyISAM使用前缀压缩技术使得索引更小,InnoDB按原数据格式进行存储;MyISAM索引通过数据的物理位置引用被索引的行,InnoDB根据主键引用被索引的行

索引优化

1. 减少回表查询

如下图,id为聚集索引,name为普通索引。回表查询则是红色表示过程,select * from x where name='ls',通过name查找记录,先普通索引找到主键id为5,再通过聚集索引找到对应的记录。一共扫描了两遍索引树,并且访问聚集索引时采用随机IO读,效率也会低于顺序IO(这就是为什么有时候使用了索引还不如全表扫描快)

解决回表查询的方法是索引覆盖,即将被查询的字段,建立到联合索引里去。例如上面修改为select id,name from x where name='ls',则只用一次索引查询,因为name和id都可以在name的索引树中得到。如果加入一个字段sex,则可以通过建表时设置index(name,sex)联合索引避免回表查询(PK默认是id)

2. 全表count查询。select count(name) from user; 可以通过添加name为索引提升效率

3. 分页查询避免全表。select id,name,sex ... order by name limit 500,100; 设置分页可以避免全表查询

4. 避免索引过多。如果每个索引中包含表的所有列,首先能带来的优势是,匹配到的sql查询更多,查询到的数据不用在进行聚簇索引查询,节省了随机IO。但劣势也很明显,长列索引会造成频繁的page split 和 page merge ,每个page能够存入的索引数据更少,而且会有更多的 page split,这对插入和查询来说,效率都会降低不少。

语句流程

Order By

InnoDB引擎对OrderBy有三种实现方式,根据性能高到低分别是:

  1. 索引排序:如果查询的字段是覆盖索引,那么会先通过索引找到符合条件的记录;再直接输出结果集(搜索的字段都在索引树上不需要回表)
  2. 全字段排序:根据索引在索引树上找到符合条件的记录(id);根据id找到主键索引里对应字段的记录;在sort_buffer中排序;输出结果集
  3. rowid排序:这种情况一般是内存不够会采用的方法,这样可以一次排序多行。先根据索引在索引树上找到符合条件的记录(id);根据id找到主键索引里对应字段的记录(两个字段id和要排序的字段);在sort_buffer中排序;在根据排序的结果从主键索引中取出select对应的字段;输出结果集

JOIN

性能优化

指标

  • 吞吐量:单位时间内事务处理数,常用TPS每秒事务处理数
  • 响应时间/延迟:用于测试任务所需的整体时间,例如百分比响应时间(95%响应时间都是5毫秒)
  • 并发性:同时工作中的线程数/连接数。一般会当作基准测试的属性,即不同并发下其他指标的性能
  • 可扩展性:给系统增加一倍工作,吞吐量是否增加一倍;增加一倍资源,是否获得两倍吞吐量

CPU利用率上升可能只是性能优化后的一种表现,也有可能是索引不当导致的一些bug造成的现象,因此不是一个好的度量指标。吞吐量优化,也只是性能优化的副产品

范式&反范式:范式的优势是更新操作快、少有重复数据(因此修改少)、表小方便放在内存、较少的使用DISTINCT/GROUP BY(因为是单独的一张表);缺点是要关联,代价昂贵可能使一些索引策略无效(一些列被拆分,但可以本属于一个索引)。因此实践中,大多是范式和反范式混用

汇总表:例如需要计算之前24小时系统发送的消息数,可以每小时生成一张汇总表,将24张汇总表计数相加,这种避免了实时维护计数器这种高昂的开销

缓存表:例如有时需要很多不同的索引组合加速各种类型的查询,可以创建一张只包含主表中部分列的缓存表。缓存表可以采用不同的存储引擎,比如主表用InnoDB,缓存表用MyISAM得到更小的索引占用空间&全文搜索的能力;或导出表插入到搜索系统

MySQL的一些优化:Index condition push down (ICP)、Multi-Range Read(MRR)、Batched Key Access(BKA)

并发控制

读写锁:共享锁(读锁)和排他锁(写锁);意向共享锁(表级别读锁)和意向排他锁(表级别写锁)。在为数据行加共享/排他锁前,InnoDB会尝试先获取这个数据行所在表对应的意向锁(意向锁的意义在于如果需要加表锁,不需要全表扫描判断是否有事务锁住了某行)。

锁粒度:表锁(性能优)和行级锁(并发好)

锁算法:记录锁、间隙锁、临键锁(Next-key Lock,InnoDB默认)

死锁:死锁形成一般是:多事务并发+事务都持有锁+都需要继续持有锁+加锁循环等待。InnoDB默认事务超时时间为50s,避免两个事务互相等待,超时则回滚。InnoDB也提供wait-for graph算法自动死锁检测,当加锁请求无法满足进入等待时触发

事务混用存储引擎问题:如果两个表采用不同的存储引擎,如InnoDB和MyISAM前者支持事务,后者不支持,当事务中包含两种不同存储引擎的表进行回滚时,会造成一个表数据回滚而另一个没有,导致数据不一致。

事务隔离

MySQL的读已提交和可重复读的隔离模式都是使用MVVC(Multi-Version Concurrency Control)解决多个事务操作数据库并发问题。其核心思想是undo log与read view

undo log的数据是在rowid + 数据的基础上增加了事务id和回滚指针,其中事务id根据某一行的数据操作递增,回滚指针指向操作前数据地址

read view的核心是维护一个m_ids列表,存放了当前系统活跃的事务的id。

  • 对于RC(READ COMMITTED)隔离级别下的操作,在查询的时候会生成一个read view并判断:如果被访问版本的 trx_id 属性值小于 m_ids 列表中最小的事务id,表明生成该版本的事务在生成 ReadView 前已经提交,所以该版本数据可以被当前事务访问。如果大于说明是最近提交之后的数据,不可以访问。即读到的是trx_id小于当前m_ids列表中最小的trx_id最大数据
  • 对于RR(REPEATABLE READ)隔离级别来说相对简单,它只会在第一次查询的时候生成一个ReadView,以后都会在这基础上查询,即每次查到的都不变,不会产生不可重复读。判断逻辑也是读小于min(m_ids)中最大的trx_id的数据

主从复制

问题

1. 为什么m叉的B+树比二叉搜索树的高度大大大大降低?参考

首先是m阶B树的几个特征:

  • 根结点至少有两个子女
  • 每个中间节点都至少包含ceil(m / 2)个孩子,最多有m个孩子。
  • 每一个叶子节点都包含j-1个元素,其中 m/2 <= j <= m。
  • 所有的叶子结点都位于同一层。
  • 每个节点中的元素从小到大排列,节点当中j-1个元素正好是j个孩子包含的元素的值域分划。

大概计算一下:

  1. 局部性原理,将一个节点的大小设为一页,一页4K,假设一个KEY有8字节,一个节点可以存储500个KEY,即j=500
  2. m叉树,大概m/2<= j <=m,即可以差不多是1000叉树
  3. 那么:
    1. 一层树:1个节点,1*500个KEY,大小4K;
    2. 二层树:1000个节点,1000*500=50W个KEY,大小1000*4K=4M;
    3. 三层树:1000*1000个节点,1000*1000*500=5亿个KEY,大小1000*1000*4K=4G

可以看到,存储大量的数据(5亿),并不需要太高树的深度(高度3),索引也不是太占内存(4G)。

2. MySQL为什么使用B+树而不是B树?

因为B树不管叶子节点还是非叶子节点,都会保存数据,这样导致在非叶子节点中能保存的指针数量变少(有些资料也称为扇出),指针少的情况下要保存大量数据,只能增加树的高度,导致IO操作变多,查询性能变低


参考

  • 《高性能MySQL》
  • https://mp.weixin.qq.com/s/oVpiU16PCHQhHr00G3OK-g
  • 回表查询
  • 三星索引
  • https://my.oschina.net/u/1859679/blog/1589575 三星索引选择
  • 数据索引
  • https://www.jianshu.com/p/71700a464e97B+树总结
  • https://mp.weixin.qq.com/s/CZHuGT4sKs_QHD_bv3BfAQ MVVC
  • https://blog.csdn.net/huangjw_806/article/details/100927097 binlog和redolog数据一致性
  • https://www.cnblogs.com/f-ck-need-u/archive/2018/05/08/9010872.html binlog和undolog详解

  • https://www.cnblogs.com/michael9/p/12572895.html changebuffer

  • https://blog.csdn.net/m0_47157676/article/details/109014986 ,https://blog.csdn.net/huangjw_806/article/details/100927097 binlog和redolog一致性,XA两阶段提交

MySQL数据库知识点相关推荐

  1. MySQL/数据库 知识点总结

    书籍推荐 <SQL基础教程(第2版)> (入门级) <高性能MySQL : 第3版> (进阶) 文字教程推荐 SQL Tutorial (SQL语句学习,英文).SQL Tut ...

  2. mysql数据库知识点梳理_MySQL数据库知识点整理 (持续更新中)

    一.修改用户密码 格式(在命令行下输入):mysqladmin -u 用户名 -p旧密码 password 新密码 1. 给root添加密码ab12:  mysqladmin -uroot -pass ...

  3. Mysql数据库知识点归纳汇总

    文章目录 数据库范式 第一范式(1NF) 第二范式(2NF) 第三范式(3NF) 巴斯-科德范式(BCNF) 第四范式(4NF) 第五范式(5NF) 连接方式 内连接(INNER JOIN) 左连接( ...

  4. MySql 数据库 知识点

    数据库概念 1.什么是数据库?什么是数据库管理系统?什么是 SQL?它们之间的关系是什么? 数据库:英文单词 DataBase ,j简称DB,按照一定格式存储数据的一些文件的集合. 顾名思义:存储数据 ...

  5. 【mysql篇】mysql数据库知识点(四种语言)

    mysql数据库语言分为四种DDL,DQL,DML,DCL下面我们一一介绍: 注:(上图取自黑马程序员的课程APP中,这些笔记也是看了黑马程序员的课程之后做的): 一,       DDL(data ...

  6. MySQL数据库知识点总结(基本篇)

    目录 MySQL数据库和SQL语句(重点) 1.数据库的简介 2.MySQL数据库的安装和卸载 3.MySQL数据库概念 4.SQL语言(操作数据库) 5.SQL语言分类 1.数据库的操作(CURD) ...

  7. mysql数据库知识点总结_mysql数据库知识点总结

    一.数据库的基本操作 --------------------------------------------------------------数据库的安装以后更新----------------- ...

  8. MySQL数据库知识点总结

    数据库: 数据库索引的好处:索引是对数据库表中的一个或多个列的值进行排序的结构,这样检索或者查询某条记录的时候就不在是顺序查找,而是使用特定的查找方式进行查找,如通过二分查找或者是hash值来查找,提 ...

  9. MySQL数据库学习笔记,知识点和案例整理,期末三天复习完【简单且详细】

    MySQL数据库近三万字学习笔记,超级详细! 文章目录 前言 一.day1 二.day2 三.day3 前言 MySQL数据库知识点和案例总结,非常详细,将近三万字!分成了三天去消化吸收! 一.day ...

最新文章

  1. 安卓高手之路之ClassLoader(三)
  2. Javascript的this用法
  3. linux硬件抽象层框图,理解和使用Linux的硬件抽象层HAL.docx
  4. 递归循环一个无限极数组_理解递归、尾调用优化和蹦床函数优化
  5. 255.0.0.0子网掩码相应的cidr前缀表示法是?_【洛谷日报#246】浅谈表达式的求值(Vol.2 进阶)...
  6. java 反射 内存_Java内存到反射入门
  7. MongoDB查询用法大全
  8. 《Photoshop混合模式深度剖析》目录—导读
  9. Android -- 网络请求
  10. 如何打造一个让粉丝一见就能收钱的朋友圈
  11. [NHibernate]一对多关系(级联删除,级联添加)
  12. 自动控制原理第七版胡寿松pdf_自动控制原理简明笔记—(04)
  13. Java酒店管理系统项目
  14. 把Alexa工具条改装成木马
  15. android软件安装到平板,新人看过来 安卓平板装机必备软件推荐
  16. Hibernate报错org.hibernate.MappingException: Unknown entity解决方法
  17. Java如何爬虫奥运奖牌榜数据,恭喜中国获得东京奥运会首金!
  18. JointJS+新的MindMap应用程序
  19. 华清远见Qt作业网络聊天室1014
  20. 服务器操作系统不能显示全屏,服务器窗口显示不全屏

热门文章

  1. Pycharm 的设置背景颜色和字体颜色
  2. InnoDB数据字典操作进行故障排除
  3. 2021计组和微计-背下来就能拿分的知识总结
  4. 计算机维修技术在线阅读,西南大学19秋[0240] 计算机维修技术在线作业
  5. 【Maya】移动、缩放、旋转、万向节旋转、冻结(未完成)
  6. GuidedImageFiltering
  7. 【持续更新-34家】百亿量化私募名单-2022年7月27日
  8. Oracle登录错误12560,登录错误-----ORA-12560: TNS: 协议适配器错误
  9. JSP Web编程的设计过程
  10. MVC有哪几种过滤器?