mysql索引字段设计

news2024/12/24 2:49:41

表字段数量与row大小限制可以参考官方文档
https://dev.mysql.com/doc/refman/8.0/en/column-count-limit.html#column-count-limits

复合索引

参考:https://dev.mysql.com/doc/refman/8.0/en/innodb-limits.html

数量限制

一个复合索引最多可以包含16个列:https://dev.mysql.com/doc/refman/8.0/en/multiple-column-indexes.html
官方对组合索引给出了一个比较好的可行方案:可以引入基于来自其他列的信息进行“散列”的列,方法如下:

SELECT * FROM tbl_name
  WHERE hash_col=MD5(CONCAT(val1,val2))
  AND col1=val1 AND col2=val2;

大小限制

innodb索引大小限制

  • 对于使用DYNAMIC(5.7.9开始默认为该格式)或COMPRESSED行格式的InnoDB表,索引key前缀长度限制为3072字节。
  • 对于使用REDUNDANT或COMPACT行格式的InnoDB表,索引key前缀长度限制为767字节。例如,在TEXT或VARCHAR类型字段上列前缀索引超过191字符,可能会达到这个限制,假设一个utf8mb4字符集,每个字符最多4个字节。
  • 试图使用超过限制的索引键前缀长度将返回错误。
  • 如果你在创建mysql实例时通过innodb_page_size参数配置,减小InnoDB的page页大小至8KB或4KB,索引的最大长度也会基于16KB页大小3072字节的限制,按比例降低。也就是说,当页大小是8KB时最大索引键长度是1536字节,页大小是4KB时最大长度为768字节。该限制适用在索引键前缀,也同样适用在full-column索引键

为什么是3072?
16KB page size

  1. BTree结构叶子结点至少两个Node(不然就退化成列表了),16/2=8KB
  2. 二级索引一定包含一个主键索引key,8/2=4KB

预留空间后<4KB,取整=3*1024=3072

row format

mysql> SHOW TABLE STATUS FROM test LIKE 't%' \G;
*************************** 1. row ***************************
           Name: t1
         Engine: InnoDB
        Version: 10
     Row_format: Dynamic
           Rows: 0
 Avg_row_length: 0
    Data_length: 16384
Max_data_length: 0
   Index_length: 0
      Data_free: 0
 Auto_increment: NULL
    Create_time: 2021-02-18 12:18:28
    Update_time: NULL
     Check_time: NULL
      Collation: utf8mb4_0900_ai_ci
       Checksum: NULL
 Create_options: 
        Comment:

计算索引长度

  1. 非NOT NULL字段:占用1个字节。
  2. 定长字段:tinyint占1个字节、int占4个字节、bitint占8个字节、date占3个字节、datetime占5个字节,char(n)占n个字符。
  3. 变长字段:varchar(n)占n个字符+2个字节。

其他类型大家可以通过本地创建测试表测试索引验证字段类型占用字节数
常见字符集一个字符占用字节数

  1. latin1编码:每个字符占用一个字节
  2. gbk/gb2312编码:每个字符占用两个字节
  3. utf8编码:每个字符占用三个字节
  4. utf8mb4编码:每个字符占用四个字节

案例

CREATE TABLE `test` (
  `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT 'Primary key',
  `msg_id` varchar(64) NOT NULL COMMENT 'msg unique id',
  `send_to_id` varchar(128) DEFAULT '' COMMENT 'to user',
  `error_code` varchar(64) DEFAULT '' COMMENT 'errorCode',
  `db_create_time` datetime(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT 'Create time',
  PRIMARY KEY (`id`),
  KEY `idx_send_to_id` (`send_to_id`,`error_code`,`msg_id`,`db_create_time`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

查看执行计划

desc select msg_id,error_code 
from test 
where send_to_id='1' 
and error_code in ('a') 
and msg_id='1' 
and db_create_time='2022-12-12'

截屏2022-12-15 14.48.37.png

  1. varchar3个字段共占用(64+64+128)4=1024+(23)=1030
  2. datetime(3)占用5+2=7
  3. 两个非NOT NULL字段1+1=2

索引占用1030+7+2=1039字节

索引设计

群发消息场景

  1. 一个批次消息推送对应600W+用户的消息触达
  2. 异步推送时消息失败需要重试,重试需要幂等处理
  3. 产品需要查看一个批次消息的推送的详情,因此分库规则使用了msgId(群发消息的批次概念)

幂等规则:msg_id+send_to

伪代码:select msg_id,error_code from table where msg_id=‘a’ and send_to=‘1’。
为什么需要error_code,因为有些类型的失败消息不允许重试,比如:用户已注销账户或者用户已退订等类型

群发消息场景下,600W+条消息都是同一个批次,也就是msg_id相同,send_to均不相同,error_code(大部分消息发送成功,errorCode为空字符)

索引覆盖

不需要二次回表,直接索引覆盖索引,字段顺序选择如下:

  1. idx_send_to(msg_id,send_to,error_code)
  2. idx_send_to(error_code,send_to,msg_id)
  3. idx_send_to(send_to,error_code,msg_id)
  4. idx_send_to(send_to,msg_id,error_code)

假设:表中每个字段的distinct值,send_to=600W,error_code=20,msg_id=50W。表总数据量为:600W2050W=600000W

选择性
选择性=不重复的索引值数量/表记录总数量
msgId选择性:50W/600000W=0.000083
send_to选择性:600W/600000W=0.001
error_code选择性:20/600000W=0.0000000033
理想情况下索引性能由高到低依次为:索引4-》索引3-〉索引2-》索引1
但是如果send_to与msg_id:1对1或者1对二,二send_to与error_code:1对20,那么索引3就是最佳选择,例如下面的案例,mysql自动选择走索引3,而不是索引4
截屏2022-12-15 23.00.42.png

截屏2022-12-15 23.02.21.png

截屏2022-12-15 23.03.30.png

总结

基于索引选择性创建联合索引,字段设计可以根据实际业务场景来评估
例如:字段1(基数=10W),字段2(基数=10W),字段3(基数=20)
虽然字段1,2独立的选择性更高,但是如果字段1与字段2基本1:1,而字段1与字段3基本1:5。那么字段1+字段3无疑是更佳的选择

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/164913.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

微信小程序--自定义组件

组件的创建与引用 1.创建组件 在项目的根目录中&#xff0c;鼠标右键&#xff0c;创建 components -> test 文件夹 在新建的components -> test文件夹上&#xff0c;鼠标右键&#xff0c;点击“新建Component" 键入组件的名称之后回车&#xff0c;会自动生成组件对…

C语言进阶(9)——C语言文件操作

本章重点 为什么使用文件什么是文件文件的打开和关闭文件的顺序读写文件的随机读写文本文件和二进制文件文件读取结束的判定文件缓冲区 文章目录本章重点1.为什么使用文件2.什么是文件2.1程序文件2.2数据文件2.3文件名3.文件打开和关闭3.1 文件指针3.2文件的打开和关闭4. 文件…

【蓝桥杯嵌入式】第十一届蓝桥杯嵌入式省赛(第二场)程序设计试题及其题解

题目再现 题目分析 通过阅读本届试题可知&#xff0c;其功能比较单一&#xff0c;除了试题中常客——LED、LCD、按键三巨头外&#xff0c;还包含了定时器的PWM以及ADC读取这两个部分&#xff0c;考察的重点在于对定时器产生PWM的应用以及如何修改PWM的占空比&#xff0c;完全消…

MPU-6000(6050)介绍

MPU-6000&#xff08;6050&#xff09;简介MPU-60X0是全球首例9 轴运动处理传感器。它集成了3 轴MEMS陀螺仪&#xff0c;3 轴MEMS加速度计&#xff0c;以及一个可扩展的数字运动处理器DMP&#xff08;DigitalMotion Processor&#xff09;&#xff0c;可用I2C接口连接一个数字传…

react PureComponent

这个 其实和我之前写的文章react组件优化&#xff0c;当父组件数据变化与子组件无关时&#xff0c;控制子组件不重新渲染实现的东西是一样的 只是用了一种更简洁的方式 我们还是重新来一次 创建一个react项目 然后 创建一个子组件 我这里就直接叫 subset.jsx 参考代码如下 i…

ADAM: A METHOD FOR STOCHASTIC OPTIMIZATION

核心 Adam: 一种基低阶矩的自适应估计的随机目标函数的一阶梯度优化算法&#xff0c;该方法实现简单**&#xff0c;计算效率高&#xff0c;内存需求很少**&#xff0c;对梯度的对角线重新缩放不变&#xff0c;并且非常适合于在数据或参数方面较大问题&#xff0c;该方法也适用…

ADI demo PS工程的编译-以adrv9371x_zc706为例子

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 ADI demo PS工程的编译-以adrv9371x_zc706为例子前言VITIS建工程总结前言 接《ADI demo PL工程的编译-以adrv9371x_zc706为例子之使用Cygwin》这篇。导出XSA文件&#xff0c…

VMware虚拟机搭建安装MacOS13及开发环境搭建

文章目录前言准备工作&#xff1a;安装虚拟机及MacOS系统1.安装VMware 虚拟机2. 运行解锁工具3. 安装macOS 134. 配置网络5. 安装VMware tools开发环境1. 安装xcode2. 安装HbuilderX前言 终于把macOS13虚拟机安装好了&#xff0c;比起上次安装macOS10,这次走了很多弯路。 先说…

108. 将有序数组转换为二叉搜索树

108. 将有序数组转换为二叉搜索树 难度简单1214 给你一个整数数组 nums &#xff0c;其中元素已经按 升序 排列&#xff0c;请你将其转换为一棵 高度平衡 二叉搜索树。 高度平衡 二叉树是一棵满足「每个节点的左右两个子树的高度差的绝对值不超过 1 」的二叉树。 示例 1&…

春节期间商城如何做好运营

有经验的商家都知道&#xff0c;春节对于店铺来说&#xff0c;这是一个全新的起点&#xff0c;所以商家们一定要抓住新年这个过渡期的时机。那么在春节期间的运营该如何做呢&#xff1f; 首先看看春节期间会有的几个问题&#xff1a; 推广竞争会比较小&#xff0c;在这个时间…

git使用日常问题记录【按日期频繁记录,欢迎收藏】

git系列文章 文章目录2023.1.14 将gitee仓库转移到github遇到的问题1-1 add到暂存区&#xff0c;commit到仓库之后&#xff0c;不想push了&#xff1f;&#xff1f;&#xff1f;1-2 git push大文件失败解决1-3 上传多余文件&#xff0c;如何从远端仓库中删除2023.1.151-1 githu…

销售管理系统 | 数据库课设

文章目录前言项目介绍E-R图表结构系统总体框架搭建项目环境介绍创建网站主页连接数据库注册功能登录功能管理员登录功能注销登录功能个人信息后台管理查看供应商名单删除功能修改功能登记货物信息功能购买商品功能总源码教训总结前言 为了期末的数据库课设&#xff0c;这是最初…

【C++】STL - Stack - Queue - PriorityQueue使用和模拟实现

&#x1f431;作者&#xff1a;傻响 &#x1f431;专栏&#xff1a;《数据结构_STL》 &#x1f525;格言&#xff1a;你只管努力&#xff0c;剩下的交给时间&#xff01; 目录 栈 Stack介绍 模拟实现 队列 Queue介绍 常用的函数接口介绍 模拟实现 优先级队列 Priority…

【docker18】docker容器之CAdvisor+InfluxDB+Granfana

1.原生命令 1.1操作 命令&#xff1a; docke stats 1.2问题 通过docker stats命令可以很方便的看到当前宿主机上所有容器的CPU&#xff0c;内存以及网络流量控制等数据&#xff0c;一般的小公司够用了。 但是&#xff0c;docker stats统计结果只能是当前宿主机的全部容器&am…

669. 修剪二叉搜索树

669. 修剪二叉搜索树 难度中等 给你二叉搜索树的根节点 root &#xff0c;同时给定最小边界low 和最大边界 high。通过修剪二叉搜索树&#xff0c;使得所有节点的值在[low, high]中。修剪树 不应该 改变保留在树中的元素的相对结构 (即&#xff0c;如果没有被移除&#xff0c…

SourceTree使用方法总结

SourceTree使用方法总结 SourceTree使用总结 添加仓库 mac下从url克隆&#xff1a; windows下从url克隆&#xff1a; 抓取、获取分支信息 抓取&#xff08;mac下的名字&#xff09;获取&#xff08;Windows下的名字&#xff09;指获取服务端git库的变更信息&#xff0c;比如…

基于FPGA的UDP 通信(五)

引言 前文链接&#xff1a; 基于FPGA的UDP 通信&#xff08;一&#xff09; 基于FPGA的UDP 通信&#xff08;二&#xff09; 基于FPGA的UDP 通信&#xff08;三&#xff09; 基于FPGA的UDP 通信&#xff08;四&#xff09; 本文基于FPGA设计千兆以太网通信模块UDP数据发…

12.I/O复用

I/O复用 多进程方式跳过 基于I/O复用的服务器端 接下来讨论并发服务器实现方法的延伸。如果有读者已经跳过第10章和第11章&#xff0c;那就只需把本章内容当做并发服务器实现的第一种方法即可。将要讨论的内容中包含一部分与多进程服务器端的比较&#xff0c;跳过第10章和第…

Android WebView中H5调用Android原生方法

最近做项目&#xff0c;使用webView看一些网页&#xff0c;和网页开发一起找什么方法进行交互&#xff0c;还好解决&#xff0c;分享一下经验。 对于webView的使用就不写了&#xff0c;百度大法好&#xff0c;主要是交互方面&#xff0c;对WebView增加以下代码&#xff1a; bi…

五个了解自己天赋优势的分析工具(一)霍兰德兴趣测试

霍兰德兴趣测试 霍兰德职业兴趣自测&#xff08;Self-Directed Search&#xff09;是由美国职业指导专家霍兰德&#xff08;John Holland&#xff09;根据他本人大量的职业咨询经验及其职业类型理论编制的测评工具。 霍兰德认为&#xff0c;个人职业兴趣特性与职业之间应有一…