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

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

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

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

1. 关于主键

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

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

DB_ROW_ID

(全局共享递增)

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

可以用 以下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 |

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

| 篓

上一篇:shell编程之shell基础


下一篇:TeamTalk源码之用户登录验证流程