Mysql - 某邦面试题

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只能选一种,具体选哪一种同样和你的数据有关
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章