mirror of
https://github.com/Estom/notes.git
synced 2026-11-06 10:17:23 +08:00
123
This commit is contained in:
@@ -43,7 +43,7 @@ mysql拿到一个查询请求后,会先到查询缓存查看之前是否执行
|
||||
开始执行的时候,要先判断一下用户对这个表 T 有没有执行查询的权限。如果没有,就会返回没有权限的错误。如果命中查询缓存,会在查询缓存返回结果的时候,做权限验证。查询也会在优化器之前调用 precheck 验证权限。如果有权限,就打开表继续执行。打开表的时候,执行器就会根据表的引擎定义,去调用这个引擎提供的接口。在数据库的慢查询日志中看到一个rows_examined 的字段,表示这个语句执行过程中扫描了多少行,这个值就是在执行器每次调用引擎获取数据航的时候累加的。在有些场景下,执行器调用一次,在引擎内部则扫描了多行,因此引擎扫描行数跟rows_examined并不是完全相同的。
|
||||
|
||||
|
||||
## 2 SQL查询机制
|
||||
## 2 SQL查询语句
|
||||
|
||||

|
||||
|
||||
@@ -59,17 +59,17 @@ SQL执行步骤:请求、缓存、SQL解析、优化SQL查询、调用引擎
|
||||
|
||||
|
||||
|
||||
## 3 SQL更新机制和日志记录
|
||||
## 3 SQL更新语句
|
||||
|
||||

|
||||
|
||||
|
||||
### 执行过程
|
||||
1. 客户端向 MySQL 服务器发送一条更新请求
|
||||
2. 清除表查询缓存,跟这个有关的查询缓存会失效。这就是一般不建议使用查询缓存的原因。
|
||||
3. 分析器进行 SQL解析(词法和语法分析),分析这是一条更新语句和。
|
||||
4. 优化器生成对应的执行计划,优化器决定使用ID这个索引;
|
||||
5. 执行器负责更新,找到这一行,然后进行更新:
|
||||
1. 连接:客户端向 MySQL 服务器发送一条更新请求
|
||||
2. 缓存:清除表查询缓存,跟这个有关的查询缓存会失效。这就是一般不建议使用查询缓存的原因。
|
||||
3. 解析:分析器进行 SQL解析(词法和语法分析),分析这是一条更新语句和。
|
||||
4. 优化:优化器生成对应的执行计划,优化器决定使用ID这个索引;
|
||||
5. 执行:执行器负责更新,找到这一行,然后进行更新:
|
||||
1. 取数据行: 执行器先找引擎取 ID=2 这一行: ID 是主键,引擎直接用树搜索找到这一行。如果 ID=2 这一行所在的数据页本来就在内存中,就直接返回给执行器;否则,需要先从磁盘读入内存,然后再返回。)
|
||||
2. 更新数据: 执行器拿到引擎给的行数据,把这个值加上 1,比如原来是 N,现在就是 N+1,得到新的一行数据,再调用引擎接口写入这行新数据。
|
||||
3. 更新内存: 引擎将这行新数据更新到内存中,
|
||||
@@ -80,9 +80,39 @@ SQL执行步骤:请求、缓存、SQL解析、优化SQL查询、调用引擎
|
||||

|
||||
|
||||
|
||||
### 日志类型
|
||||
## 4 日志类型
|
||||
|
||||
|
||||
与查询流程不同的是,更新流程涉及两个重要日志模块:redo log(重做日志)和 binlog(归档日志)。redo log是InnoDB存储引擎层的日志,binlog是MySQL Server层记录的日志, 两者都是记录了某些操作的日志(不是所有)自然有些重复(但两者记录的格式不同)。
|
||||

|
||||
|
||||
redo log在数据库重启恢复的时候被使用,因为其属于物理日志的特性,恢复速度远快于逻辑日志。而binlog和undo log属于的逻辑日志。
|
||||
|
||||
### redo log
|
||||
* redo log记录的是page的变化。数据内容的变化,是物理层的。。对于面向disk的数据库,需要把数据先写入到page中,然后成批的flush到磁盘,所以在Page没有flush前需要有log能记录下page的state。这就是Redo,所以Redo是物理的,因为记录的是Page的具体变更,用Redo的目的是恢复出之前的page。
|
||||
* Redo本身也是要写disk,将多次写操作存入到buffer中,在事务commit的时候才把Redo顺序写入disk。redo log prepare状态切换到commit状态,完成提交。
|
||||
|
||||
|
||||
|
||||
使用场景:
|
||||
* redo log在数据库重启恢复的时候被使用,因为其属于物理日志的特性,恢复速度远快于逻辑日志。
|
||||
* redo log作为异常宕机或者介质故障后的数据恢复使用
|
||||
|
||||
### bin log
|
||||
|
||||
* MySQL Server层面的,又称为归档日志,属于逻辑日志,是以二进制的形式记录的是这个语句的原始逻辑。
|
||||
|
||||
使用场景:
|
||||
* 在主从复制的时候使用。主库向从库写入变化。
|
||||
* binlog可以作为恢复数据使用
|
||||
|
||||
### undo log
|
||||
|
||||
* Undolog主要分为两种
|
||||
* insert undo log。代表事务在insert新记录时产生的undo log, 只在事务回滚时需要,并且在事务提交后可以被立即丢弃
|
||||
* update undo log。事务在进行update或delete时产生的undo log; 不仅在事务回滚时需要,在快照读时也需要;所以不能随便删除,只有在快速读或事务回滚不涉及该日志时,对应的日志才会被purge线程统一清除
|
||||
|
||||
|
||||
### 日志对比
|
||||
|
||||
- 层次不同。redo/undo 是 innodb 引擎层维护的,而 binlog 是 mysql server 层维护的,跟采用何种引擎没有关系,记录的是所有引擎的更新操作的日志记录。
|
||||
- 记录内容不同。redo/undo 记录的是 每个页/每个数据 的修改情况,属于物理日志+逻辑日志结合的方式(redo log 是物理日志,undo log 是逻辑日志)。binlog 记录的都是事务操作内容,binlog 有三种模式:Statement(基于 SQL 语句的复制)、Row(基于行的复制) 以及 Mixed(混合模式)。不管采用的是什么模式,当然格式是二进制的,
|
||||
- 记录时机不同。redo/undo 在 事务执行过程中 会不断的写入,而 binlog 是在 事务最终提交前 写入的。binlog 什么时候刷新到磁盘跟参数 sync_binlog 相关
|
||||
@@ -183,131 +183,4 @@ select username, score from t1 where username = '小明'
|
||||
### 前缀索引
|
||||
* tire索引/前缀索引:用来索引字符串。
|
||||
|
||||
> 特点:索引能够加快数据库查询,需要占用一定的存储空间。基本表更新后,索引也需要更新。用户不必显示地选择索引,关系数据库管理系统在执行查询时,会自动选择合适的索引作为存储路径。
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
MySQL中常用的索引结构有:B+树索引和哈希索引两种。目前建表用的B+树索引就是BTREE索引。
|
||||
|
||||
在MySQL中,MyISAM和InnoDB两种存储引擎都不支持哈希索引。只有HEAP/MEMORY引擎才能显示支持哈希索引。
|
||||
|
||||
创建索引:
|
||||
|
||||
CREATE TABLE userInfo(
|
||||
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键',
|
||||
`username` varchar(3) NOT NULL COMMENT '用户名',
|
||||
`age` int(10) NOT NULL COMMENT '年龄',
|
||||
`addr` varchar(40) NOT NULL COMMENT '地址',
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `ind_user_info_username` (`username`) USING BTREE, --此处普通索引
|
||||
key 'ind_user_info_username_addr' ('username_addr') USING BTREE, --此处联合索引
|
||||
unique key(uid) USINGBTREE, --此处唯一索引
|
||||
key 'ind_user_info_addr' (addr(12)) USINGBTREE —-此处 addr列只创建了最左12个字符长度的部分索引
|
||||
)ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='用户表';
|
||||
————————————————
|
||||
版权声明:本文为CSDN博主「yanweihpu」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
|
||||
原文链接:https://blog.csdn.net/yanweihpu/article/details/80254066
|
||||
|
||||
|
||||
## 索引类型:
|
||||
|
||||
唯一索引、主键索引、外键索引、普通索引,复合索引
|
||||
|
||||
## 索引优化查询:
|
||||
|
||||
A、关联查询时,保证关联的字段都建立索引,并且字段类型一致,这样才能两个表都使用索引。如果字段类型不一样,至少一个表不能使用索引。
|
||||
|
||||
B、索引列如果使用like条件进行查询,那么 like 'xxx%' 可以使用索引,like '%xxx' 不能使用索引。
|
||||
|
||||
C、复合索引,如果创建了一个(username,age,addr)的复合索引,那么相当于创建了(username,age,addr),(username,age),(username)三个索引,所以在创建复合索引的时候应该将最常用的限制条件的列放在最左边,依次递减。
|
||||
|
||||
D、索引列的值最好不要有null值。列中只要包含null,则不会被包含到索引中,复合索引中只要有一列为null值,则这个复合索引失效的。所以创建索引列不要设置默认值null
|
||||
|
||||
E、字符串列加索引最好加短索引,即对前该列的前xx个字符,例如:key 'ind_user_info_addr' (addr(10)) USINGBTREE代表对addr列的前10个字符家索引。
|
||||
|
||||
F、如果where条件中使用了一个列的索引,那么后面order by 在用这个列进行排序时,便不会再使用索引。
|
||||
|
||||
|
||||
|
||||
## 数据库优化
|
||||
|
||||
6、数据库优化
|
||||
|
||||
关联查询中的inner join 和左连接、右连接、子查询
|
||||
A、inner join 内连接也叫做等值连接,left/right join 是外连接。能用inner join连接的尽量用inner join连接
|
||||
|
||||
B、尽量使用外连接来替换子查询。
|
||||
|
||||
C、在使用on和where的时候,先用on,在用where。
|
||||
|
||||
D、使用join时,用小的结果驱动大的结果(left join左表结果尽量小,如果有条件,先放左边处理,right join同理反向)。
|
||||
|
||||
E、多表联合查询尽量拆分多个简单的sql语句进行查询。
|
||||
|
||||
建立索引,加快查询性能
|
||||
A、where条件用到复合索引中的字段时,最好把该字段放在复合索引的左端,这样才能使用索引提高查询。
|
||||
|
||||
B、保证连接的索引是相同类型。即a.age = b.age,a表的和b表的age字段类型保证一样,并且都建立了索引。
|
||||
|
||||
C、在使用like一个字段的索引时,like 'xxx%'能用到索引,like '%xxx'不能用到索引。
|
||||
|
||||
D、复合索引的使用:如果我们建立了一个(name,age,addr)的复合索引,那么相当于创建了(name,age,addr)、(name,age)、(name)三个索引。这样就把常用的限制条件放到最左边,依次递减。
|
||||
|
||||
E、索引列不要包含NULL值的列。所以数据库设计时,尽量不让字段默认为NULL。
|
||||
|
||||
F、使用短索引,对于字符串的索引,应指定一个前缀长度,体积高查询速度并且可以节省磁盘空间和I/O操作。
|
||||
|
||||
G、排序索引。尽量不要使用包含多个列的排序,如果需要则给这些列加上复合索引。
|
||||
|
||||
limit千万级分页优化
|
||||
A、select * from A order by id limit 1000000,10; 查询更换成select * from A where id between 1000000 and 1000010;
|
||||
|
||||
尽量避免select * 的查询
|
||||
尽量不要使用BY RAND()命令
|
||||
利用limit 1取得唯一行。使用limit 1可以终止数据库引擎继续扫描整个表或者索引
|
||||
减少排序order by
|
||||
少用OR
|
||||
避免类型转换,也就是转入的参数类型要和字段类型一致
|
||||
不要在列上进行运算。
|
||||
尽量不要使用not in 和<> 操作
|
||||
A、not in 和<>操作都不会使用索引,而是进行全表扫描。
|
||||
|
||||
B、把not in 转化为 left join 操作。
|
||||
|
||||
使用批量插入操作代替一个一个插入
|
||||
对于多表查询可以建立视图。
|
||||
7、数据库原则
|
||||
|
||||
(1)不在数据库做运算:cpu计算务必移至业务层
|
||||
|
||||
(2)控制单表数据量:单表记录控制在1000w
|
||||
|
||||
(3)控制列数量:字段数控制在20以内
|
||||
|
||||
(4)平衡范式与冗余:为提高效率牺牲范式设计,冗余数据
|
||||
|
||||
(5)拒绝3B:拒绝大sql,大事物,大批量
|
||||
> 特点:索引能够加快数据库查询,需要占用一定的存储空间。基本表更新后,索引也需要更新。用户不必显示地选择索引,关系数据库管理系统在执行查询时,会自动选择合适的索引作为存储路径。
|
||||
BIN
数据库/数据库.xmind
Normal file
BIN
数据库/数据库.xmind
Normal file
Binary file not shown.
Reference in New Issue
Block a user