IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 大数据 -> MySQL的执行计划key_len -> 正文阅读

[大数据]MySQL的执行计划key_len

key_len的含义

参考mysql 8.0官方文档的解释:https://dev.mysql.com/doc/refman/8.0/en/explain-output.html

key_len是explain输出字段中的一列。

含义是:The length of the chosen key,所选键的长度。其单位是字节。

key_len的作用

根据这个值,就可以判断索引使用情况。比如当key_len列显示为NULL时,key列也就会显示为NULL, 说明语句没有用到索引。比如在使用组合索引的时候,判断是否所有的索引字段是否都被用到。

如何根据key_len的值判断是否所有的索引字段都被用到,就要知道key_len的计算规则。

key_len 计算规则

1.可以为NULL的列的key长度比非NULL列的key长度大1。

?

Due to the key storage format, the key length is one greater for a column that can be NULL than for a NOT NULL column.

看个例子,有一张表a_test,其表结构如所示:

CREATE?TABLE?`a_test`?(
??`id`?int(4)?unsigned?NOT?NULL?AUTO_INCREMENT,
??`server_id`?int(4)?NOT?NULL?DEFAULT?<span style="color:#98c379">'0'</span>,
??`user_id`?int(4)?DEFAULT?NULL,
??PRIMARY?KEY?(`id`),
??KEY?`idx_server_id`?(`server_id`),
??KEY?`idx_user_id`?(`user_id`)
)?ENGINE=InnoDB?DEFAULT?CHARSET=latin1

可以看到表a_test,有两个普通索引idx_server_id和idx_user_id。server_id的字段类型是int,有not null约束。user_id的字段类型是int,没有not null约束,默认值是null。

我们来看下分别使用这两个索引时,key_len的值。

mysql>?explain?select?*?from?a_test?<span style="color:#e6c07b">where</span>?server_id=1;
+----+-------------+--------+------+---------------+---------------+---------+-------+------+-------+
|?id?|?select_type?|?table??|?<span style="color:#e6c07b">type</span>?|?possible_keys?|?key???????????|?key_len?|?ref???|?rows?|?Extra?|
+----+-------------+--------+------+---------------+---------------+---------+-------+------+-------+
|??1?|?SIMPLE??????|?a_test?|?ref??|?idx_server_id?|?idx_server_id?|?4???????|?const?|????1?|?NULL??|
+----+-------------+--------+------+---------------+---------------+---------+-------+------+-------+
1?row?<span style="color:#c678dd">in</span>?<span style="color:#e6c07b">set</span>?(0.02?sec)

mysql>?explain?select?*?from?a_test?<span style="color:#e6c07b">where</span>?user_id=1;
+----+-------------+--------+------+---------------+-------------+---------+-------+------+-------+
|?id?|?select_type?|?table??|?<span style="color:#e6c07b">type</span>?|?possible_keys?|?key?????????|?key_len?|?ref???|?rows?|?Extra?|
+----+-------------+--------+------+---------------+-------------+---------+-------+------+-------+
|??1?|?SIMPLE??????|?a_test?|?ref??|?idx_user_id???|?idx_user_id?|?5???????|?const?|????1?|?NULL??|
+----+-------------+--------+------+---------------+-------------+---------+-------+------+-------+
1?row?

如上所示,当使用idx_user_id索引时,key_len的值是5(int类型长度4+1),而使用idx_server_id索引时,key_len的值是4(仅为int类型长度4)。

2.如果索引列是字符型字段,则索引列数据类型本身占用空间跟字符集有关。

不同的字符集下,同一个字符存储到表中的时候,它所占用的空间大小是不同的。一个字符存储在表中,到底占用多少个字节byte,需要根据不同的字符集来分别计算。

常用的几种字符集下,字符character和字节byte的换算关系如下:

字符集1个字符占用字节数(Maxlen)
GBK2
UTF83
UTF8mb44
latin11

注:latin1字符集编码下,不支持插入中文字符。

所以CHAR(M)类型占用空间为M * Maxlen?

验证一下:

3. 如果索引列是变长的(比如varchar),则在索引列数据类型本身占用空间的基础上再加2。

我们把上面的char类型替换成varchar。

看个组合索引的例子

我有一张表kill_log。

`timestamp`?datetime?DEFAULT?NULL,
`db`?varchar(64)?DEFAULT?NULL,
...
KEY?`idx_timestamp_db`?(`timestamp`,`db`)
)?ENGINE=InnoDB?AUTO_INCREMENT=77559?DEFAULT?CHARSET=utf8mb4

查看如下语句的执行计划。

SELECT
*
FROM
??`kill_log`
??FORCE?INDEX(`idx_timestamp_db`)
WHERE
??1?=?1
??and?timestamp?>'2022-05-06T16:22:39.206273Z' and?timestamp?<?'2022-05-07T15:22:39.206323Z'
and?db?=?'db_common'

其输出的执行计划如下:

key_len为265。

我们来分析下这个265怎么算出来的吧。

  1. key_len = len(idx_timestamp_db) = len(timestamp) + len(db)

  2. len(timestamp) = timestamp占用字节5 + null值1 = 6

  3. len(db) = varchar(64)*utf8mb4 maxlen 4 + 变2 + null值1 = 259

  4. 259 + 6 = 365

把查询语句db的条件去掉。

SELECT
*
FROM
??`kill_log`
??FORCE?INDEX(`idx_timestamp_db`)
WHERE
??1?=?1
??and?timestamp?>'2022-05-06T16:22:39.206273Z'?and?timestamp?< '2022-05-07T15:22:39.206323Z'

再看下执行计划。

此时查询只用到了组合索引中的第一个字段timestamp,长度为6。

参考文档:

https://blog.csdn.net/javaanddonet/article/details/111992505

https://www.modb.pro/db/52861

关注我,和我一起拯救吧!

?

?

  大数据 最新文章
实现Kafka至少消费一次
亚马逊云科技:还在苦于ETL?Zero ETL的时代
初探MapReduce
【SpringBoot框架篇】32.基于注解+redis实现
Elasticsearch:如何减少 Elasticsearch 集
Go redis操作
Redis面试题
专题五 Redis高并发场景
基于GBase8s和Calcite的多数据源查询
Redis——底层数据结构原理
上一篇文章      下一篇文章      查看所有文章
加:2022-05-15 11:37:30  更:2022-05-15 11:38:25 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2025年1日历 -2025/1/16 6:50:01-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码