Mysql优化习惯|建表规约丶SQL规约丶索引规约

2023-09-20 13:06:15

        今天看到一个mysql规范,说mysql里面的字符集utf8不是真正的utf8(很感兴趣就去搜索了一下);真正的utf8字符集在mysql里面叫utf8mb4.

        感兴趣的自己可以去看下这个链接

MySQL中的 utf8 并不是真正的UTF-8编码 ! !_mysql是真正utf-8_I'm sure ok!的博客-CSDN博客


言归正传

一.建表规范

【强制】(1) 存储引擎必须使用InnoDB
  • InnoDB支持事物、行级锁、并发性能更好,CPU及内存缓存页优化使得资源利用率更高。
【强制】(2)每张表必须设置一个主键ID,且这个主键ID使用自增主键(在满足需要的情况下尽量短),除非在分库分表环境下
  • 由于InnoDB组织数据的方式决定了需要有一个主键,而且若是这个主键ID是单调递增的可以有效提高插入的性能,避免过多的页分裂、减少表碎片提高空间的使用率。 而在分库分表环境下,则需要统一来分配各个表中的主键值,从而避免整个逻辑表中主键重复。
【强制】(3)必须使用utf8mb4字符集
  • 在Mysql中的UTF-8并非“真正的UTF-8”,而utf8mb4”才是真正的“UTF-8”。
【强制】(4) 数据库表、表字段必须加入中文注释
  • 大家都别懒。
【强制】(5) 库名、表名、字段名均小写,下划线风格,不超过32个字符,必须见名知意,禁止拼音英文混用
  • 约定。
【强制】(6)单表列数目必须小于30,若超过则应该考虑将表拆分
  • 单表列数太多使得Mysql服务器处理InnoDB返回数据之间的映射成本太高。
【强制】(7)禁止使用外键,如果有外键完整性约束,需要应用程序控制
  • 外键会导致表与表之间耦合,UPDATE与DELETE操作都会涉及相关联的表,十分影响SQL的性能,甚至会造成死锁。
【强制】(8)必须把字段定义为NOT NULL并且提供默认值
  • NULL的列使索引/索引统计/值比较都更加复杂,对MySQL来说更难优化;

  • NULL这种类型Msql内部需要进行特殊处理,增加数据库处理记录的复杂性;同等条件下,表中有较多空字段的时候,数据库的处理性能会降低很多;

  • NULL值需要更多的存储空,无论是表还是索引中每行中的NULL的列都需要额外的空间来标识。

【强制】(9)禁用保留字,如DESC、RANGE、MARCH等,请参考Mysql官方保留字
【强制】(10)如果存储的字符串长度几乎相等,使用CHAR定长字符串类型。
  • 能够减少空间碎片,节省存储空间。
【建议】(11)在一些场景下,考虑使用TIMESTAMP代替DATETIME。
  • 这两种类型的都能表达"yyyy-MM-dd HH:mm:ss"格式的时间,TIMESTAMP只需要占用4个字节的长度,可以存储的范围为(1970-2038)年,在各个时区,所展示的时间是不一样的;

  • 而DATETIME类型占用8个字节,对时区不敏感,可以存储的范围为(1001-9999)年。

二.SQL规约

【建议】 (1) 为了充分利用缓存,不允许使用自定义函数、存储函数、用户变量
  • 如果查询中包含任何用户自定义函数、存储函数、用户变量、临时表、Mysql库中的系统表,其查询结果都不会被缓存。比如函数NOW()或者CURRENT_DATE()会因为不同的查询时间,返回不同的查询结果。
【强制】(2)在查询中指定所需的列,而不是直接使用“ *”返回所有的列
  • 读取不需要的列会增加CPU、IO、NET消耗。
  • 不能有效的利用覆盖索引。
【强制】(3)不允许使用属性隐式转换
  • 假设我们在手机号列上添加了索引,然后执行下面的SQL会发生什么?explain SELECT user_name FROM parent WHERE phone=13812345678; 很明显就是索引不生效,会全表扫描。
【建议】(4)在WHERE条件的属性上使用函数或者表达式
  • Mysql无法自动解析这种表达式,无法使用到索引。
【强制】(5)禁止使用外键与级联,一切外键概念必须在应用层解决
  • 外键与级联更新适用于单机低并发,不适合分布式、高并发集群;级联更新是强阻塞,存在数据库更新风暴的风险;外键影响数据库的插入速度。
【建议】(6)应尽量避免在WHERE子句中使用or作为连接条件
  • 根据情况可以选择使用UNION ALL来代替OR。
【强制】(7)不允许使用%开头的模糊查询
  • 根据索引的最左前缀原理,%开头的模糊查询无法使用索引,可以使用ES来做检索。

三.索引规约

【建议】(1)避免在更新比较频繁、区分度不高的列上单独建立索引
  • 区分度不高的列单独创建索引的优化效果很小,但是较为频繁的更新则会让索引的维护成本更高。
【强制】(2) JOIN的表不允许超过五个。需要JOIN的字段,数据类型必须绝对一致; 多表关联查询时,保证被关联的字段需要有索引
  • 太多表的JOIN会让Mysql的优化器更难权衡出一个“最佳”的执行计划(可能性为表数量的阶乘),同时要注意关联字段的类型、长度、字符编码等等是否一致。
【强制】(3)在一个联合索引中,若第一列索引区分度等于1,那么则不需要建立联合索引
  • 索引通过第一列就能够完全定位的数据,所以联合索引的后边部分是不需要的。
【强制】(4)建立联合索引时,必须将区分度更高的字段放在左边
  • 区分度更高的列放在左边,能够在一开始就有效的过滤掉无用数据。提高索引的效率,相应我们在Mapper中编写SQL的WHERE条件中有多个条件时,需要先看看当前表是否有现成的联合索引直接使用,注意各个条件的顺序尽量和索引的顺序一致。
【建议】(5)利用覆盖索引来进行查询操作,避免回表
  • 覆盖查询即是查询只需要通过索引即可拿到所需DATA,而不再需要再次回表查询,所以效率相对很高。我们在使用EXPLAIN的结果,extra列会出现:"using index"。这里也要强调一下不要使用“SELECT * ”,否则几乎不可能使用到覆盖索引。
【建议】(6)在较长VARCHAR字段,例如VARCHAR(100)上建立索引时,应指定索引长度,没必要对全字段建立索引,根据实际文本区分度决定索引长度即可
  • 索引的长度与区分度是一对矛盾体,一般对字符串类型数据,若长度为20的索引,区分度会高达90%以上,则可以考虑创建长度例为20的索引,而非全字段索引。例如可以使用SELECT COUNT(DISTINCT LEFT(lesson_code, 20)) / COUNT(*) FROM lesson;来确定lesson_code字段字符长度为20时文本区分度。
【建议】(7)如果有ORDER BY的场景,请注意利用索引的有序性。ORDER BY最后的字段是联合索引的一部分,并且放在索引组合顺序的最后,避免出现file_sort的情况,影响查询性能。
  • 假设有查询条件为WHERE a=? and b=? ORDER BY c;存在索引:a_b_c,则此时可以利用索引排序;

  • 反例:在查询条件中包含了范围查询,那么索引有序性无法利用,如:WHERE a>10 ORDER BY b; 索引a_b无法排序。

【建议】(8)在where中索引的列不能某个表达式的一部分,也不能是函数的参数
  • 即是某列上已经添加了索引,但是若此列成为表达式的一部分、或者是函数的参数,Mysql无法将此列单独解析出来,索引也不会生效。
【建议】 (9)我们在where条件中使用范围查询时,索引最多用于一个范围条件,超过一个则后边的不走索引
  • Mysql能够使用多个范围条件里边的最左边的第一个范围查询,但是后边的范围查询则无法使用。
【建议】 (10)在多个表进行外连接时,表之间的关联字段类型必须完全一致
  • 当两个表进行Join时,字段类型若没有完全一致,则加索引也不会生效,这里的完全一致包括但不限于字段类型、字段长度、字符集、collection等等。
四.其他
仅使用最有效的过滤条件,索引字段不是越多越好

 

更多推荐

常用与业务密切相关的prompt

可以在Bard、Bing、Claude2、ChatGPT和Llama2上使用定义您的业务目的和愿景。提示:“我正在[插入行业]创业。我的重点是定义与我的受众产生共鸣的明确目标和愿景。你能指导我制定有意义的愿景声明吗?”研究和分析您的目标市场。提示:“我想了解[插入行业]的目标市场。对他们的需求和行为的详细洞察将塑造我的

《确保安全:PostgreSQL安全配置与最佳实践》

🌷🍁博主猫头虎(🐅🐾)带您GotoNewWorld✨🍁🐅🐾猫头虎建议程序员必备技术栈一览表📖:🛠️全栈技术FullStack:📚MERN/MEAN/MEVNStack|🌐Jamstack|🌍GraphQL|🔁RESTfulAPI|⚡WebSockets|🔄CI/CD|🌐Git&Versio

Linux进程【1】进程概念(超详解哦)

进程概念引言(操作系统如何管理)基本概念描述与组织进程查看进程进程pid与ppidgetpid与getppid总结引言(操作系统如何管理)在冯诺依曼体系结构中,计算机由输入设备、输出设备、运算器、控制器和存储器组成。我们使用计算机的时候,实际就是数据在这些硬件中传递的过程。硬件的行为由驱动控制,驱动又由更上层的操作系统

jvm深入研究文档--jvm分区以及职责

Java虚拟机(JVM)主要包括以下几个区域:方法区(MethodArea):这个区域存储已被加载的类信息,常量,静态变量,即时编译器编译后的代码等数据。方法区是所有线程共享的。在Java8之前,方法区是永久代(PermGen),从Java8开始,永久代被元空间(Metaspace)替代。堆区(Heap):这是Java

K8S:Pod概念、分类及相关的策略

文章目录一.pod相关概念1.Pod基础概念2.Kubrenetes集群中Pod两种使用方式3.pause容器的Pod中的所有容器共享的资源4.kubernetes中的pause容器主要为每个容器提供功能:5.Kubernetes设计这样的Pod概念和特殊组成结构有什么用意6.Pod分为两类:二.Pod容器的分类1.基

[k8s] 常见yml配置和详细解释

在Kubernetes(K8s)中,常见的YAML文件配置包括:文章目录PodDeploymentServiceClusterIPNodePortLoadBalancerIngressConfigMapSecretVolume访问模式StatefulSetDaemonSetJob容器的重启策略ConJobPodapiV

基于Java的高校科研信息管理系统设计与实现(亮点:完整严谨的科研项目审批流程、多文件上传、多角色)

高校科研信息管理系统一、前言二、我的优势2.1自己的网站2.2自己的小程序(小蔡coding)2.3有保障的售后2.4福利三、开发环境与技术3.1MySQL数据库3.2Vue前端技术3.3SpringBoot框架3.4微信小程序四、功能设计4.1主要功能描述五、系统实现5.1系统主要功能展示5.1.1三个角色展示5.1

详谈操作系统中的内核态和用户态

不知道大家有没有思考过这样一个问题:什么是处理器(CPU)的状态?🤔其实CPU和人一样,没有执行程序的时候,是没有什么状态的,当它执行的程序是用户程序的时候就叫用户态,当执行的程序是操作系统的代码时就叫系统态或者内核态.接下来,我们就来谈谈内核态和用户态.目录1.内核态和用户态的概念2.内核态和用户态的区别3.特权指

《银河麒麟高级服务器操作系统V10》使用

一言而论:讲了麒麟服务器V10的基本使用,包括终端、VNC文章目录前言基本架构环境硬件环境软件环境麒麟安装步骤1.在宿主机上安装好VM,并且激活2.使用VM创建虚拟机3.启动虚拟机终端常用点VNC的使用麒麟上安装VNC服务器Windows上安装VNC客户端VNC服务器补充事项总结一些吐槽(坑)参考资料前言公司接到项目,

【AI】推理系统和推理引擎的整体架构

本文主要是对B站Up主ZOMI酱推理系统系列视频的理解,可以认为是重点笔记。一、深度学习模型的全生命周期相信很多人和我一样,刚看到深度学习模型中的推理系统或推理引擎时是一头雾水,因为学习DL时通常关注于模型的设计和训练。下图是深度学习模型的全生命周期图,主要分为两大类任务,训练任务和推理任务。训练任务:通常需要执行数小

理解 React 服务器组件

自从React被引入开发社区以来的十年里,它经历了几次演变。React团队在发生根本性变革时并不害羞:如果他们发现了一个更好的问题解决方案,他们就会带着它运行。几个月前,React团队推出了ReactServerComponents,这是最新的范式转变。有史以来第一次,React组件可以只在服务器上运行。网上对此有太多

热文推荐