mysql索引,主从多个核心主题去探索问题。

网上收集不错的优化方案

事务 mvcc 详讲

详讲

索引

索引概念

MySQL官方对索引的定义为:索引(index)是帮助MySQL高效获取数据的数据结构(有序)。在数据之外,数据 库系统还维护者满足特定查找算法的数据结构,这些数据结构以某种方式引用(指向)数据, 这样就可以在这些数 据结构上实现高级查找算法,这种数据结构就是索引。如下面的示意图所示 :
![image.png](https://img-blog.csdnimg.cn/img_convert/cb8d7299e79951d2f4ad428c967278c4.png#clientId=ue5dd7c7a-42ef-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=274&id=uda93acc5&margin=[object Object]&name=image.png&originHeight=548&originWidth=1738&originalType=binary&ratio=1&rotation=0&showTitle=false&size=183072&status=done&style=none&taskId=u69fecc7e-5806-4d8f-9f62-53ed58838c6&title=&width=869)
左边是数据表,一共有两列七条记录,最左边的是数据记录的物理地址(注意逻辑上相邻的记录在磁盘上也并不是 一定物理相邻的)。为了加快Col2的查找,可以维护一个右边所示的二叉查找树,每个节点分别包含索引键值和一 个指向对应数据记录物理地址的指针,这样就可以运用二叉查找快速获取到相应数据。
一般来说索引本身也很大,不可能全部存储在内存中,因此索引往往以索引文件的形式存储在磁盘上。索引是数据 库中用来提高性能的最常用的工具。

索引也是一种数据结构而已

索引优势劣势

优势
  1. 类似于书籍的目录索引,提高数据检索的效率,降低数据库的IO成本。
  2. 通过索引列对数据进行排序,降低数据排序的成本,降低CPU的消耗。
劣势
  1. 实际上索引也是一张表,该表中保存了主键与索引字段,并指向实体类的记录,所以索引列也是要占用空间 的。
  2. 虽然索引大大提高了查询效率,同时却也降低更新表的速度,如对表进行INSERT、UPDATE、DELETE。因为 更新表时,MySQL 不仅要保存数据,还要保存一下索引文件每次更新添加了索引列的字段,都会调整因为更新所 带来的键值变化后的索引信息。

索引结构

索引是在MySQL的存储引擎层中实现的,而不是在服务器层实现的。所以每种存储引擎的索引都不一定完全相同,
也不是所有的存储引擎都支持所有的索引类型的。MySQL目前提供了以下4种索引:
BTREE 索引 : 最常见的索引类型,大部分索引都支持 B 树索引。
HASH 索引:只有Memory引擎支持 , 使用场景简单 。
R-tree 索引(空间索引):空间索引是MyISAM引擎的一个特殊索引类型,主要用于地理空间数据类型,通常 使用较少,不做特别介绍。

**Full-text (全文索引) :全文索引也是MyISAM的一个特殊索引类型,主要用于全文索引,InnoDB从 Mysql5.6版本开始支持全文索引。 **
![image.png](https://img-blog.csdnimg.cn/img_convert/8678ff187bb1247b956a7191c22a9e9f.png#clientId=ue5dd7c7a-42ef-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=372&id=u57efa479&margin=[object Object]&name=image.png&originHeight=744&originWidth=1910&originalType=binary&ratio=1&rotation=0&showTitle=false&size=143372&status=done&style=none&taskId=u9d29df53-7de8-4fb7-9f9c-011ba999300&title=&width=955)

BTREE 结构

**BTree又叫多路平衡搜索树,一颗m叉的BTree特性如下: **
树中每个节点最多包含m个孩子。 除根节点与叶子节点外,每个节点至少有[ceil(m/2)]个孩子。 若根节点不是叶子节点,则至少有两个孩子。
所有的叶子节点都在同一层。 每个非叶子节点由n个key与n+1个指针组成,其中[ceil(m/2)-1] <= n <= m-1
以5叉BTree为例,key的数量:公式推导[ceil(m/2)-1] <= n <= m-1。所以 2 <= n <=4 。当n>4时,中间节点分裂到 父节点,两边节点分裂。
插入 C N G A H E K Q M F W L T Z D P R X Y S 数据为例。

演变过程如下:

1). 插入前4个字母 C N G A

![image.png](https://img-blog.csdnimg.cn/img_convert/99a83baeea7f688d3a38baa319fd8f34.png#clientId=ue5dd7c7a-42ef-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=108&id=u0b58f80d&margin=[object Object]&name=image.png&originHeight=216&originWidth=838&originalType=binary&ratio=1&rotation=0&showTitle=false&size=15004&status=done&style=none&taskId=u683e7e43-eed9-44c6-b008-c2c8e1e8b7e&title=&width=419)

2). 插入H,n>4,中间元素G字母向上分裂到新的节点
![image.png](https://img-blog.csdnimg.cn/img_convert/7b1168ba8c55a46ff390d1fe972fcb2c.png#clientId=ue5dd7c7a-42ef-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=226&id=uc091a996&margin=[object Object]&name=image.png&originHeight=452&originWidth=1234&originalType=binary&ratio=1&rotation=0&showTitle=false&size=33319&status=done&style=none&taskId=ubce9215c-acb1-46b9-b814-baa9fb6b16e&title=&width=617)

3). 插入E,K,Q不需要分裂

![image.png](https://img-blog.csdnimg.cn/img_convert/47d317694066045f8e4cc483d450d6a2.png#clientId=ue5dd7c7a-42ef-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=321&id=u961c4516&margin=[object Object]&name=image.png&originHeight=642&originWidth=1400&originalType=binary&ratio=1&rotation=0&showTitle=false&size=106973&status=done&style=none&taskId=u5893d17b-deef-4fd8-bf1a-b18759c4c4c&title=&width=700)

4). 插入M,中间元素M字母向上分裂到父节点G

![image.png](https://img-blog.csdnimg.cn/img_convert/5d7db8ed924ee29d6936b47dfa86873f.png#clientId=ue5dd7c7a-42ef-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=217&id=u3c06e34c&margin=[object Object]&name=image.png&originHeight=434&originWidth=1108&originalType=binary&ratio=1&rotation=0&showTitle=false&size=76190&status=done&style=none&taskId=u13495b2c-04ee-4b51-a96c-1628d538e80&title=&width=554)
5). 插入F,W,L,T不需要分裂

![image.png](https://img-blog.csdnimg.cn/img_convert/8cfbf318bd70a45732b1277d0f765899.png#clientId=ue5dd7c7a-42ef-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=257&id=uc818d24c&margin=[object Object]&name=image.png&originHeight=514&originWidth=1446&originalType=binary&ratio=1&rotation=0&showTitle=false&size=99323&status=done&style=none&taskId=uc1c24b2c-a519-4663-99fd-696d709d465&title=&width=723)

6). 插入Z,中间元素T向上分裂到父节点中

![image.png](https://img-blog.csdnimg.cn/img_convert/b14fdacadf88dbcba54984d71430990f.png#clientId=ue5dd7c7a-42ef-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=210&id=u02381bb7&margin=[object Object]&name=image.png&originHeight=420&originWidth=1380&originalType=binary&ratio=1&rotation=0&showTitle=false&size=103866&status=done&style=none&taskId=u39a4f762-a5c3-45b0-a574-fded4b7267a&title=&width=690)

7). 插入D,中间元素D向上分裂到父节点中。然后插入P,R,X,Y不需要分裂

![image.png](https://img-blog.csdnimg.cn/img_convert/3e593e50765b76ee5253f23f57f16f53.png#clientId=ue5dd7c7a-42ef-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=179&id=u7e9c6f89&margin=[object Object]&name=image.png&originHeight=358&originWidth=1332&originalType=binary&ratio=1&rotation=0&showTitle=false&size=105865&status=done&style=none&taskId=u5391095c-c383-4604-b24f-51d3e148244&title=&width=666)

8). 最后插入S,NPQR节点n>5,中间节点Q向上分裂,但分裂后父节点DGMT的n>5,中间节点M向上分裂
![image.png](https://img-blog.csdnimg.cn/img_convert/3ec0442e30ed987128dba6f751fe943d.png#clientId=ue5dd7c7a-42ef-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=339&id=ud73c171b&margin=[object Object]&name=image.png&originHeight=678&originWidth=1370&originalType=binary&ratio=1&rotation=0&showTitle=false&size=138673&status=done&style=none&taskId=u04f07039-8054-4e91-9402-c100b16fd0c&title=&width=685)

到此,该BTREE树就已经构建完成了, BTREE树 和 二叉树 相比, 查询数据的效率更高, 因为对于相同的数据量来说,BTREE的层级结构比二叉树小,因此搜索速度快。

总结起来相当于就是,**设定一个规则,层级节点的长度,不能高于这个长度,一旦大于这个节点 长度,那么就会将当前节点中间节点往上推一层。**根据这个规则去做 就是 Btree 树

B+TREE 结构

B+Tree为BTree的变种,B+Tree与BTree的区别为:

1). n叉B+Tree最多含有n个key,而BTree最多含有n-1个key。

2). B+Tree的叶子节点保存所有的key信息,依key大小顺序排列。

3). 所有的非叶子节点都可以看作是key的索引部分。

	![image.png](https://img-blog.csdnimg.cn/img_convert/0881f37036d14da39da7122fcf3e2456.png#clientId=ue5dd7c7a-42ef-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=354&id=ued7c117f&margin=[object Object]&name=image.png&originHeight=708&originWidth=1268&originalType=binary&ratio=1&rotation=0&showTitle=false&size=467547&status=done&style=none&taskId=u52387738-5929-4f9c-861d-7aa6cdc0e6d&title=&width=634)

由于B+Tree只有叶子节点保存key信息,查询任何key都要从root走到叶子。所以B+Tree的查询效率更加稳定。

相当于所有的夫节点都是存储了个 指针而已,数据并不同步,找到对应指针后,一直往下查找,找到叶子节点才能把数据找到。排兵布阵一般,打先锋的都是送人头的,只有将前锋消灭完,才能直奔敌方主力大军。

MySQL中的B+Tree

MySql索引数据结构对经典的B+Tree进行了优化。在原B+Tree的基础上,增加一个指向相邻叶子节点的链表指针,就形成了带有顺序指针的B+Tree,提高区间访问的性能
![image.png](https://img-blog.csdnimg.cn/img_convert/546e12e8b3830e0e09fca25d9fd4ab70.png#clientId=ue5dd7c7a-42ef-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=250&id=u70a32d8a&margin=[object Object]&name=image.png&originHeight=500&originWidth=1302&originalType=binary&ratio=1&rotation=0&showTitle=false&size=163394&status=done&style=none&taskId=ucbe43711-fb84-4569-bbfe-bea02c9de17&title=&width=651)

**就是将对应存储数据的叶子结点 区间也新增了个指针,互相指向,这样方便范围查询。 **

索引分类

1) 单值索引 :即一个索引只包含单个列,一个表可以有多个单列索引

就是起个索引名称,直关联 一个字段。

2) 唯一索引 :索引列的值必须唯一,但允许有多个空值(不建议空值,互联网日常开发,就算是空值,也需要约定俗成给一个默认值!!!必须是唯一的)

查找细粒度高。 由于是唯一,所以比较精确。

3) 复合索引 :即一个索引包含多个列

就是起个索引名称,直关联 N个字段。

索引语法
  1. 创建索引
CREATE 	[UNIQUE|FULLTEXT|SPATIAL]  INDEX index_name 
[USING  index_type]
ON tbl_name(index_col_name,...)


index_col_name : column_name[(length)][ASC | DESC]


![image.png](https://img-blog.csdnimg.cn/img_convert/2efc5afd54b4960aaff05f1c445c53ad.png#clientId=ue5dd7c7a-42ef-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=37&id=uc1cbe14e&margin=[object Object]&name=image.png&originHeight=74&originWidth=1260&originalType=binary&ratio=1&rotation=0&showTitle=false&size=45611&status=done&style=none&taskId=uca7c53e2-9bb2-4db9-b594-3dbe9b9fa10&title=&width=630)

  1. 查看索引
show index  from  table_name;

![image.png](https://img-blog.csdnimg.cn/img_convert/907fee3452ca30ff86b78804d310110c.png#clientId=ue5dd7c7a-42ef-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=187&id=u09295228&margin=[object Object]&name=image.png&originHeight=374&originWidth=1260&originalType=binary&ratio=1&rotation=0&showTitle=false&size=98234&status=done&style=none&taskId=u4109069e-abff-4d3e-a828-f3da840ce90&title=&width=630)
![image.png](https://img-blog.csdnimg.cn/img_convert/7d4b4147f61dc13c652da822ead5dacf.png#clientId=ue5dd7c7a-42ef-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=192&id=u16df9af4&margin=[object Object]&name=image.png&originHeight=384&originWidth=1262&originalType=binary&ratio=1&rotation=0&showTitle=false&size=96327&status=done&style=none&taskId=u7f8973f3-e1fb-4808-9805-ba63066dfd4&title=&width=631)

  1. 删除索引
DROP  INDEX  index_name  ON  tbl_name;

![image.png](https://img-blog.csdnimg.cn/img_convert/7bc81c30b684150bbf2da0a674c5a235.png#clientId=ue5dd7c7a-42ef-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=42&id=uca14ec64&margin=[object Object]&name=image.png&originHeight=84&originWidth=1264&originalType=binary&ratio=1&rotation=0&showTitle=false&size=47080&status=done&style=none&taskId=u9be6fc1f-ce2b-44a5-aea8-4893617afeb&title=&width=632)

  1. ALTER命令
# 该语句添加一个主键,这意味着索引值必须是唯一的,且不能为NULL
alter table tb_name add primary key(column_list); 

#这条语句创建索引的值必须是唯一的(除了NULL外,NULL可能会出现多次)
alter table tb_name add unique index_name(column_list); 

#添加普通索引, 索引值可以出现多次。
alter  table  tb_name  add  index index_name(column_list);

#该语句指定了索引为FULLTEXT, 用于全文索引
alter table tb_name add fulltext index_name(column_list); 
索引的设计原则
索引的设计可以遵循一些已有的原则,创建索引的时候请尽量考虑符合这些原则,便于提升索引的使用效率,更高效的使用索引。
  • 对查询频次较高,且数据量比较大的表建立索引。
  • 索引字段的选择,最佳候选列应当从where子句的条件中提取,如果where子句中的组合比较多,那么应当挑选最常用、过滤效果最好的列的组合。
  • 使用唯一索引,区分度越高,使用索引的效率越高。
  • 索引可以有效的提升查询数据的效率,但索引数量不是多多益善,索引越多,维护索引的代价自然也就水涨船高。对于插入、更新、删除等DML操作比较频繁的表来说,索引过多,会引入相当高的维护代价,降低DML操作的效率,增加相应操作的时间消耗。另外索引过多的话,MySQL也会犯选择困难病,虽然最终仍然会找到一个可用的索引,但无疑提高了选择的代价。
  • 使用短索引,索引创建之后也是使用硬盘来存储的,因此提升索引访问的I/O效率,也可以提升总体的访问效率。假如构成索引的字段总长度比较短,那么在给定大小的存储块内可以存储更多的索引值,相应的可以有效的提升MySQL访问索引的I/O效率。
  • 利用最左前缀,N个列组合而成的组合索引,那么相当于是创建了N个索引,如果查询时where子句中使用了组成该索引的前几个字段,那么这条查询SQL可以利用组合索引来提升查询效率。
创建复合索引:

	CREATE INDEX idx_name_email_status ON tb_seller(NAME,email,STATUS);

就相当于
	对name 创建索引 ;
	对name , email 创建了索引 ;
	对name , email, status 创建了索引 ;

视图

视图简介

视图(View)是一种虚拟存在的表。视图并不在数据库中实际存在,行和列数据来自定义视图的查询中使用的表,并且是在使用视图时动态生成的。通俗的讲,视图就是一条SELECT语句执行后返回的结果集。所以我们在创建视图的时候,主要的工作就落在创建这条SQL查询语句上。

视图相对于普通的表的优势主要包括以下几项。

  • 简单:使用视图的用户完全不需要关心后面对应的表的结构、关联条件和筛选条件,对用户来说已经是过滤好的复合条件的结果集。
  • 安全:使用视图的用户只能访问他们被允许查询的结果集,对表的权限管理并不能限制到某个行某个列,但是通过视图就可以简单的实现。
  • 数据独立:一旦视图的结构确定了,可以屏蔽表结构变化对用户的影响,源表增加列对视图没有影响;源表修改列名,则可以通过修改视图来解决,不会造成对访问者的影响。

对视图进行修改 也会影响到源表!!!

实际操作

### 创建视图
#	LOCAL : 只要满足本视图的条件就可以更新。
#	CASCADED : 必须满足所有针对该视图的所有视图的条件才可以更新。 默认值.
create or REPLACE VIEW view_fw_moneys as SELECT * from fw_moneys_copy1
WITH CASCADED CHECK OPTION ;


# 查询视图
select * from view_fw_moneys  WHERE total >= 1000;


# 修改视图
ALTER VIEW view_fw_moneys as SELECT count(1) as total from fw_moneys_copy1


# 删除视图
DROP VIEW view_fw_moneys;

# 视图更改了数据 那么 原始表也会被修改 此操作可见,CRUD 都会影响到 源数据表。
UPDATE view_fw_moneys SET  create_by = 'test' WHERE id = '1430440729691316224';
DELETE from view_fw_moneys WHERE id = '1430440729691316224';
INSERT INTO `hq`.`view_fw_moneys` (`id`, `user_id`, `disappear`, `integral`, `shang_jia`, `money_balance`, `create_by`, `create_time`, `update_by`, `update_time`, `tec_shangjia`, `man_shangjia`) VALUES ('1430440729691316224', '1408342533951574016', 0.000, 0.000, 0.000, 0.00, 'test', '2021-08-25 16:03:41', NULL, '2022-07-16 23:47:47', '0', '0');

存储过程和函数

简介

存储过程和函数是  事先经过编译并存储在数据库中的一段 SQL 语句的集合,调用存储过程和函数可以简化应用开发人员的很多工作,减少数据在数据库和应用服务器之间的传输,对于提高数据处理的效率是有好处的。
存储过程和函数的区别在于函数必须有返回值,而存储过程没有。

函数 : 是一个有返回值的过程 ;

过程 : 是一个没有返回值的函数 ;

delimiter

数据库中的分隔符转换关键字,可以将任何分隔符转换成其他的操作符;
该关键字用来声明SQL语句的分隔符 , 告诉 MySQL 解释器,该段命令是否已经结束了,mysql是否可以执行了。默认情况下,delimiter是分号;。在命令行客户端中,如果有一行命令以分号结束,那么回车后,mysql将会执行该命令。

delimiter $

create procedure pro_test1()
begin
	select 'Hello Mysql' ;
end$

delimiter ;

存储过程操作sql

### 创建存储过程
create PROCEDURE test_1()
BEGIN
SELECT count(1) FROM fw_moneys_copy1;
END;


# 调用存储过程
CALL test_1() ;


# 删除存储过程
DROP PROCEDURE test_1;

语法

存储过程是可以编程的,意味着可以使用变量,表达式,控制结构 , 来完成比较复杂的功能。

in out in/out | 赋值

代表 存储过程|函数 结构参数中可以传递 这两种类型的参数。

  • in 输入
  • out 输出
  • in/out 输入和输出
# 存储过程  参数类型  in  out  in/out
create procedure test_2(in num INT)
BEGIN
select num;
END;

call test_2(10);
create procedure test_3(IN num int,out outint int)
BEGIN
# 2种赋值方式,1,set 赋值,2. into 赋值
SET outint =  num * 10;
select count(1) INTO outint from fw_moneys_copy1;
END;
# 此处 这样调用 
CALL test_3(20,@outint);
select @outint;

**这种变量要在变量名称前面加上“@”符号,叫做用户会话变量,代表整个会话过程他都是有作用的,这个类似于全局变量一样。 **
@@global.sort_buffer_size : 这种在变量前加上 “@@” 符号, 叫做 系统变量

变量

通过 DECLARE 可以定义一个局部变量,该变量的作用范围只能在 BEGIN…END 块中。

### 定义变量
create procedure test_4()
BEGIN
DECLARE num int DEFAULT 3;
select num;
END;
call test_4();

if

create procedure test_5(in top int)
BEGIN

DECLARE formInfo VARCHAR(32) default '太久远了....';

IF top <= 18 and top >= 0
 THEN
 SET formInfo = '少年';
 elseif top <= 50 and top > 18
 THEN
  SET formInfo = '青年';
 else 
  SET formInfo = '老年';
 END if;

select formInfo;
END;

CALL test_5(41);

case when

### case when 2 种语法
# 1. case val when change_val then '' when chage_val then '' else '' end case;
# 2.  CASE

#  WHEN search_condition THEN statement_list
  
#  [WHEN search_condition THEN statement_list] ...
  
#  [ELSE statement_list]
  
# END CASE;

select count( case sex when 0 then 1 else null end) from tb_user;
select count(null) from tb_user;
select case sex when 0 then '女' when 1 then  '男'  else '无性别' end from tb_user;


create procedure test_6(in sexName varchar(32))
BEGIN
DECLARE infoForm VARCHAR(32) DEFAULT '测试';
DECLARE total int default 0;
CASE 
	WHEN sexName = '男'  THEN
	select count(1) into total from tb_user WHERE sex = 1;
	set infoForm = '查询的是男总量';
	WHEN sexName = '女'  THEN
		select count(0) into total from tb_user WHERE sex = 0;
			set infoForm = '查询的是女总量';
	ELSE
		select count(0) into total from tb_user WHERE sex is null;
			set infoForm = '查询的是未知性别总量';
END CASE;
select total ,infoForm;
END;
call test_6('xxx');

循环

while循环
### 循环
## 1. while 循环 和普通的循环无疑
create PROCEDURE test_7(in num int)
BEGIN
declare tempNum int default 0;
while 
num >=0 DO

set tempNum  = tempNum + num;

set  num = num -1;

END 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值