执行流程
查询缓存
解析器生成解析树
预处理再次生成解析树
查询优化器
查询执行计划
查询执行引擎
查询数据返回结果
执行计划与执行明细
Explain: 可以让我们查看MySQL执行一条SQL所选则的执行计划
Profiling:可以用来准确定位一条 SQL的性能瓶颈
表结构对性能的影响
-
冗余数据的处理(可以提高系统的整体查询性能<三范式>)
没一列只能有一个值
每一行可以被唯一的区分
不包含其他表的已包含的非关键信息
-
大表拆小表
一般不会设计属性过多的表
一遍不会拆超过500到1000万数据的表
有大数据的列单独拆为 小表
根据需求展示更加合理的表结构
常用属性分离为小表
索引
-
类型
Normal:普通的索引;允许一个索引值后面关联多个行值;
Unique:唯一索引;允许一个索引值后面只能有一个行值;之前对列添加 唯一约束其实就是为这列添加一个unique索引;当我们为一个表添加一个主键的时候,其实就是为这个表主键列(设置了非空约束),并为主键列添加了一个唯一索引;
Fulltext:全文检索,MySQL的全文检索只能用myisam引擎,并且性能较低,不建议使用;
-
方法
b+tree:是一颗树(二叉树,平衡二叉树,平衡树(B-TREE))使用平衡树实现索引,是MySQL中使用最多的索引索引类型;在innodb中,存在两种索引类型,第一种是主键索引(primary key),在索引内容 中直接保存数据的地址;第二种是其他索引,在索引内容中保存的是 指向主键索引的引用;所以在 使用innodb的时候,要尽量的使用主键索引,速度非常快;
-
hash:把索引的值做hash运算,并存放到hash表中,使用较少,一般是memory引擎使用;
优点:因为使用hash表存储,按照常理 ,hash的 性能比B-TREE效率高很多。
-
缺点:
hash索引只能适用于精确的值比较,=、in、!=、<>,无法使用范围查询;
无法使用索引排序;
组合hash索引无法使用部分索引;
如果大量索引hash值相同,性能较低;
-
创建:
较频繁的作为查询条件的字段应该创建索引;
-
唯一性太差的字段不适合单独创建索引,即使频繁作为查询条件;
作为索引的列,如果不能有效的区分数据,那么这个列就不适合作为索引列;比如(性别,状态不多的状态列)
举例:select sum(amount) from acountflow where accountType = 0;
假如把accountType作为索引列,因为accountType只有14种,所以,如果根据accountType来创建索引,最多只能按照1/14的比例过滤数据;但是,如果可能出现,只能按照该条件查询,那我们就要考虑到其他的提升性能的方式了;
更新非常频繁的字段不适合创建索引;原因:索引有维护成本;
不会出现在WHERE子句种的字段不该创建索引;
-
索引不是越多越好;(只为必要的列创建索引)
不管你有多少个索引,一次查询至多采用一个索引;(索引和索引之间是独立的)
因为索引和索引之间是独立的,所以说每个索引都应该是单独维护的;数据的增/删/改/查/删,会导致所有的索引都要单独维护;
事务
-
特性:
原子性:<数据库事务不可分割的单位,要么都做,要么不做>
一致性:<事务的操作不会改变数据库的状态,比方说唯一约束>
隔离性:<事务是相互不可见的>
持久性:<事务一旦提交,即使宕机也是能恢复的>
-
分类:
扁平事务:<使用最频繁的事务,要么都成功提交,要么都失败回滚>
带有扁平点的扁平事务:<允许事务回滚到同一个事务中比较早的一个状态>
链事务:<回滚到最近的一个保存点,在所有的事务都提交之后才会释放锁,并且下一个事务的开始需要上一个事务来进行通知>
嵌套事务:<树结构,只有当父级事务提交之后子级事务才会提交,任意一个父级事务的回滚都会导致下面的子级事务回滚>
分布式事务:<操作两个不同的数据库,使其实现数据的同步,例如将中国银行的钱转到工商银行,这个不同银行的不同数据库,为分布式事务>
-
隔离级别:
read uncommittted<脏读:事务A读取了事务B更新的数据,然后B回滚操作,那么A读取到的数据是脏数据>
read committed<不可重复读:事务 A 多次读取同一数据,事务 B 在事务A多次读取的过程中,对数据作了更新并提交,导致事务A多次读取同一数据时,结果 不一致。>
repeatable read<幻读:系统管理员A将数据库中所有学生的成绩从具体分数改为ABCDE等级,但是系统管理员B就在这个时候插入了一条具体分数的记录,当系统管理员A改结束后发现还有一条记录没有改过来,就好像发生了幻觉一样,这就叫幻读。>
serializable<锁表,不会出现意外情况>
锁
-
lock
-
共享锁<s lock>允许事务读取一行数据
共享锁允许多个事务来读取相同的数据,因为读取不会改变数据,但是不能与排他锁共存,当有事务想要update数据的时候就要等共享锁释放之后才能使用排他锁进行update
-
排他锁<x lock>允许事务更新或者是删除一条数据
当排他锁进行了行数据的锁定的时候就必须等这个锁释放之后下一个锁才能进来,也就是说必须当数据更新完成之后才能接收下一个事务的锁
意向共享锁<is lock>事务想要获得一张表某几行的共享锁
意向排他锁<ix lock>事务想要获得一张表的某几行的排他锁
-
latch <轻量级锁,锁的时间非常短,用来操作临界资源>
一致性的非锁定读
一致性的锁定读
死锁
优化原则
-
SQL语句的优化:
-
如何选择需要优化的SQL
云服务器的慢查询日志
Nginx响应日志找到相应接口数据模块语句
-
Explain和Profile入手
任何SQL的优化,都从Explain语句开始;Explain语句能够得到数据库的执行该SQL选择的执行计划;
首先明确需要的执行计划,在使用Explain检查;
使用profile明确SQL的问题和优化的结果;
永远用小结果集驱动大的结果集
在索引中完成排序
使用最小的Columns
使用最有效的过滤条件
避免复杂的join和子查询
-
-
索引优化
-
如何选择是否索引
数据大于2000条,酌情考虑建索引,索引建的越多,插入越慢
选择性的取值范围[0, 1], select count(Distinct(title))/count(*), 越接近1,越适合
-
前缀索引
频繁用作查询条件,可以用多个条件的字段前缀用作索引
索引的长度要短,索引文件要小,选择性要高
-
-
插入数据优化
InnoDB默认的装载因为为15/16,则开辟一个新页
页子节点采用自增主键,B-Tree的页子节点有顺序链表连续性关联性较高。如果不是自增,会频繁移动索引数据分页操作造成大量的碎片,得不到紧凑的索引结构,甚至目标页面从缓存中清掉,再从磁盘上读回来
-
MySQL配置优化:
MySQL数据库是常见的两个瓶颈是CPU和I/O的瓶颈,CPU在饱和的时候一般发生在数据装入内存或从磁盘上读取数据时候。 磁盘I/O瓶颈发生在装入数据远大于内存容量的时候,如果应用分布在网络上,那么查询量相当大的时候那么平瓶颈就会出现在网络上, 我们可以用mpstat(获取 CPU 相关统计信息), iostat(监控系统设备的IO负载情况), Linux sar命令和vmstat来查看系统的性能状态。
show status——显示当前状态信息,show processlist——查看当前SQL执行状态,是否表锁;
-
常用配置:
max_connections——允许的同时会话数的上限
max_connect_errors——客户端连接最大的错误允许数量
back_log——操作系统在监听队列中所能保持的连接数,你有非常高的连接率并且出现 “connection refused” 报错,应该增加此处的值
interactive_timeout——服务器关闭交互式连接前等待活动的秒数(默认8小时)
wait_timeout——服务器关闭非交互连接之前等待活动的秒数(默认8小时)
ft_min_word_len——被全文检索索引的最小的字长, 注意在你修改此值之后,你需要重建你的 FULLTEXT 索引
JOIN原理
-
join的原理:
在MySQL中使用Nested Loop Join来实现join;
A JOIN B:通过A表达结果集作为循环基础,一条一条的通过结果集中的数据作为过滤条件到下 一个表中查询数据,然后合并结果集;
-
JOIN的优化原则:
尽可能减少join语句中的Nested Loop的循环总次数,用小结果集驱动大结果集;
优先优化Nested Loop的内层循环;
保证Join语句中被驱动表Join条件字段已经被索引;
扩大join buffer的大小;
树知识与主存、磁盘存取解析
-
平衡二叉树、AVL树、23树、红黑树、B+Tree
-
二叉查找树:
也成二叉搜索树,或者二叉排序树,其定义也比较简单,要么是空树,要么就是如下性质的二叉树
若任意节点的左子树不空,则左子树上所有节点的值均小于他的根节点的值
若任意节点的右子树不空,则右子树所有节点的值均大于他的根节点的值
任意节点的左右子树也分别为二叉查找树
没有键值相等的节点
-
平衡二叉树:
也称AVL树,且具有如下性质:
它是一颗空树或者它的左右两个子树的高度差的绝对值不超过1
并且左右的两端子树都是一颗平衡二叉树
旋转操作:
左旋就是将节点的右子节点变成父节点,并把晋升之后的多余的左子节点让给降级的右子节点
右旋就是将节点的左子节点变成父节点,并把晋升之后的原多余的右子节点让给降级的节点的左子节点
-
2-3树
是一颗自平衡的多路查找树,并不是一颗二叉树
每个节点有1个到2个key,对应的子节点为2个子节点或者3个子节点
所有叶子节点到根节点的长度一致
每个节点的key从左到右保持了从小到大的顺序,两个key之间的子树中所有的key一定大于它的父节点的左key,小于父节点的右key
2-3-4树,就是同样性质的3阶4阶的B树
-
B树
是一颗m阶的B树(B-Tree)定义如下
每个节点最多有m-1个key
根节点至少有一个key
非根节点至少有Math.ceil(m/2)- 1个key
每个及诶点中的key都按照从小到大的顺序排列,每个key的左子树中的所有的key都小于它,而右子树中的所有key都大于它
所有叶子节点都位于同一层,即跟节点到每个叶子节点的长度都相同
-
B+树在B树的基础上做了优化差异于
有k个子节点的节点必然有k个key
非叶子节点仅具有索引作用,跟记录有关的信息均存放于叶子节点
树的所有叶子节点构成一个有序链表,可以按照key排序全部记录
B+树的优点在于:
由于B+树在内部节点上不包含数据信息,因此在内存页中能够存放更多的key。数据存放的更加紧密,具有更好的空间局部性,因此访问叶子及诶点上关联的数据也具有更好的缓存命中率
B+树的叶子节点都是相连的,因此对整颗的遍历只需要一次性遍历叶子节点即可,而且由于数据顺序排列并且相连,所以便于区间查找和搜索而B树则需要进行每一层的递归遍历,相邻的元素可能在内存中不相邻,所以缓存命中率没有B+树
但是,由于B树的每一个节点都包含了key和value,因此经常访问的元素可能离根节点更近,因此访问也更迅速
-
红黑树的5个特征:
节点是黑色和红色
跟节点是黑色
叶子节点和NIL空节点是黑色
红色节点的子节点是黑色,不存在两个连续的红色节点
从任一节点到每个叶子节点的黑色节点个数相同,黑色节点个数是h,树的高度是H,H<=h<=2H
-
-
MySQL存储引擎支持的索引
B+Tree索引
哈希索引
全文索引
-
索引是什么?
- 是帮助MySQL高效获取数据结构,本质:索引是数据结构
查询算法:
顺序查找(linear search)
二分查找(binary search)要求被检查数据有序
二叉树查找(binary tree search)复杂度O(log2n)
没有办法直接作用在查询数据上,索引就是满足特定条件查找算法的数据 结构,在数据库上维护这种结构并实现高级查找算法
-
B-Tree B+Tree广泛应用于索引
-
B-Tree:
d为大于1的正整数,称为B-Tree的度
h为一个正整数,称为B-Tree的高度
每个非叶子 节点有n-1个key和几个指针组成,其中d<=n<=2d
每个叶子节点 最少包含一个key和两个指针,最多包含2d-1个key,而2d个指针,叶节点的指针均为null
所有叶子节点具有相同的深度,等于个高度h
key和指针相互间隔,节点两端是指针
一个节点中的key从左到右递增排列
-
B+Tree是MySQL普遍使用的索引结构与B-Tree相比有一下不同点:
每个节点的指针上限为2d而不是2d+1
内接点不存储data只存储key,叶子节点不存储指针
B-Tree每个节点的域和上限是一致的,对每个节点申请相同大小的空间。B+Tree更适合实现外存储索引结构
数据库系统使用B+Tree结构,增加了顺序访问指针
-
为什么使用B+Tree:
所以你本身也很大,以索引文件的形式存储在磁盘中,I/O操作次数的渐进复杂度。索引的结构组织要尽量减少查找过程中的I/O的存取次数
-
-
主存存取原理
目前计算机使用的主存基本都是可以随机读写存储器(RAM),从抽象角度看,主存是一系列的存储单元组成的矩阵。每个存储单元有唯一的地址。
主存的存取过程如下:
当系统需要读取主存时,则讲地址信号放到地址总线传给主存,主存读到地址信号后,解析信号并定位到指定的存储单元。将储存单元数据放到数据总线上,供其他部件读取
-
磁盘存取原理
-
磁盘原理
磁盘I/O存在机械运动耗费,因此磁盘I/O的时间消耗是巨大的,一个磁盘由大小相同的且同轴的原型盘片组成,磁盘可以转动,在磁盘的一侧有磁头支架。上面固定了一组磁头,每个磁头负责存取一个磁盘的内容。磁头不能转动,但是可以沿着磁盘半径方向运动,盘片被削分成一系列同心环,圆心是盘片中心,每个同心环叫做一个磁道。所有半径相同的磁道组成一个柱面。磁道被沿半径划分成一个小段,每个段叫做一个扇区,每个扇区是磁盘的最小存储单元。
-
磁盘的存取过程
磁盘读取数据时,系统会将数据逻辑地址传给磁盘,磁盘的控制电路按照寻址逻辑将逻辑地址翻译成物理地址,即确定要读的数据在哪个磁道哪个扇区,将磁头放到移动到对应扇区的磁道,这个过程叫做寻道。所耗费的时间叫做寻道时间。磁盘转动的时间叫做旋转时间。
-
-
局部性原理与磁盘预读
预读的长度一般为页(page)的整倍数。主存和磁盘存储区分割为连续的大小相等块,每个存储块称为页,大小为4K
B-Tree、B+Tree性能分析
数据库系统的设计者巧妙的利用了磁盘预读原理。将一个节点的大小设为等于一个页的大小4k
每次新建节点,直接申请了一个页的空间,保证该一个节点物理上也有存储在一个页里。加之计算机存储分配都是按页对齐实现一个Node只需一次I/O
B-Tree一次检索只需要h-1次I/O(根节点常驻内存),渐进复杂度O(h)=O(logdN),出度d是非常大的数字超过100,因此h非常小(通常不超过3)
红黑树,h明显深很多,由于逻辑上很近的节点(父子)物理上可能很远,无法利用局部性的预读,红黑树的I/O渐进复杂度为O(h)
B+Tree适合外存,d越大索引的性能越好,出度的上限取决于节点内key和data的大小。内节点去掉了data域。因此可以拥有更大的出度,拥有了更好的性能
MyISAM、InnoDB的索引实现
MyISAM索引文件保存记录的地址,主索引是唯一辅助索引(Secondary key)可以重复,可以和主索引没有区别,索引文件和数据文件区分开
InnoDB数据文件本身就是索引文件,索引的key就是主键,叶子节点包含完整的数据叫做聚集索引,所有辅助索引都引用了主键作为data域
MySQL事务的4种隔离级别详解
低级别的隔离,一般支持更高的并发处理,并拥有更低的开销;
脏读(Dirty Read):脏读是读到了别的事务du回滚前的脏数据。比如事务B执行过程中修改了数zhi据X,在未提交前,事务A读取了X,而事务B却回滚了,这样事务A就形成了脏读。
不可重复读(Nonerepeatable Read):事务A第一次查询得到一行记录row1,事务B提交修改后,事务A第二次查询得到row1,但列内容发生了变化;
幻读(Phantom Read):事务A第一次查询得到一行记录row1,事务B提交修改后,事务A第二次查询得到两行记录row1和row2;
Ps:事务B未提交就是脏读,已提交,数据变化了就是不可重复读,条数变化了就是幻读。可以这么记防止混淆;
-
读取未提交(Read Uncommitted)
所有事务都可以看到其他未提交事务的执行结果
隔离级别很少用于实际应用,因为它的性能也不比其他级别好多少
-
该级别引发的问题——脏读(Dirty Read)读取未提交数据
脏读例子:
start transaction; -- 事务A select num from tx where id = 1; --1 start transaction; -- 事务B update tx set num=2 where id = 1; -- 此时未commit -- 事务A在查询 select num from tx where id = 1; --2</pre>
-
读取已提交(Read Committed)
这是大多数数据库系统的默认隔离级别(但不是MySQL默认的)
它满足了隔离的简单定义:一个事务只能看见已经提交事务所的改变
-
这种隔离级别出现的问题是——不可重复读(Nonerepeatable Read):不可重复读意味着我们在同一个事务中,执行完全相同的select语句可能看到不一样的结果,
不可重复读例子:
start transaction; -- 事务A select num from tx where id = 1; --1 start transaction; -- 事务B update tx set num=2 where id = 1; commit; -- 事务A在查询 select num from tx where id = 1; --2</pre>
-
可重复读(Repeatable Read)
这是MySQL默认的事务隔离级别
它确保同一事务的多个实例在并发读取数据时,会看到同样的数据
此级别可能出现出现的问题——幻读(Phantom Read):当用户读取某一范围的数据时,另一个事务又在该范围内插入新行,当用户再读取该范围的数据行时,会发现新的幻影行
InnoDB和Falcon储存引擎通过MVCC机制、间隙锁(gap锁机制)
-
MVCC机制
什么是MVC:英文全称为Multi-Version Concurrency Control,中文为多版本并发控制,乐观锁的一种实现方式
-
特点:
MVCC其实广泛应用于数据库技术,像Oracle,PostgreSQL等也引入了该技术,即适用范围广
MVCC并没有简单的使用数据库的行锁,而是使用了行级锁,row_level_lock,而非InnoDB中的innodb_row_lock
基本原理:MVCC的实现,通过保存数据在某个时间点的快照来实现的。这意味着一个事务无论运行多长时间,在同一个事务里能够看到数据一致的视图。根据事务开始的时间不同,同时也意味着在同一个时刻不同事务看到的相同表里的数据可能是不同的。
-
基本特征:
每行数据都存在一个版本,每次数据更新时都更新该版本。
修改时Copy出当前版本随意修改,各个事务之间无干扰。
保存时比较版本号,如果成功(commit),则覆盖原记录;失败则放弃copy(rollback)
-
InnoDB存储引擎MVCC的实现策略:
在每一行数据中额外保存三个隐藏的列:当前行创建时的版本号和删除时的版本号(可能为空,其实还有一列称为回滚指针,用于事务回滚,不在本文范畴)。这里的版本号并不是实际的时间值,而是系统版本号。每开始新的事务,系统版本号都会自动递增。事务开始时刻的系统版本号会作为事务的版本号,用来和查询每行记录的版本号进行比较。
start transaction; -- 事务A select count(1) from tx where id = 1; --1 start transaction; -- 事务B insert into tx(id, num) value(1, 2); commit; -- 事务A在查询 select count(1) from tx where id = 1; --2</pre>
-
可串行化(Serializable)
这是最高隔离级别
它通过强制事务排序,使之不可能相互冲突,从而解决幻读问题。简言之,它是每个读的数据行上加上共享锁
在这个级别,可能导致大量的超时现象和锁竞争
脏读 不可重复读 幻读 未提交读 ✔️ ✔️ ✔️ 已提交读 ❌ ✔️ ✔️ 可重复读 ❌ ❌ ✔️ 可串行化 ❌ ❌ ❌
MySQL的七种锁
-
共享锁(S锁)排它锁(X锁)
事务拿到某一行记录的共享S锁,才可以读这一行;
事务拿到某一行记录的排他X锁,才可以修改删除这一行;
共享锁的目的提高读读并发;
排它锁的目的为保证数据的一致性;
-
意向锁
意向共享锁:预示事务有意向时表中的某些行加共享S锁
意向排他锁:预示事务有意向对表中的某些行为排他X锁
兼容性 IS IX S X IS √ √ √ X IX √ √ X X S √ X √ X X X X X X 意向锁的意义在哪里?
IX、IS是表级锁,X、S是行级锁,意向锁是添加行锁之前
先判断是否兼容,再考虑行级锁的遍历
-
插入意向锁
插入意向锁是间隙锁的一种,针对insert操作产生,目的是提高并发
多个事务在同一个索引,同一个范围区间进行插入记录的时候,如果插入的位置不冲突,不会阻塞彼此,如果不用commit。只能查自己的插入记录,这里用了默认的第三种事务隔离“可重复读Repeatable Read”。如果修改的是同一行会被X阻塞。
-
记录锁
自动创建的隐式row_id作为聚集索引来进行加锁,是对单条索引记录加锁,而非记录本身
-
间隙锁(gap锁)
封锁记录中的 间隔,防止间隔中被 其他事务插入,间隙 锁主要出现在RR隔离级别,避免出现幻读
在MVCC下,读操作可以分为两种:
<pre spellcheck="false" class="md-fences md-end-block md-fences-with-lineno ty-contain-cm modeLoaded" cid="n685" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: "Fira Mono", Cousine, Consolas, monospace; font-size: 1rem; display: block; break-inside: avoid; text-align: left; white-space: normal; background-image: inherit; background-size: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: inherit; position: relative !important; padding-left: 0.25rem; width: auto; color: rgb(51, 51, 51); font-weight: normal; background-position: inherit inherit; background-repeat: inherit inherit;" lang=""> 1. 快照读:select * from table where..</pre>
-
id非唯一索引 + RR
id索引加X锁,区间加gap锁
主键聚簇索引上加X锁
读下条重复进行
直到不满足条件,不需要加记录X锁,仍就加gap锁
-
id无索引 + RR
id无索引,全表扫描当前读
聚簇索引上全加X锁和gap锁
几种触发间隙锁的情况?
当前读:select * from table where..for update
update delete insert也是当前读,会把过滤出来的记录进行加锁(current read)
insert会触发unique key的冲突检查,也会进行当前读
-
-
临键锁(next-key-lock)
临建锁是记录锁和间隙锁的组合,即锁住记录也锁住范围
临键锁主要目的,也是避免幻读
如果把事务的隔离级别降级为RC,临键锁也会失效
-
自增长锁
是一种表级锁,专门针对auto-increment类型
simple inserts: 持有锁,读取,释放,执行SQL最快,不需要执行完就释放,不需要等待insert执行完对于回滚,就 变成不连续的,默认此类型
bulk inserts:持有锁读取,执行SQL,释放,唯一持有时间过长,不利于并发
mixed-mode inserts:指插入中有一部分的值是自增长的,有一部分是确定的。入INSERT INTO t1(c1,c2) VALUES(1,’a’),(2,’a’),(3,’a’);也可以是指INSERT…ON DUPLICATE KEY UPDATE这类SQL语句。
(外键锁:在InnoDB存储引擎中,对于一个外键列,如果没有显示地对这个列加索引,InnoDB存储引擎会自动对其加一个索引,因为这样可以避免表锁)
MySQL事务日志(redo log、undo log)和二进制日志(binlog)
innodb事务日志包括redo log和undo log。
redo log是重做日志,提供前滚操作,物理日志记录数据页物理修改
undo log是回滚日志,提供回滚操作,逻辑日志记录数据行操作修改
undo log不是redo log的逆向过程,其实它们都算是用来恢复的日志: 1.redo log通常是物理日志,记录的是数据页的物理修改,而不是某一行或某几行修改成怎样怎样,它用来恢复提交后的物理数据页(恢复数据页,且只能恢复到最后一次提交的位置)。 2.undo用来回滚行记录到某个版本。undo log一般是逻辑日志,根据每行记录进行记录。
面试题热点问题总结
mysql 中 myisam 与 innodb 的区别
MySQL存储引擎选型及注意事项
解读MySQL的共享锁及排它锁
MySQL事务及隔离界别
正确掌握使用执行计划
解读BTree与B+Tree索引
sql慢查询配置及分析
sql优化策略及实战
项目中sql语句的诊断
MySQL主从复制、读写分离高可用方案
MySQL+keepalived实现双主高可用方案
千万级MySQL分库分表高性能解决方案
SQL语句执行从10s如何提升到毫秒级
高并发场景下的数据库事务调优
MySQL索引的失效与 优化
项目中常见的死锁故障如何快速排查
索引的底层实现
为什么索引结构使用B+Tree,而不是hash,二叉树,红黑树
B+Tree与skiplist跳表的区别
为什么使用自增主键作为索引
数据库三范式是什么
有哪些优化数据库方面的经验
请简述常用的索引种类
mysql 数据库中索引的工作机制是什么?
mysql 的复制原理以及流程
mysql 支持的复制类型
mysql 中 varchar 与 char 的区别以及 varchar(50)中的 50 代表的涵 义?
MySQL 中 InnoDB 支持的四种事务隔离级别名称,以及逐级之间的区别?
表中有大字段 X(例如:text 类型),且字段 X 不会经常更新,以读为 为主,将该字段拆成子表好处是什么
MySQL 中 InnoDB 引擎的行锁是通过加在什么上完成的(或称实现)
MySQL 中控制内存分配的全局参数,有哪些?
若一张表中只有一个字段 VARCHAR(N)类型,utf8 编码,则 N 最大值为多少(精确到数量级即可)?
[SELECT *] 和[SELECT 全部字段]的 2 种写法有何优缺点?
HAVNG 子句 和 WHERE 的异同点?
MySQL 当记录不存在时 insert,当记录存在时 update,语句怎么写?
MySQL 的 insert 和 update 的 select 语句语法
Insert into student(stuid, stuname, deptid) select 10, 'xzm', 3 from student where stuid >8;
Update student a inner join student b on b.stuID = 10 set a.stuname=concat(b.stuname, b.stuID) where a.stuID=10;
该文分上中下,请移步观看