mysql前缀索引 默认长度_如何确定前缀索引的长度?

mysql前缀索引 默认长度_如何确定前缀索引的长度?为什么需要前缀索引问题我们在对一张表里的某个字段或者多个字段建立索引的时候,是否遇到过这个问题。Specifiedkey’uniq_code’wastoolong;maxkeylengthis767bytes.表结构如下:createtable`t_account`(`id`BIGINT(20)UNSIGNEDNOTNULLauto_incrementCOMM…

大家好,又见面了,我是你们的朋友全栈君。

为什么需要前缀索引

问题

我们在对一张表里的某个字段或者多个字段建立索引的时候,是否遇到过这个问题。

Specified key ‘uniq_code’ was too long; max key length is 767 bytes.

表结构如下:

create table `t_account`(

`id` BIGINT(20) UNSIGNED NOT NULL auto_increment COMMENT ‘自增ID’,

`date` varchar(50) NOT NULL DEFAULT ” COMMENT ‘日期’,

`nick_name` varchar(50) NOT NULL DEFAULT ” COMMENT ‘昵称’,

`account` varchar(50) NOT NULL DEFAULT ” COMMENT ‘账号’,

`city` varchar(100) NOT NULL DEFAULT ” COMMENT ‘城市’,

PRIMARY KEY (`id`),

UNIQUE KEY `uniq_code` (`nick_name`,`account`,`city`)

) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT=’Test’;

复制代码

原因

在MySQL5.6里默认 innodb_large_prefix=0 限制单列索引长度不能超过767bytes。

在MySQL5.7里默认 innodb_large_prefix=1 解除了767bytes长度限制,但是单列索引长度最大还是不能超过3072bytes。

至于为什么是767字节,是依赖于具体的存储引擎实现的,找了官方文档,也没说为啥。 https://dev.mysql.com/doc/refman/8.0/en/create-index.html

varchar(n)占用几个字节跟字符集有关系:

字符类型若为gbk,每个字符占用2个字节,

字符类型若为utf8,每个字符最多占用3个字节,

字符类型若为utf8mb4,每个字符最多占用4个字节

复制代码

这里我设置的编码为utf8mb4编码,一个字符是占了4个字节,而我创建的索引50+50+100=200字符,总共就是800字节,所以超出了长度。

所以我们经常会见到把字段设置成varchar(255)长度的,在utf8字符集下这个是最大不超过767bytes的长度了,但是并不是一定要设置成varchar(255),还是要根据业务设置每个字段的长度,太长了也不利于我们建立联合索引。

解决办法

可以直接去改字段的长度,或者说,把索引的字段取消掉一些,但是这样改对表本身是不友好的。

通过限定字段的前n个字符为索引,可以通过衡量实际的业务中数据中的长度来取具体的值。

UNIQUE KEY `uniq_code` (`nick_name`(20),`account`(20),`city`(20))

复制代码

表示三个字段取前20字符作为唯一索引,这样的话就是长度就不会超出,这个就是我们说的前缀索引

修改单个索引的最大长度

修改索引限制长度需要在my.ini配置文件中添加以下内容,并重启:

#修改单列索引字节长度为767的限制,单列索引的长度变为3072

innodb_large_prefix=1

但是开启该参数后还需要开启表的动态存储或压缩:

系统变量innodb_file_format为Barracuda

ROW_FORMAT为DYNAMIC或COMPRESSED

复制代码

如何确定前缀索引的长度

上面我们说到可以通过前缀索引来解决索引长度超出限制的问题,但是我们改如何确定索引字段取多长的前缀才合适呢?

这里我们可以通过计算选择性来确定前缀索引的选择性,计算方法如下

全列选择性:

SELECT COUNT(DISTINCT column_name) / COUNT(*) FROM table_name;

某一长度前缀的选择性:

SELECT COUNT(DISTINCT LEFT(column_name, prefix_length)) / COUNT(*) FROM table_name;

当前缀的选择性越接近全列选择性的时候,索引效果越好。

前缀索引的优缺点

占用空间小且快

无法使用前缀索引做 ORDER BY 和 GROUP BY

无法使用前缀索引做覆盖扫描

有可能增加扫描行数

比如身份证加索引,可以加哈希索引或者倒序存储后加前缀索引。

再谈联合索引的创建

当我们不确定在一张表上建立的联合索引应该以哪个字段作为第一列时,上面的创建规则同样适用。

下面这个例子就是在建立customer_id,staff_id的联合索引时进行判断,最终选择(customer_id,staff_id)这样的组合。

# staff_id_selectivity: 0.0001

# customer_id_selectivity: 0.0373

# COUNT(*): 16049

# 通过结果发现,customer_id 的选择性更高,所以应该选择 customer_id 作为联合索引的第一列

SELECT

COUNT(DISTINCT staff_id)/COUNT(*) as staff_id_selectivity,

COUNT(DISTINCT customer_id)/COUNT(*) as customer_id_selectivity,

COUNT(*)

FROM payment

复制代码

所以说

当索引选择性越接近全列选择性的时候,索引效果越好。

也就是用此字段创建索引时,它在这个表的数据里区分度更加明显。

参考

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/143845.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • react中添加debounce 实现[通俗易懂]

    react中添加debounce 实现[通俗易懂]react中添加debounce实现handelChange(e){//输入框修改的时候执行的方法 e.persist()//react默认会清楚所有的默认属性,所以需要添加这段,保留参数的属性 debounce(()=>{ console.log(e) },500)() }<inputref={ev=>this.moneyInp…

    2022年6月20日
    73
  • 什么是SOAP ,WSDL 和UDDI[通俗易懂]

    什么是SOAP ,WSDL 和UDDI[通俗易懂]什么是WebServices一直没有一个明确的答案,这里给出的看法是:WebServices是一种基于组件的软件平台,是面向服务的Internet应用。WebServices是应用于Internet的,而不是限于局域网或试验环境。这要求提出的WebServices框架必须适用于现有的Internet软件和硬件环境,即服务的提供者所提供的服务必须具有跨平台、跨语言的特性。其次,

    2022年7月24日
    18
  • 黑盒测试的常见的测试用例设计方法有哪些[通俗易懂]

    黑盒测试的常见的测试用例设计方法有哪些[通俗易懂]测试用例怎么设计?一般根据业务知识掌握,之前已有的回归测试用例,测试知识库,测试需求开始设计。黑盒测试的常见的测试用例设计方法有哪些?1)等价类划分:等价类是指某个输入域的子集合.在该子集合中,各个输入数据对于揭露程序中的错误都是等效的.并合理地假定:测试某等价类的代表值就等于对这一类其它值的测试.因此,可以把全部输入数据合理划分为若干等价类,在每一个等价类中取一个数据作为测试的输入条件,就可以用少量代表性的测试数据.取得较好的测试结果.等价类划分可有两种不同的情况:有效等价类和无效等价类.

    2022年6月29日
    23
  • C语言程序设计50例(经典收藏)[通俗易懂]

    C语言程序设计50例(经典收藏)本篇文章是对C语言程序设计的50个小案例进行了详细的分析介绍,需要的朋友参考下【程序1】题目:有1、2、3、4个数字,能组成多少个互不相同且无重复数字的三位数?都是多少?1.程序分析:可填在百位、十位、个位的数字都是1、2、3、4。组成所有的排列后再去      掉不满足条件的排列。2.程序源代码:代码如下:#include&quot;stdio.h&quot;#i…

    2022年4月18日
    67
  • 贴片电阻丝印是什么意思「建议收藏」

    贴片电阻丝印是什么意思「建议收藏」贴片电阻上的数字是什么意思?贴片电阻是电路原理中最常见的电子器件,在一块电路板上使用量较大的将会便是电阻器和电容器了。电阻由于体型小,非常容易设备电焊焊接,能极大地提升批量生产高效率、减少错误率、控制成本,因此应用愈来愈普遍。贴片电阻表层一般都是印着丝印油墨,其丝印油墨带表了不一样的电阻值信息内容,电阻的丝印油墨怎样讲解。普遍的电热丝印一般有这几类状况:1)含有三位数据的丝印油墨;2)2)含有四位数据的丝印油墨;3)3)含有英文字母R的丝印油墨;4)4)含有数据和英文字母混和的丝印油墨。带有

    2022年8月21日
    6

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号