热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

innodb索引设计小结

一关于t1表和testtb的索引设计二把主键放到二级索引的后面,会否占据更多的物理空间?三InnoDB的主键该如何选择,业务ID和自增

一关于t1表和testtb的索引设计


二把主键放到二级索引的后面,会否占据更多的物理空间?

三 InnoDB的主键该如何选择,业务ID和自增ID做主键有何区别?

 

看到了@淘宝丁奇的《关于InnoDB的索引大小》和@plinux 的《InnoDB一定会在索引中加上主键吗》之前在阿里DBA内部分享过一个InnoDB表该如何建主键索引的PPT,借这个机会再整理和思考一次。

 

一关于t1表和testtb的索引设计


1.  CREATE TABLE `t1` (  

2.    `id` int(11) NOT NULL AUTO_INCREMENT,  

3.    `a` int(11) DEFAULT NULL,  

4.    `b` int(11) DEFAULT NULL,  

5.    `c` int(11) DEFAULT NULL,  

6.    PRIMARY KEY (`id`),  

7.    KEY `i2` (`a`,`id`)  

8.  ) ENGINE=InnoDB DEFAULT CHARSET=utf8;    

9.  CREATE TABLE `testtb` (  

10.   `id` int(11) NOT NULL AUTO_INCREMENT,  

11.   `a` int(11) DEFAULT NULL,  

12.   `b` int(11) DEFAULT NULL,  

13.   `c` int(11) DEFAULT NULL,  

14.   PRIMARY KEY (`id`),  

15.   KEY `i3` (`id`,`a`)  

16. ) ENGINE=InnoDB DEFAULT CHARSET=utf8;  

t1表和testtb表的差别只在于索引i2 和i3的索引字段,

前者和后者的区别是更新记录的时候,t1表由于a字段是随机的,而id的顺序自增的.

i2的分裂成本要比i3的成本高,在高并发更新的情况下,testtb表的性能会比t1表的高。

 

索引

插入性能对比

实际业务场景对比

KEY `i2` (`a`,`id`)

a字段是随机写入,i2索引的b-tree分裂成本相对i3的顺序写入要高

对于select b,c from table where a=10;的查询,可以直接用到i2索引

KEY `i3` (`id`,`a`)

id是顺序自增,在a字段插入数据的时候,b-tree的分裂成本相对i2要低

对于select b,c where a=10;的查询,用不到i2索引

 

实际业务场景对比,可能会有同学说,那select b,c where id=? and a=?将会怎么运行呢?答案是查询优化器会直接选择主键索引,我们可以看一个简单的例子.

 

 

 

结论:

1.       在大部分的业务场景下,业务的sql一般是只用到where a=?来进行查询,如果是组合条件,比如where id=? and a=?这种情况,而没有where a=?的查询条件,我一般直接就让sql走主键索引,而不会再额外建一个(id,a)的索引。

2.       如果业务的sql是只有where a=?的查询条件,建了(id,a)是会让SQL用不到这个索引的,只能单独建一个(a)索引。

 

二把主键放到二级索引的后面?

彭爷的博文的最后,提到这个语句SELECT * FROM t WHERE d=x1 AND b=x2 ORDER BY a;以及建议所有的DBA建索引的时候,都在业务要求的索引字段后面补上主键字段

 

建了两张字段结构一样,记录一样,二级索引不一样的两个表

CREATE TABLE `test1` (

 `id` int(11) NOT NULL AUTO_INCREMENT,

  `a`int(11) DEFAULT NULL,

  `b`int(11) DEFAULT NULL,

  `c`int(11) DEFAULT NULL,

 PRIMARY KEY (`id`),

 KEY `i4` (`a`,`id`)

) ENGINE=InnoDB AUTO_INCREMENT=56908DEFAULT CHARSET=utf8;

 

CREATE TABLE `test2` (

 `id` int(11) NOT NULL AUTO_INCREMENT,

  `a`int(11) DEFAULT NULL,

  `b`int(11) DEFAULT NULL,

  `c`int(11) DEFAULT NULL,

 PRIMARY KEY (`id`),

 KEY `i4_no_id` (`a`)

) ENGINE=InnoDB AUTO_INCREMENT=56908DEFAULT CHARSET=utf8

 

观察test1和test2的物理空间大小

12KB         test1.frm

13332KB  test1.ibd

12KB         test2.frm

13332KB  test2.ibd

物理空间不会因为把id放在二级索引的后面而变大,那以后建表的时候,可以考虑直接把ID加进到二级索引的后面

 

三 InnoDB的主键该如何选择,业务ID和自增ID做主键有何区别?

这个topic,我把9.23即将在北京阿里技术嘉年华IData论坛要分享的内容直接贴上来

 

a表

b表

CREATE TABLE `a` (

`id` bigint(20) NOT NULL AUTO_INCREMENT,

`message_id` int(11) NOT NULL,

`user_id` int(11) NOT NULL,

`msg` varchar(1024) DEFAULT NULL,

`gmt_create` datetime NOT NULL,

PRIMARY KEY (`id`),

KEY `user_id` (`user_id`,`message_id`),

KEY `idx_gmt_create` (`gmt_create`)

) ENGINE=InnoDB DEFAULT CHARSET=gbk;

 

CREATE TABLE `b` (

  `user_id` int(11) NOT NULL,

  `message_id` int(11) NOT NULL,

  `msg` varchar(1024) DEFAULT NULL,

  `gmt_create` datetime NOT NULL,

 PRIMARY KEY (`user_id`,`message_id`),

KEY `idx_gmt_create` (`gmt_create`)

) ENGINE=InnoDB DEFAULT CHARSET=gbk;

 

 

 

物理空间

优点

缺点

适用场景

a表(500万记录)

509M

主键ID自增,在写入数据的时候,Btree分裂成本低,写性能高

1.       物理空间相对较多

如果根据user_id来查记录,需要走两次IO

写操作较多的场景

b表(500万记录)

361M

1.物理空间相对减少

2.根据user_id查数据,直接走主键拿到数据,无需回表

(user_id,message_id)为随机写入,Btree分裂成本高,写性能低

写少读多的场景,例如从hadoop回流到MySQL的统计结果表,这种统计结果一般数据较多,但主要是读

 

 

如何用一张图表示主键索引和二级索引的关系?请见下图


 


推荐阅读
  • MySQL锁机制详解
    本文深入探讨了MySQL中的锁机制,包括表级锁、行级锁以及元数据锁,通过实例详细解释了各种锁的工作原理及其应用场景。同时,文章还介绍了如何通过锁来优化数据库性能,避免常见的并发问题。 ... [详细]
  • 本文介绍如何通过SQL查询来统计不同职位类型的员工当前薪资的平均值,并将结果按照平均薪资升序排列。 ... [详细]
  • 交互式左右滑动导航菜单设计
    本文介绍了一种使用HTML和JavaScript实现的左右可点击滑动导航菜单的方法,适用于需要展示多个链接或项目的网页布局。 ... [详细]
  • python开发mysql:单表查询&多表查询
    一单表查询,以下是表内容二多表查询,一下是表内容三总结&表创建过程单 ... [详细]
  • 本文介绍了一种根据目标检测结果,从原始XML文件中提取并分析特定类别的方法。通过解析XML文件,筛选出特定类别的图像和标注信息,并保存到新的文件夹中,以便进一步分析和处理。 ... [详细]
  • 本文探讨了如何使用pg-promise库在PostgreSQL中高效地批量插入多条记录,包括通过事务和单一查询两种方法。 ... [详细]
  • ML学习笔记20210824分类算法模型选择与调优
    3.模型选择和调优3.1交叉验证定义目的为了让模型得精度更加可信3.2超参数搜索GridSearch对K值进行选择。k[1,2,3,4,5,6]循环遍历搜索。API参数1& ... [详细]
  • Python数据类型6 字典
    字典Python的字典数据类型是基于hash散列算法实现的,采用键值对(key:value)的形式,根据key的值计算value的地址,具有非常快的查取和插入速度。但它是无序的,包 ... [详细]
  • JavaScript:简洁与复杂之间的平衡
    本文探讨了在编写JavaScript教程时,如何在保持内容简洁的同时,确保初学者能够理解并应用实际开发中的复杂问题。文章通过具体示例分析了不同层次的JavaScript代码实现。 ... [详细]
  • 本文深入探讨了JavaScript中实现继承的四种常见方法,包括原型链继承、构造函数继承、组合继承和寄生组合继承。对于正在学习或从事Web前端开发的技术人员来说,理解这些继承模式对于提高代码质量和维护性至关重要。 ... [详细]
  • 深入解析Android中的SQLite数据库使用
    本文详细介绍了如何在Android应用中使用SQLite数据库进行数据存储。通过自定义类继承SQLiteOpenHelper,实现数据库的创建与版本管理,并提供了具体的学生信息管理示例代码。 ... [详细]
  • 本文探讨如何利用Java反射技术来模拟Webwork框架中的URL解析过程。通过这一实践,读者可以更好地理解Webwork及其后续版本Struts2的工作原理,尤其是它们在MVC架构下的角色。 ... [详细]
  • 本文探讨了一个特定于 Spring 4.2.5 的问题,即在应用上下文刷新事件(ContextRefreshedEvent)触发时,带有 @Transactional 注解的 Bean 未能正确代理事务。该问题在 Spring 4.1.9 版本中正常运行,但在升级至 4.2.5 后出现异常。 ... [详细]
  • LeetCode 347. 高频元素前 K 名
    本题旨在从给定数组中找出出现频率最高的前 K 个元素。难度等级为中等,使用优先队列(大顶堆)作为主要数据结构进行求解。 ... [详细]
  • Java实现文本到图片转换,支持自动换行、字体自定义及图像优化
    本文详细介绍了如何使用Java实现将文本转换为图片的功能,包括自动换行、自定义字体加载、抗锯齿优化以及图片压缩等技术细节。 ... [详细]
author-avatar
徐天凝_669
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有