mysql uuid 前缀索引_Mysql使用Java UUID作为唯一值时使用前缀索引测试

本文探讨了在MySQL中使用字符串前缀作为索引来节省存储空间的方法,通过测试UUID生成的32位字符串,分析不同长度前缀的索引选择性。随着数据量增加,前缀索引的选择性会降低,例如在2000万数据时,前7位和前9位的索引选择性分别为0.96和0.9999。建议根据业务数据量选择合适的前缀长度,以平衡索引效率和空间占用。前缀索引虽节省空间,但不支持ORDER BY和GROUP BY查询,也不能作为覆盖索引使用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Mysql可以使用字符串前缀 作为索引 以节约空间。

下面我们以 Java的UUID 生成的 32位(移除UUID中的 中划线)字符串 来做一下 测试。

表结构:

CREATE TABLE `test_uuid` (

`id` int(10) unsigned NOT NULL AUTO_INCREMENT,

`uuid` varchar(36) DEFAULT NULL,

PRIMARY KEY (`id`)

) ENGINE=InnoDB AUTO_INCREMENT DEFAULT CHARSET=utf8

UUID生成的方式(不考虑replaceAll的替换效率):

UUID.randomUUID().toString().replaceAll("-", "")

查询 不同长度的前缀索引效率(索引的选择性,即不重复的索引值)的SQL:

select

count(DISTINCT uuid) / count(*) as total,

count(DISTINCT LEFT(uuid,5)) / count(*) as five,

count(DISTINCT LEFT(uuid,6)) / count(*) as six,

count(DISTINCT LEFT(uuid,7)) / count(*) as seven,

count(DISTINCT LEFT(uuid,8)) / count(*) as eight,

count(DISTINCT LEFT(uuid,9)) / count(*) as nine,

count(DISTINCT LEFT(uuid,10)) / count(*) as ten

from test_uuid;

下面看一下测试数据及结果:

20W数据

fcd20b03b0c3c4604025d919d68a3d1b.png

40W

504bf951c51e0b125b2be32a46efd311.png

60W

512c1ae04a08f4e3c7ddbd886ee0e9c4.png

80W

a46fd6ad33b91f376081aae88bcdd40c.png

100W

ad9f22061a64de4a8196a2f98fc607f0.png

200W

e9c0439c46198275510a2321083ee9bb.png

300W

c97ed098eec9612e6c9ae4768ef41065.png

500W

1f19d092ab5f860a8f481e2cf3a0755a.png

1000W

de99df3e4ba1103751a409095fc425ff.png

2000W

f3ae7fe77fe3edde6407cbf55d8cdae0.png

随着数据量的增多,同样长度的前缀索引选择性 逐渐降低。

前7位 在2000W数据的时候损失了 0.04, 也就是说 每100 条数据, 会有4条与其他96条数据 有重复。

前9位 在2000W数据的时候损失了 0.0001 ,也就是说 每10000 条数据,会有1 条与 其他 9999条有重复。

前10位 在2000W数据的时候 选择行 依然为1 (前10位没有任何重复的)。

大家可以算一下 26的10次方,大概是 141 万 亿。

当然,以上数据 我只做过一次, 其他测试数据应该与 本次测试数据 稍有不同,但可以肯定的是:不会相差很多。

所以,当业务需要使用 uuid 作为 业务唯一的key时, 可以评估业务数据量,选择合适长度的前缀索引。

前缀索引的选择性 越接近 总长度索引的选择性 时,说明已经可以了。

但是,前缀索引有一些缺点:

1. Mysql 前缀索引 不支持 order by 和 group by 查询。

2 Mysql 前缀索引 不能作为 覆盖索引使用。

各位大佬有问题,欢迎交流。

原文:https://www.cnblogs.com/selfchange/p/11240818.html

### 回答1: MySQL 中可以使用 UUID 来作为表的主键。UUID 是一种全局唯一标识符,使用它作为主键可以避免因为主键重复而导致的数据冲突。MySQL 中可以使用 `uuid()` 函数来生成 UUID。例如,可以使用以下语句创建一个使用 UUID 作为主键的表: ``` CREATE TABLE my_table ( id VARCHAR(36) NOT NULL PRIMARY KEY DEFAULT uuid(), name VARCHAR(20) NOT NULL ); ``` 在插入数据,不需要指定主键的值,MySQL 会自动为主键生成一个 UUID。例如: ``` INSERT INTO my_table (name) VALUES ('Alice'); ``` 这将在 `my_table` 表中插入一行数据,其中 `id` 列的值为一个新生成的 UUID。 ### 回答2: MySQLUUID是一个全局唯一标识符,它是一个128位的字符串,通常以36个字符串表示,其中包含了32位的16进制数字和连字符。UUID可以在多个系统之间进行唯一标识和交换数据。 MySQLUUID主要有两种生成方式:第一种是使用UUID()函数生成,它是MySQL的内置函数,可以直接调用,每次调用都会生成一个新的UUID值。第二种是使用UUID_SHORT()函数生成,它是使用服务器状态和网络地址生成UUID的方法,相比UUID()函数生成的UUID长度更短,只有64位,但仍然是全局唯一的。 使用UUID作为主键有一些好处。首先,UUID可以在分布式系统中提供唯一性标识,避免了多个系统中生成相同的主键的问题。其次,UUID是随机生成的,可以避免主键的顺序递增导致的性能问题,如插入数据的磁盘碎片等。此外,UUID可以在生成就包含间信息,方便分析和排序。 然而,使用UUID也存在一些问题。首先,UUID是随机生成的,不方便人眼阅读和调试,也不易于直接使用。其次,UUID作为主键,会增加索引的大小和查询的复杂性,对性能有一定的影响。另外,由于UUID的长度较长,会占用更多的存储空间和网络带宽。 总的来说,MySQLUUID是一种全局唯一标识符,可以在分布式系统中提供唯一性标识。但在使用需要权衡好唯一性、性能和存储等因素,选择适合的主键策略。 ### 回答3: MySQL UUID是一种全局唯一标识符(Universally Unique Identifier),它是通过128位数字来表示的。在MySQL中,UUID可以作为主键或其他唯一性字段的值。它具有以下特点: 1.全球唯一:UUID是根据计算机的MAC地址、间戳和随机数等信息生成的,因此在全球范围内是唯一的。 2.长度固定:UUID的长度为32位十六进制数字,相对较短,不同于自增长的整数类型。 3.不依赖于数据库服务器:UUID是在应用程序级别生成的,不依赖于数据库服务器,因此可以在多个数据库服务器之间实现唯一性。 4.随机性:UUID的生成是基于随机数的,因此具有较高的随机性,这也保证了唯一性。 5.适用性广泛:UUID可以用于各种应用场景,如分布式系统中的数据同步、数据迁移和唯一标识等。 6.效率较低:由于UUID是一个较长的字符串,它在索引和查询需要更多的存储空间和处理间。 在使用MySQL UUID,需要注意以下几点: 1.正确生成UUID:可以使用MySQL提供的UUID()函数来生成UUID值,也可以在应用程序中使用UUID库生成。 2.选择存储类型:UUID可以使用CHAR(36)或BINARY(16)两种存储类型,具体选择取决于需求,CHAR类型可以方便人类阅读和检索,而BINARY类型效率更高。 3.索引优化:由于UUID的长度较长,为了提高查询效率,可以考虑使用前缀索引、哈希索引或直接将UUID的一部分作为索引字段。 总之,MySQL UUID是一种全球唯一标识符,具有广泛的应用场景,但在使用需要考虑存储空间和查询效率等问题。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值