一、 limit

1. 测试案例
-- 创建表 ![在这里插入图片描述](https://img-blog.csdnimg.cn/cover1/248667912046641316.jpg?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,image_MjAyMDA3MTUxNjIxMDEzOC5wbmc=,size_16,color_FFFFFF,t_70,image/resize,m_lfit,w_962)DROP TABLE IF EXISTS `rental`;
CREATE TABLE `rental` (`rental_id` int(11) NOT NULL AUTO_INCREMENT,`rental_date` datetime NOT NULL,`inventory_id` mediumint(8) unsigned NOT NULL,`customer_id` smallint(5) unsigned NOT NULL,`return_date` datetime DEFAULT NULL,`staff_id` tinyint(3) unsigned NOT NULL,`last_update` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,PRIMARY KEY (`rental_id`)
)  -- 查询语句
select * from rental limit 1000000,20-- 可替代语句
select * from rental a join (select rental_id from rental limit 1000000,20 ) b on a.rental_id = b.rental_id -- 主键自增 有序 也可以这样
select * from rental a where a.rental_id >= (select rental_id from rental limit 1000000,1) limit 20 -- 有人会想到用IN   看下图图图图图  我用的这个版本不支持其他没测试不知道了
select * from rental a where a.rental_id in (select rental_id from rental limit 1000000,20)  -- 前三个哪个好一点呢 这个需要实际场景中 根据自己的实际数据进行测试 和预测 -- 看过一篇博客 说是百万级别内 limit 1000000,20 比较好
-- 千万级别及以上 后边2中比较好
-- sql优化 还是那句话  没有绝对  只有测试结果 一定要根据自己的场景进行测试 合适自己的鞋 只有自己试了才知道  合适自己的女朋友只有自己处了才知道 合适自己的路 只有自己走了才知道


2. 尽量使用覆盖索引 1中的join 就是用了主键优化查询了

二、 优化UNION

  1. 除非确实需要服务器消除重复的行,否则一定要使用union all,没有all关键字的话,mysql在查询的时候会给临时表加上distinct关键字 ,这个操作比较耗性能

  2. 行转列的时候 可能会用到union

Mysql行转列 测试

--创建表
CREATE TABLE `score_table` (`stuname` VARCHAR (255) NULL,`classname` VARCHAR (255) NULL,`score` FLOAT NULL
);-- 插入数据
INSERT INTO `score_table` VALUES ('黄渤', '唱歌', '60');
INSERT INTO `score_table` VALUES ('邓紫棋', '唱歌', '90');
INSERT INTO `score_table` VALUES ('孙漂亮', '唱歌', '50');
INSERT INTO `score_table` VALUES ('黄渤', '演技', '80');
INSERT INTO `score_table` VALUES ('邓紫棋', '演技', '70');
INSERT INTO `score_table` VALUES ('孙漂亮', '演技', '90');


我想要的结果是:姓名 , 演技成绩, 唱歌成绩

 -- 方式1   max
select
stuname,
max(case classname when '演技' then score else 0 end) 演技分数,
max(case classname when '唱歌' then score else 0 end) 唱歌分数
from score_table
group by stuname -- 方式1.5  if
select
stuname,
sum(if( classname='演技' ,score,0) ) 演技分数,
sum(if( classname='唱歌' ,score,0)) 唱歌分数
from score_table
group by stuname -- 方式2  sum
select
stuname,
sum(case classname when '演技' then score else 0 end) 演技分数,
sum(case classname when '唱歌' then score else 0 end) 唱歌分数
from score_table
group by stuname -- 方式3  子查询
select
distinct stuname ,
(select score from score_table b where b.stuname = a.stuname and b.classname='演技') 演技分数,
(select score from score_table b where b.stuname = a.stuname and b.classname='唱歌') 唱歌分数
from score_table a-- 方式4 可以mysql使用存储过程 或者函数来处理

-- 方式5
SELECT stuname,GROUP_CONCAT(classname,':',score) AS 成绩 FROM score_table
GROUP BY stuname

-- 方式6
select a.stuname,a.score as '演技分数',b.score  as '唱歌分数' from
(select stuname , score from score_table where classname ='演技') a
left JOIN
(select stuname , score from score_table where classname ='唱歌') b
on a.stuname = b.stuname -- 方式7
select a.stuname ,sum(a.演技分数) 演技分数, sum(a.唱歌分数)唱歌分数
from (
select stuname ,score 演技分数 , 0 唱歌分数 from score_table where classname ='演技'
union all
select stuname ,0 演技分数 , score 唱歌分数 from score_table where classname ='唱歌'
) a
group by a.stuname

三、推荐使用用户自定义变量

1. 自定义变量的使用
set @one :=1
select @one --结果 1
select @one:=@one+1 --结果 2  
-- 可以加sql语句
set @min_rental_id :=(select min(rental_id) from rental)select @min_rental_id  --结果 1
-- 可以加函数
set @last_week:=current_date-interval 1 week;select  @last_week  --  2020-07-16
 select @isEnd:=10 -- 结果10 并且或赋值给@isEndselect @isEnd -- 结果 10
2. 自定义变量的限制
  1. 当前会话有效 无法使用缓存

  2. 不能在使用常量或者标识符的地方官使用自定义变量,例如表名 limit子句

  3. 用户自定义变量在一个连接内有效 所以不能作为连接之间的通信数据使用 一个session有效

  4. 不能显示的生命自定义变量类型

  5. mysql优化器 在某些场景下 可能会把自定义变量优化掉,可能不会按照自己想的意愿进行

  6. 赋值符号 := 的优先级非常低 所以在使用赋值表达式的时候应该明确的使用括号
    select a.*,(@aa:=1) from actor a;

  7. 使用未定义变量 不会产生语法错误
    select @bbbbbbbbbbb; – 没有错误

  8. 有人说mybatis不支持 自定义变量 我测试了一个版本 简单的可以支持 复杂的没测试

pom mybatis版本 :

接口+xml:


测试类:

输出结果:

3.自定义变量的案例
  1. 排序
set @rownum:=0;select city,@rownum:=@rownum+1 as   rownum from city limit 10 -- 案例2
-- 这是个错误的案例
set @rownum=0;
select actor_id,count(*) cnt,@rownum:=@rownum+1  from film_actor group by actor_id order by cnt limit 10 -- 分组的时候 要把分组放在子查询
set @rownum=0;
select * , @rownum:=@rownum+1   as num from
(
select actor_id,count(*) cnt from film_actorgroup by actor_id order by cnt limit 10
) a



2. 避免重复查询刚刚更新的数据

-- 创建表
CREATE TABLE `test` (
`id`  int NOT NULL ,
`t_date`  datetime NULL ,
`name`  varchar(255) NULL ,
PRIMARY KEY (`id`)
)
-- 插入数据
INSERT INTO `sakila`.`test` (`id`, `t_date`, `name`) VALUES ('1', '2020-07-25 10:07:01', '测试');--  跟新id为1的数据的时间 并再次查询
update `sakila`.`test` set t_date = now() where id=1
select t_date from `sakila`.`test` where id=1-- 第二种方式
update `sakila`.`test` set t_date = now() where id=1 and @now:=now()
select @now ;
  1. 确定取值的顺序问题 在赋值和取变量的时候可能不在一个阶段
-- 还是上边test表
INSERT INTO `sakila`.`test` (`id`, `t_date`, `name`) VALUES ('2', '2020-07-25 10:26:00', '测试2');
INSERT INTO `sakila`.`test` (`id`, `t_date`, `name`) VALUES ('3', '2020-07-25 10:26:11', '测试3');-- 1
set @rownum:=0;
select name,@rownum:=@rownum+1 from test  where @rownum<=1
可能是先走where 判断第一条数据@rownum<=1   正确
走select字段 @rownum:=@rownum+1
再走where 再判断第二条数据 @rownum<=1   正确
@rownum:=@rownum+1
再走where 再判断第二条数据 @rownum<=1   错
-- 2
set @rownum:=0;
select name,@rownum:=@rownum+1 from test  where @rownum<=1 order by t_date
讲道理是先过滤再排序 这里好像是先排序后过滤了 所以所有数据都查出来了
-- 3
set @rownum:=0;
select name,@rownum from test  where (@rownum:=@rownum+1)<=1这个也是先走where 但是where的时候执行了@rownum:=@rownum+1
相比1中的在select字段中+1 就少了一条数据
--


-------------------!分区表!

https://www.mysql.com/
– 分区表相关介绍
https://dev.mysql.com/doc/refman/8.0/en/partitioning.html
InnoDB 每个表默认2个文件 x.frm(表结构元数据) x.ibd(索引+数据)

MyISAM 默认3个文件 x.frm x.MYD(数据) x.MYI(索引)

**总结:**可以按照自己定义的规则,把一个表分成多个文件存储带"#",分而治之

检索的时候 IO 量就少了

1.应用场景
1. 表很大无法全放内存,或者只在表的最后部分有热点数据,其他部分都是历史数据
2. 分区表数据更容易进行维护 批量删除大量数据的时候,可以清除指定分区对一个独立的分区进行优化、检查、修复等操作
3. 分区表的数据可以分布在不同的物理设备上 从而更高效的利用物理设备
4. 可以使用分区表,避免某些特殊瓶颈innodb单个索引 互斥访问,innodb加锁是给索引加锁的,如果分区了 效率就高了ext3文件系统inode锁竞争 ls -li 展示第一列就是inode  分区的话就相当于是1.7hash的segment了
5. 可以备份和恢复 独立分区
2.分区表的限制
1. 早期mysql中 分区表表达式必须是整数,或者返回整数的表达式mysql5.5中  某些场景可以使用列来分区
2. 一个表最多只能有1024个分区, 5.7支持8196个分区  -- 这个与linux文件系统相关的 unlimited 3. 分区表的分区表达式中使用的所有列都必须是表可能具有的每个唯一键的一部分,
换句话说,表上的每个唯一键都必须使用表的分区表达式中的每一列
官网地址:
https://dev.mysql.com/doc/refman/8.0/en/partitioning-limitations-partitioning-keys-unique-keys.html这个需要翻来覆去的看官网的几个错误的和正确的例子
我是这样理解的 不知道对不对:
分区表达式中有的列 表的唯一键和主键都必须包含
举例子
分区表达式有列col_a  col_b
那么unique字段和主键 必须包含col_a col_b 这俩字段
也就是说 分区表达式的字段是unique的子集 也是主键的子集  见下图4. 分区表无法使用外键约束

3.分区表简单使用

6种分区类型:
范围分区、列表分区、列分区、hash分区、KEY分区、子分区
https://dev.mysql.com/doc/refman/8.0/en/partitioning-types.html

秘钥

CREATE TABLE employees (id INT NOT NULL,fname VARCHAR(30),lname VARCHAR(30),hired DATE NOT NULL DEFAULT '1970-01-01',separated DATE NOT NULL DEFAULT '9999-12-31',job_code INT NOT NULL,store_id INT NOT NULL
)
PARTITION BY RANGE (store_id) (PARTITION p0 VALUES LESS THAN (6), -- store_id小于6 放这个分区PARTITION p1 VALUES LESS THAN (11),-- store_id大于6,小于11 放这个分区PARTITION p2 VALUES LESS THAN (16),-- store_id大于11,小于16 放这个分区PARTITION p3 VALUES LESS THAN MAXVALUE-- store_id 大于16,小于INT最大值 放这个分区
);-- 还可以根据日期分区  各种高级应用场景-- 修改的时候 最好不要修改分区键 -- 有人说了,我们表刚开始没有建立分区,现在有数据了已经,还能再建立分区吗,当然可以!https://dev.mysql.com/doc/refman/8.0/en/partitioning-maintenance.htmlALTER TABLE t1 REBUILD PARTITION p0, p1;

4. 分区表原理

分区表是由多个底层表实现的,这个底层表也是由句柄对象标识,我们可以直接访问各个分区,存储引擎管理分区各个底层表和管理普通表一样(所有底层表都必须使用相同的存储引擎),分区表的索引只是在各个底层表上各自加上一个完全相同的索引。
从存储引擎的角度来开,底层表和普通表没有任何不同,存储引擎也无须知道这是一个普通表还是一个分区表
感觉有点儿像是1.7hashmap的segment桶
分区表的增删改查操作逻辑:

  1. select 查询
    当查询一个分区表的时候,分区层先打开并锁住所有的底层表,优化器判断是否可以过滤部分分区,然后再调用对应的存储引擎接口访问各个分区的数据

  2. insert 操作
    当写入一条数据的时候,分区层先打开并锁住所有的底层表,然后确定哪个分区接受这条记录,然后将记录写入对应的底层报表

  3. update 操作
    更新一条记录时,分区层先打开并锁住所有的底层表,mysql先确定需要更新的记录在哪个分区,然后取出数据进行更新,再判断更新后数据应该再哪个分区,最后对底层表进行写入操作,并对源数据所在的底层进行删除操作

  4. delete 操作
    当删除一条记录时,分区层先打开并锁住所有的底层表,mysql确定要删除的记录在哪个分区,最后对相应的底层表进行删除操作

     有些操作支持过滤,例如删除一条记录时,Mysql需要先找到这条记录,如果where条件恰好和分区表达式匹配,就可以将所有不包含这条记录的分区都过滤掉,对于update同样有效对于insert操作 本身就是只命中一个分区,其他分区都会被过滤掉。虽然每个操作都会先锁住所有的底层表,但是这并不是说分区表在处理的过程中会锁住全表,**如果存储引擎能够自己实现行级锁,例如InnoDB 则会在分区层释放对应的表锁**
    

5. 分区表类型

https://dev.mysql.com/doc/refman/8.0/en/partitioning-types.html
范围分区、列表分区、列分区、hash分区、秘钥分区、子分区

  1. 范围分区
    https://dev.mysql.com/doc/refman/8.0/en/partitioning-range.html
-- 普通范围分区
CREATE TABLE employees (id INT NOT NULL,fname VARCHAR(30),lname VARCHAR(30),hired DATE NOT NULL DEFAULT '1970-01-01',separated DATE NOT NULL DEFAULT '9999-12-31',job_code INT NOT NULL,store_id INT NOT NULL
)
PARTITION BY RANGE (job_code) (PARTITION p0 VALUES LESS THAN (100),PARTITION p1 VALUES LESS THAN (1000),PARTITION p2 VALUES LESS THAN (10000)
);-- 包含最大值MAXVALUE 包含函数YEAR    范围分区
CREATE TABLE employees (id INT NOT NULL,fname VARCHAR(30),lname VARCHAR(30),hired DATE NOT NULL DEFAULT '1970-01-01',separated DATE NOT NULL DEFAULT '9999-12-31',job_code INT,store_id INT
)
PARTITION BY RANGE ( YEAR(separated) ) (PARTITION p0 VALUES LESS THAN (1991),PARTITION p1 VALUES LESS THAN (1996),PARTITION p2 VALUES LESS THAN (2001),PARTITION p3 VALUES LESS THAN MAXVALUE
);-- 使用UNIX_TIMESTAMP 范围分区
CREATE TABLE quarterly_report_status (report_id INT NOT NULL,report_status VARCHAR(20) NOT NULL,report_updated TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
)
PARTITION BY RANGE ( UNIX_TIMESTAMP(report_updated) ) (PARTITION p0 VALUES LESS THAN ( UNIX_TIMESTAMP('2008-01-01 00:00:00') ),PARTITION p1 VALUES LESS THAN ( UNIX_TIMESTAMP('2008-04-01 00:00:00') ),PARTITION p2 VALUES LESS THAN ( UNIX_TIMESTAMP('2008-07-01 00:00:00') ),PARTITION p3 VALUES LESS THAN ( UNIX_TIMESTAMP('2008-10-01 00:00:00') ),PARTITION p4 VALUES LESS THAN ( UNIX_TIMESTAMP('2009-01-01 00:00:00') ),PARTITION p5 VALUES LESS THAN ( UNIX_TIMESTAMP('2009-04-01 00:00:00') ),PARTITION p6 VALUES LESS THAN ( UNIX_TIMESTAMP('2009-07-01 00:00:00') ),PARTITION p7 VALUES LESS THAN ( UNIX_TIMESTAMP('2009-10-01 00:00:00') ),PARTITION p8 VALUES LESS THAN ( UNIX_TIMESTAMP('2010-01-01 00:00:00') ),PARTITION p9 VALUES LESS THAN (MAXVALUE)
);
  1. 列表分区
    https://dev.mysql.com/doc/refman/8.0/en/partitioning-list.html
    类比sql中的in条件 java总的List#contains
CREATE TABLE employees (id INT NOT NULL,fname VARCHAR(30),lname VARCHAR(30),hired DATE NOT NULL DEFAULT '1970-01-01',separated DATE NOT NULL DEFAULT '9999-12-31',job_code INT,store_id INT
)
PARTITION BY LIST(store_id) (PARTITION pNorth VALUES IN (3,5,6,9,17),PARTITION pEast VALUES IN (1,2,10,11,19,20),PARTITION pWest VALUES IN (4,12,13,14,18),PARTITION pCentral VALUES IN (7,8,15,16)
);
  1. 列分区
    https://dev.mysql.com/doc/refman/8.0/en/partitioning-columns.html

1+2 + 无类型限制 = 3
范围分区+列表分区+无类型限制 = 列分区

 CREATE TABLE rcx (a INT,b INT,c CHAR(3),d INT)PARTITION BY RANGE COLUMNS(a,d,c) (PARTITION p0 VALUES LESS THAN (5,10,'ggg'),PARTITION p1 VALUES LESS THAN (10,20,'mmm'),PARTITION p2 VALUES LESS THAN (15,30,'sss'),PARTITION p3 VALUES LESS THAN (MAXVALUE,MAXVALUE,MAXVALUE));
  1. hash分区
    https://dev.mysql.com/doc/refman/8.0/en/partitioning-hash.html
-- 根据store_id取hash值 再模上4  跟HashMap很像
CREATE TABLE employees (id INT NOT NULL,fname VARCHAR(30),lname VARCHAR(30),hired DATE NOT NULL DEFAULT '1970-01-01',separated DATE NOT NULL DEFAULT '9999-12-31',job_code INT,store_id INT
)
PARTITION BY HASH(store_id)
PARTITIONS 4;
  1. KEY分区
    https://dev.mysql.com/doc/refman/8.0/en/partitioning-key.html
    就是hash的一个变种 使用主键+唯一键
-- 不指定列
CREATE TABLE k1 (id INT NOT NULL PRIMARY KEY,name VARCHAR(20)
)
PARTITION BY KEY()
PARTITIONS 2;-- 指定列
CREATE TABLE tm1 (s1 CHAR(32) PRIMARY KEY
)
PARTITION BY KEY(s1)
PARTITIONS 10;
  1. 子分区
    https://dev.mysql.com/doc/refman/8.0/en/partitioning-subpartitions.html
CREATE TABLE ts (id INT, purchased DATE)PARTITION BY RANGE( YEAR(purchased) )SUBPARTITION BY HASH( TO_DAYS(purchased) )SUBPARTITIONS 2 (PARTITION p0 VALUES LESS THAN (1990),PARTITION p1 VALUES LESS THAN (2000),PARTITION p2 VALUES LESS THAN MAXVALUE);

就是在分区的基础上 再进行分区

这是一般分区格式:

这是子分区格式:

6. 如何使用分区表

  1. 全量扫描数据 不要任何索引
    使用简单的分区方式存放表,不需要任何索引,根据分区规则大致定位需要的数据位置,通过使用where条件,将数据限制在几个分区范围内。这种策略适合正常方式访问大量数据

  2. 索引数据 并分离热点
    比如说最近一个月是热数据 之前月份是历史数据
    能够使用索引 也能使用缓存

7. 分区表注意事项

  1. null值可能对分区无效
  2. 分区列和索引不匹配 可能会导致查询无法进行分区过滤
  3. 选择分区的时候 成本可能很高 粒度越小可能成本越高
  4. 打开并锁住所有底层表的成本可能会很高
  5. 维护分区表成本可能很高

mysql优化 个人笔记 (mysql 进阶索引 ) 非礼勿扰 -m15相关推荐

  1. mysql优化 个人笔记 (mysql 进阶索引 ) 非礼勿扰 -m14

    查询优化 1. 查询慢的可能原因 网络 CPU (时间片) IO (磁盘) 上下文切换 (线程切换) 系统调用 生成统计信息 锁等待时间 2. 优化数据访问 查询性能低的主要原因是访问的数据太多,某些 ...

  2. mysql优化 个人笔记 (mysql 进阶索引 ) 非礼勿扰 -m12

    索引优点 减少服务器需要扫描的数据量 帮助服务器避免排序和临时表 将随机IO编程顺序IO 应用场景 快速匹配where字句的行 从consideration中消除行,如果可以在多个索引之间进行选择,m ...

  3. mysql优化 个人笔记 (mysql 进阶索引 ) 非礼勿扰 -m13

    接上一篇 一.union all .in .or -- 还是老朋友 dd DROP TABLE IF EXISTS `dd`; CREATE TABLE `dd` (`d1` varchar(255) ...

  4. mysql优化 个人笔记 (mysql锁机制 ) 非礼勿扰 -m10

    锁机制 A : undolog 实现 C : I :锁实现 D :redolog实现 1. mysql锁基本介绍 锁是计算机协调多个进程或线程并发访问某一资源的机制 在数据库中 除了传统的计算机资源( ...

  5. mysql优化 个人笔记 (mysql 主从复制 ) 非礼勿扰 -m11

    1.为什么需要主从复制 在业务中 有一条sql需要锁表 就会导致其他读业务不能执行 ,那么就很影响业务,使用主从复制,让主库写,从库读.这样即使主库出现锁表情况,从库也可以正常使用,保证业务正常进行 ...

  6. mysql优化说出九条_技术分享 | MySQL 优化:为什么 SQL 走索引还那么慢?

    原标题:技术分享 | MySQL 优化:为什么 SQL 走索引还那么慢? 背景 2019-01-11 9:00-10:00 一个 MySQL 数据库把 CPU 打满了. 硬件配置:256G 内存,48 ...

  7. mysql数据库优化课程---15、mysql优化步骤(mysql中最常用最立竿见影的优化是什么)...

    mysql数据库优化课程---15.mysql优化步骤(mysql中最常用最立竿见影的优化是什么) 一.总结 一句话总结:索引优化最立竿见影 索引优化:不然有多少行要扫描多少次,1亿行大概是5到10分 ...

  8. MySQL优化(二):索引的类型、匹配原则、创建原则

    目录 索引的优缺点 索引类型 聚簇索引(主键索引) 非聚簇索引(二级索引.辅助索引) 索引匹配的原则 最左匹配原则 无法使用索引的场景 索引创建的原则 使不使用索引的依据到底是什么? 参考 索引的优缺 ...

  9. Mysql 优化(学习笔记二十)

    https://blog.csdn.net/steven_liwen/article/details/53188411 运维角度mysql优化:https://www.cnblogs.com/shen ...

最新文章

  1. python工程师待遇-Python工程师待遇如何 玩转Python看这里
  2. Eclipse快捷键:最常用且高效的快捷键
  3. 使用navicat 11 出现不能返回存储过程结果的问题
  4. 记录一次Socket的异常:InputStream.read()阻塞问题
  5. Vue.js第六课 计算属性
  6. 活动目录数据库授权恢复
  7. 高性能网站建设的最佳实践(二)
  8. url地址传参中文乱码处理
  9. 《操作系统》OS学习(四):计算机体系结构、内存层次和地址生成
  10. [luogu4133 BJOI2012] 最多的方案 (计数dp)
  11. 7-234 两个有序序列的中位数 (25 分)
  12. 【Python系列】python GUI界面
  13. WinAPI: SetTextJustification - 设置两端对齐
  14. 常见熟知端口号的记忆技巧
  15. Java毕设项目——大学生社团管理系统(java+SSM+Maven+Mysql+Jsp)
  16. css 首行缩进两字符
  17. 文件删除如何恢复?电脑数据恢复,4个详细方法
  18. RuntimeError: CUDA error: invalid device ordinal
  19. Timeboxing——业界大佬都在用的时间管理法
  20. java使用递归,复制文件夹下的所有子文件

热门文章

  1. python项目回顾
  2. Openwrt二级路由获取IPV6
  3. react配置二级路由
  4. @Transactional注解的作用
  5. 如何获取每月第一个/最后一个交易日
  6. 暂退法(Dropout)
  7. “纳米光学先驱”师生档详解光计算,全球首款商用光子芯片即将问世-1
  8. 2021/1/8-每日三题第15弹:终于放假啦,你知道清除浮动有哪些方式吗 ???
  9. UGUI使用BMFont制作美术字体二
  10. UUID介绍与使用范围