为什么需要前缀索引

问题

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

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

复制代码

所以说

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

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

参考

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

  1. mysql+5.6+左连接_第5章 索引与算法

    5.1 InnoDB存储引擎索引概述 InnoDB常见支持:B+树索引.全文索引.哈希索引. B+树索引并不能找到一个给定键值的具体行,只能找到被查的数据所在的页.然后数据库通过把页读入到内存,再在内 ...

  2. sql索引调优_使用内置索引利用率指标SQL Server索引性能调优

    sql索引调优 描述 (Description) Indexing is key to efficient query execution. Knowing what indexes are unne ...

  3. android 分割字符 指定长度_[Android]TextUtils.ellipsize()截取指定长度字符串(附图文混排)...

    参考:http://zilla.blog.51cto.com/3095640/984775 效果图: 实现代码:// 监听布局变化,直接获取显示的长度 txtDescription.getViewTr ...

  4. mysql怎么添加默认约束_分享知识-快乐自己:MySQL中的约束,添加约束,删除约束,以及一些其他修饰...

    创建数据库: CREATE DATABASES 数据库名: 选择数据库: USE 数据库名: 删除数据库: DROP DATAVBASE 数据库名: 创建表: CREATE TABLE IF NOT ...

  5. mysql主从同步默认延迟_减少mysql主从数据同步延迟问题的详解

    基于局域网的master/slave机制在通常情况下已经可以满足'实时'备份的要求了.如果延迟比较大,就先确认以下几个因素: 1. 网络延迟 2. master负载 3. slave负载 一般的做法是 ...

  6. mysql不显示默认密码_免安装版mysql不出现默认密码状况(基于mysql8.0)

    可以使用免密码安装命令 mysqld --initialize-insecure(建议使用这个命令) mysqld install net start mysql 然后启动了 进入mysql: mys ...

  7. mysql实验索引和视图_数据库实验报告 索引和视图

    数据库实验报告 索引和视图 (9页) 本资源提供全文预览,点击全文预览即可全文预览,如果喜欢文档就下载吧,查找使用更方便哦! 19.90 积分 1西北师范大学计算机科学与工程学院学生实验报告西北师范大 ...

  8. python字符串长度_如何使用python获取字符串长度?哪些方法?

    掌握多种python技巧,对于我们更好的灵活应用python是非常重要的,比如接下来给大家介绍的获取字节长度,那大家脑海里就该有印象了,有几种方法呢?一起来看下吧~ 1.使用len()函数 这是最直接 ...

  9. python中对比数组长度_在Python中检索数组长度的首选方法

    python中对比数组长度 The __len__() is a method on container types. However, python also provides another op ...

最新文章

  1. Python 判断类型
  2. python round()四舍五入有偏差 注意了解
  3. Python使用xlrd和xlwt读取和写入excel详细教程
  4. 计算机知识幼儿园,幼儿园中班计算机教学工作计划
  5. 改变Window下的习惯--认识Linux
  6. 前端之JQuery(一)
  7. 【Linux】一步一步学Linux——mkdir命令(21)
  8. el 中requestScope和param
  9. 软件定义数据中心—Windows Server SDDC技术与实践
  10. 选择Bootstrap的理由
  11. response.contenttype
  12. The 'manifest_version' key must be present and set to 2 (without quotes)
  13. 我的知识管理工具列表
  14. excel比较两列数据,相同?包含?
  15. pdf数据脱敏 如何恢复_如何恢复Word文档丢失的数据?
  16. 散落在香山的红绳情结
  17. Windows 工作/生活 小窍门收集
  18. 棣拓DTAS公差分析软件-蒙特卡洛法公差分析软件-容差分析软件
  19. matlab 根轨迹 系统单位阶跃响应,二阶系统单位阶跃响应MATLAB仿真设计.doc
  20. 盈利“晴空”下,唯品会拨不开的“乌云”

热门文章

  1. 用户手机微信扫一扫就能进入公众号
  2. 聊聊Hive数据血缘——从Atlas没有列级血缘的Bug讲起
  3. python相关岗位面试题总结(五)(持续更新)
  4. c语言的编写程序--最简单的算术题
  5. oracle多维度查询数据
  6. 孤单还是对你最好的惩罚
  7. 应用在生物医学领域中的NLP预训练语言模型(PubMedBERT)
  8. linux键盘符号错乱,Ubuntu14.04 键盘错位小问题
  9. test api mis
  10. 服务器ip导致微信域名红,微信/QQ域名检测-最新腾讯域名检测官方接口