1.MySql逻辑架构
| 客户端
____________\|/_____________
| ________________________ |
| |________连接____________| |---客户端通过连接服务,
| ______ ______________ | 将要执行的sql指令传输过来
| | | | 解析sql | |
| | | |--------------| |
| | | | 预处理 | |
| | | |--------------| |
| | 缓存 | | 查询优化器 | |---服务器解析并优化sql,
| | | |--------------| | 生成最终的执行计划并执行
| | | | 生成执行计划 | |
| | | |--------------| |
| | | | 执行 | |
| |______| |______________| |
| ________________________ |
| | | |
| | 存储引擎 | |---存储引擎:负责数据的储存和提取
| |________________________| |
|____________________________|
2.锁
|
|-实现方式划分 |--乐观锁,通常用于数据竞争不激烈的场景,多读少写,通过版本号和时间戳实现
| |--悲观锁,通常用于数据竞争激烈的场景,每次操作都会锁定数据
|
|-影响范围分 |--表锁,锁定整张表,开销最小,但是会加剧锁竞争
| |--行锁,锁定行级别,开销最大,但是可以最大程度的支持并发
| | MVCC是行级锁的变种,多数情况下避免了加锁操作,开销更低
| | MVCC是通过保存数据的某个时间点快照实现的
3.事务隔离级别(事务内和事务间可见性)
|
|--未提交读:(Read UnCommitted),事务中的修改,即使没提交对其他事务也是可见的
| 事务可能读取未提交的数据,造成脏读
|
|--提交读:(Read Committed),一个事务开始时,只能看见已提交的事务所做的修改
| 也叫不可重复读,同一个事务多次读取同样记录可能不同
|
|--可重复读:(RepeatTable Read),同一个事务中多次读取同样的记录结果时结果相同
|
|--可串行化:Serializable),最高隔离级别,强制事务串行执行
4.存储引擎
|
|--InnoDB引擎,最重要,使用最广泛的存储引擎。被用来设计处理大量短期事务,具有高性能和自动崩溃恢复的特性
|
|--MyISAM引擎,不支持事务和行级锁,崩溃后无法安全恢复
5.性能优化
|
|--Schema和数据类型优化 |---数据类型|----(Unsigned)TinyInt,SmallInt,MediumInt,Int,BigInt
| | |----Float,Double,Decimal;VarChar,Char(适合存储固定长度的字符串,如MD5值),Blob,Text
| | |----DateTime,TimeStamp
| |
| |---优化建议:尽量使用对应的数据类型。比如,不要用字符串类型保存时间,用整型保存IP。
|
|--索引|---作用:过滤(filter),排序或分组(sort/group),覆盖(cover)
| |---原则:MySql只能高效的利用索引的最左前缀列
| |
| |---特点|----大部分情况下,索引都比较小,可以加载在内存中;
| | |----当使用覆盖索引时,可以避免很多的磁盘操作,因此对性能也会有极大的改善
| |
| |---按物理存储划分:非聚集索引,聚集索引(叶子节点中存放的即为整张表的行记录数据,通过双向链表进行维护表数据逻辑上的连续)
| |
| |---类型|----主键索引:alert table tablename add primary key (`字段名`)
| | 按使用|----唯一索引: alter table tablename add unique key (`字段名`); |-----单列索引
| | 划分 |----普通索引: alter table tablename add index (`字段名`);---------|-----多列索引
| | |----全文索引: alter table tablename add FULLTEXT(`字段名`); | 包含特殊索引:覆盖索引
| | |
| | |----索引查询:show indexes from `表名`; 或 show keys from `表名`;
| | |----索引删除:alter table `表名` drop index 索引名;
聚集索引
|
|特点:聚集索引不一定是主键,主键默认聚集的,所以是聚集索引;表必须有聚集索引,可以没有主键;
|
|-innodb引擎的聚集索引 |
| |--有主键,那么这个主键就是作为聚集索引
| |--没有主键,那么该表的第一个唯一非空索引被作为聚集索引
| |--没有主键也没有合适的唯一索引,那么innodb内部会生成一个隐藏的主键作为聚集索引,
| | 这个隐藏的主键是一个6个字节的列,该列的值会随着数据的插入自增。
一个使用索引的基本查询的工作流
|
|--step1. 使用索引以查找匹配的记录,并得到数据的指针
|--step2. 使用相关数据的指针
|--step3. 返回查询到的记录
|
|--当可以使用覆盖索引时,索引将会覆盖查询中的所有字段,因此第二步将会被跳过,于是查询流程就变成了下面这样:
|--step1. 使用索引以查找匹配的记录
|--step2. 返回查询到的记录(因为所有的记录都在内存中)
6.索引优化案例
|
|--单个等于查询 |---SELECT * FROM t WHERE c = 100;
| |---//给c字段创建索引
| |---SELECT c1, c2 FROM t WHERE c = 100
| |---//创建一个(c,c1,c2)的索引,因为这样是覆盖索引(注意不是创建(c1,c2,c))
|
|--多个等于查询 |---SELECT * FROM t WHERE c = 100 and d = 'xyz';
| |---//创建索引(c,d)或(d,c)
| |---//最常见的错误是建立两个索引:一个是c,一个是d。
| |---//尽管MySQL根据index_merge算法能同时使用这两个索引,但这样依然是糟糕的选择
|
|--等于与不等于并存的查询 |---SELECT * FROM t WHERE c > 100 and d = 'xyz';
| |---//只要有一列使用了不等于计算,那么它将阻止<其他列>使用索引
| |---//创建一个(d,c)的索引,这时候c和d两个条件都会走索引
|
|--多个不等于查询 |---SELECT * FROM t WHERE c > 100 and b < 10 and d = 'xyz';
| |---//定要把等于条件(在这里是d)所在列,放在索引的最左侧;(创建索引(d,b)或是索引(d,c))
| |---//还可以:按照字段b分区(partition on b),然后创建索引(d,c);
| |---//或按照字段c分区(partition onc),然后创建索引(d,b)
|
|--多个等于与排序 |---SELECT * FROM t WHERE c = 100 and d = 'xyz' ORDER BY b;
| |---//索引中字段的顺序必须:先过滤后排序;创建(c,d,b)或(d,c,b)
| |---SELECT c1, c2 FROM t WHERE c = 100 and d = 'xyz' ORDER BY b
| |---//创建一个集过滤、排序、覆盖于一体的索引:(c,d,b,c1,c2)
|
|--不等于与排序 |---SELECT * FROM t WHERE c > 100 and d = 'xyz' ORDER BY b
| |---//(d,b)或(d,c)。至于哪种效率更高,这取决于你的数据
| |---SELECT * FROM t WHERE c > 100 ORDER BY b
| |---//b和c只能选一种,具体选哪一种同样和你的数据有关