MySQL数据库,InnoDB5.7学习记录:
一. 部分参数的查询
-- 非正式交互超时时间 如JDBC
show global variables like 'wait_timeout' ;
-- 交互式超时时间
show global variables like 'interactive_timeout' ;
-- 当前数据库连接状态
show global status like 'Thread%';
-- 最大连接数
show global variables like 'max_connections' ;
-- 最大发送数据大小限制
show global variables like 'Max_allowed_packet';
-- 缓存数据相关的参数
show global variables like 'query_cache%' ;
-- 查看数据存放地址
show global variables like 'datadir' ;
二. 缓存和通信
1. MySQL默认缓存开关query_cache_type=OFF关闭的,
2. 缓存起作用需要两个严格条件:
(1). 查询sql完全一致,空格都一致;
(2). 查询sql相关的表所有数据都没有被改变(改变任一一条都刷新);
3.MySql的通信方式: 半双工 - 数据可以双向传输,但是不可同时传输
三. MySQL构成:
1. 连接层: 管理连接,权限验证;
2. 服务层: 实现了binlog日志,记录了DDL与DML的逻辑日志,可用来做主从数据库和数据恢复;
(1). 缓存
(2). 解析器: 词法解析(关键字等) + 语法解析(引号括号是否闭合等), 预处理检查表名字段名;
(3). 优化器: 生成执行计划并根据开销cost选择,包括索引选择;
(4). 执行器: 操作存储引起,返回结果;
3. 存储引擎层: (InnoDB引擎实现了undo日志和redo日志,保证了事务特性)
存储数据,提供读写接口;
四. 客户端执行一条update语句的逻辑处理:
1. 客户端: 提交update的sql: update t_student t.name = '张三' where t.id = 1 ; -- (t_student 是表名)
2. 服务层: 将id=1的name修改,保证在buffer中;
3. 存储引擎层: 修改结果buffer保存到内存中;
4. 存储引擎层: 记录redo log日志,状态为prepare;
5. 存储引擎层: 已修改到内存中,提交事务给服务层;
6. 服务层: 写binlog日志;
7. 服务层: 通知存储引擎层已提交事务commit;
8. 存储引擎层: redo log日志中的记录状态修改为commit状态;
redolog和binlog日志使用两个阶段提交:
为了保证数据的一致性,如果redolog直接commit状态,但是记录binlog失败,则binlog数据丢失,数据不一致;
五. 索引
-- 查看表上的索引
show indexes from t_order ; -- (t_order 是表名)
1. 数据库索引,是数据库管理系统(DBMS)中的一个排序的数据结构,以协助快速查询更新数据;
2. InnoDB引擎的索引结构是B+Tree,优点:
(1). 节省空间,只在叶子节点存放具体数据,主键索引存储的是对应行数据的磁盘地址和数据,二级索引存储索引值和主键索引值;
(2). 叶子节点加了指针,提升了范围查找和排序效率;
(3). 有序数据可预读快;
(4). 多叉树,深度小,千万数据只要深度为2;
3. 聚簇索引(聚集索引): 索引的健值逻辑顺序与表数据行的物理存储顺序一致;
主键索引即为聚集索引,无主键索引则选择非null的唯一索引,没有索引则创建一个隐藏的自增rowid作为聚集索引;
不使用自增id,而使用UUID作为主键,会使得数据的新增修改主键时,频繁的B+Tree的分裂合并;
4. 回表: 二级索引存放索引值和主键值,根据主键值再次查询表数据进行返回;
5. 索引覆盖: 查询具体的索引字段,不需要回表查询就能得到想要的值;
使用了索引覆盖,explain中的extra中显示: Using index
6. ICP: index condition pushdown索引下推; MySQL5.6的优化:
where条件被解析成3部分,index key, index filter, table filter;
ICP优化之前:
存储引擎层: 根据index key的index first key和index last key回表查询所有的数据给服务层;
服务层: 对数据进行索引过滤和数据过滤;
ICP优化之后:
存储引擎层: 根据index key的index first key和index last key定位索引,根据index filter过滤,再回表查询所有的数据给服务层;
服务层: 对数据进行索引过滤和数据过滤;
效果: 减少了回表次数和返回给服务层的数据量;
使用了索引下推,explain中的extra中显示: Using index condition
-- 查看优化器相关开关,其中 ,index_condition_pushdown=on , 索引下推默认开启
show global variables like 'optimizer_switch';
7. 列的离散度: count(disstinct(column_name)) : count(*) 即: 列内所有行的不同值:总行数
例如: 100行数据,性别列的离散度: 2/100 = 0.02
100行数据,自增主键id列的离散度: 100/100 = 1
重复值越多,离散度越低 - 不建议建索引,例如性别列建立了索引,还是要扫描一半的数据表(概率推算,可能男女比例不同);
列数据全部不重复,离散度最高达到1;
-- 查看表上的索引
show indexes from t_order ; -- (t_order 是表名)
其中有列数据: Cardinality,基数列,表示此索引中的不重复记录的预估值(不是不重复记录的具体数值);
索引的不重复记录的预估值大小,表示了不重复记录的相对大小,若很大,就说明不重复数据多,离散度高,建立索引性价比高;
8. 索引中的不重复记录的预估值Cardinality,触发自动计算的条件(满足其一):
(1). 更新了表中16分之一的数据;
(2). 更新了20亿条数据;
手动触发重新计算索引中的不重复记录的预估值Cardinality:
analyze table t_order ; -- (t_order 是表名)
9. 索引的创建:
(1). order by排序和join字段上可建立索引;
(2). 区分度(离散度)低的列不用建立索引,性价比太低;
(3). 索引个数不要太多,会耗费空间,增删数据会引起B+Tree的变动;
(4). 会频繁更新的数据的字段,不要作为主键或索引;
(5). 复合索引的建立,将散列度高的字段放在前面,最左匹配原则;
10. 不触发索引的情况:
(1). 索引列上使用了函数(replace,substr,concat,sum,avg,count),表达式(IF,IFNULL,CASE),不走索引;
(2). 索引列的格式不符,例如字符串索引列,检索条件不加引号,发生隐式转换,不走索引;
(3). like条件的前面带上了%,根据最左匹配原则,不走索引了;
11. MySql是基于开销的优化器: Cost Base Optimizer; (Oracle的优化器基于规则)
12. 负向查询: not in , not null , not like , != , <>
负向查询是否使用索引? 答案: 不一定!
MySql是否使用索引,是由优化器决定的!
MySql是基于开销的优化器,而同一个查询sql,在数据库内的数据不同时的开销都是不同的,所以负向查询不确定寿是否使用索引!