ICode9

精准搜索请尝试: 精确搜索
首页 > 数据库> 文章详细

mysql8 sql优化相关(持续更新...)

2021-06-30 11:01:30  阅读:219  来源: 互联网

标签:bin ... uuid 16 mysql8 sql true id UUID


能明确知道哪里会慢,为什么会慢

优化的本质是减少IO,减少随机IO,减少比较和排序(费cpu)

1. 关于主键

mysql8 innodb 表必定有主键,第一种方法是自己显示定义

如果没有显示定义,mysql 自动在表中添加

DB_ROW_ID

(全局共享递增)

可以用 以下sql 查看隐藏列

 show extended columns from `表名`

第一种观点 不能用UUID 做主键      

https://www.percona.com/blog/2019/11/22/uuids-are-popular-but-bad-for-performance-lets-discuss/   UUIDs are Popular, but Bad for Performance — Let’s Discusshttps://opensource.actionsky.com/20191219-percona/  这篇文章是 上一篇文章的翻译

原因:

1. innodb 聚簇索引需要排序导致页频繁拆分,这个是主要原因

2. UUID 太长,对于二级索引来说占用空间太大

3. UUID 是字符串,查询时用字符串比较效率低于整型

第二种观点  可用做主键

1. 替代方案 UUID_SHORT()

2. 参考文章

https://www.jianshu.com/p/0c5b477b2eb6  The UUID in MySQL8

https://blog.csdn.net/weixin_39531229/article/details/113670333  uuid 能当主键吗?

打算使用UUID,您应该阅读MySQL8.0中UUID的支持,推荐用binary(16) 存储UUID

CREATE TABLE t (id binary(16) PRIMARY KEY);
INSERT INTO t VALUES(UUID_TO_BIN(UUID()));
  使用uuid_to_bin() 可能会改变MySQL的UUID实现的顺序行为

UUID是由32位16进制字符串组成(不算分隔符'-')如:

62ab1547-710f-11e8-9a58-5254007205d6

如果直接保存,则需要32个字符,utf8编码下占用96个字节,对于主键来说还是太长。
幸运的是UUID中的每个字符都是16进制字符,两个16进制字符占用一个字节,
这样可以轻松将UUID转换为binary(16),占用16个字节,所需空间大大减少,而且二进制字符串检索对比效率很高。

An option in MySQL 8 is to use the UUID_TO_BIN()
function with a second argument set to 1 which will make MySQL swap the
first and third groups of hexadecimal digits.


一个至关重要的问题是UUID的组成中将timestamp 部分的低位时间段(如毫秒)放在了前面,高位时间段(如年月日)放在了后面,
这会导致前面的字符变化很快,后面的变化很慢,从而使产生的UUID不能顺序自增。这会导致索引插入效率大大降低。

为解决这一问题,mysql8提供了两个函数:UID_TO_BIN(arg1) /  BIN_TO_UUID(arg1,arg2)

UID_TO_BIN(arg1) 将UUID转化为16位二进制字符串,如果参数arg1为true则将UUID中的timestamp部分中的time-low(第一段字符)和time-high(第三段)调换,这样产生的UUID是顺序递增。

BIN_TO_UUID(arg1,arg2)将16位进制字符串转化为可读的UUID,arg1为16位二进制字符串,如果arg2省略或为false,即将二进制字符串原位转换;如果arg2为true,则将原来调换的time-low和time-high再调换回去,返回原本的uuid.


测试

创建一张表如下:

mysql8[test]>create table t (id varbinary(16) primary key,create_time timestamp default current_timestamp());

Query OK, 0 rows affected (0.34 sec)

插入几条数据,注意使用了函数uuid_to_bin:

mysql8[test]>insert into t (id)values(uuid_to_bin(uuid(),true));

Query OK, 1 row affected (0.08 sec)

mysql8[test]>insert into t (id)values(uuid_to_bin(uuid(),true));

Query OK, 1 row affected (0.08 sec)

mysql8[test]>insert into t (id)values(uuid_to_bin(uuid(),true));

Query OK, 1 row affected (0.07 sec)

查看结果:

mysql8[test]>select bin_to_uuid(id) id1,bin_to_uuid(id,true) id2, create_time from t;

+--------------------------------------+--------------------------------------+---------------------+

| id1 | id2 | create_time |

+--------------------------------------+--------------------------------------+---------------------+

| 11e87113-f079-024e-8405-5254004332fa | f079024e-7113-11e8-8405-5254004332fa | 2018-06-16 11:18:28 |

| 11e87113-f826-4134-8405-5254004332fa | f8264134-7113-11e8-8405-5254004332fa | 2018-06-16 11:18:41 |

| 11e87113-f88c-c8a6-8405-5254004332fa | f88cc8a6-7113-11e8-8405-5254004332fa | 2018-06-16 11:18:42 |

+--------------------------------------+--------------------------------------+---------------------+

3 rows in set (0.00 sec)

注意字段id1使用了函数bin_to_uuid(id), 而id2使用了bin_to_uuid(id,true),注意他们在结果集中的区别。

如果需要按主键查询,还是需要使用对应的uuid函数:

mysql8[test]>select * from t where id=uuid_to_bin('f079024e-7113-11e8-8405-5254004332fa',true);

+------------------+---------------------+

| id | create_time |

+------------------+---------------------+

| 篓

标签:bin,...,uuid,16,mysql8,sql,true,id,UUID
来源: https://blog.csdn.net/xuejianxinokok/article/details/118354964

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有