datetime建立索引有用吗_超全的数据库建表、SQL、索引规范

背景

因为工作岗位的原因,负责制定了关于后端组数据库的规约规范,作为所有产品线的规范,历经几版的修改,最终形成下边的文本,规范在整个后端执行也有大半年的时间,对于整个团队在开发阶段就减少不恰当的建表语句、错误SQL、错误的索引有积极的意义,故分享出来给大家参考。

下边分为建表规约、SQL规约、索引规约三个部分,每部分的每一条都有强制、建议两个级别,大家在参考时,根据自己公司的情况来权衡。

一、建表规约

【强制】(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)禁止使用外键,如果有外键完整性约束,需要应用程序控制

解读:外键会导致表与表之间耦合,UPDATEDELETE操作都会涉及相关联的表,十分影响SQL的性能,甚至会造成死锁。

【强制】(8)必须把字段定义为NOT NULL并且提供默认值

解读:a、NULL的列使索引/索引统计/值比较都更加复杂,对MySQL来说更难优化 b、NULL这种类型Msql内部需要进行特殊处理,增加数据库处理记录的复杂性;同等条件下,表中有较多空字段的时候,数据库的处理性能会降低很多 c、NULL值需要更多的存储空,无论是表还是索引中每行中的NULL的列都需要额外的空间来标识

【强制】(9)禁用保留字,如DESC、RANGE、MARCH等,请参考Mysql官方保留字。

【强制】(10)如果存储的字符串长度几乎相等,使用CHAR定长字符串类型。

解读:能够减少空间碎片,节省存储空间。

【建议】(11)在一些场景下,考虑使用TIMESTAMP代替DATETIME。

解读:a、这两种类型的都能表达"yyyy-MM-dd HH:mm:ss"格式的时间,TIMESTAMP只需要占用4个字节的长度,可以存储的范围为(1970-2038)年,在各个时区,所展示的时间是不一样的;b、而DATETIME类型占用8个字节,对时区不敏感,可以存储的范围为(1001-9999)年。

* 【建议】(12)当心自动生成的Schema,建议所有的Schema手动编写。

解读:对于一些数据库客户端不要太过信任。


二、SQL规约

【建议】 (1) 为了充分利用缓存,不允许使用自定义函数、存储函数、用户变量。

解读:如果查询中包含任何用户自定义函数、存储函数、用户变量、临时表、Mysql库中的系统表,其查询结果都不会被缓存。比如函数NOW()或者CURRENT_DATE()会因为不同的查询时间,返回不同的查询结果。

【强制】(2)在查询中指定所需的列,而不是直接使用“ *”返回所有的列

解读:a)读取不需要的列会增加CPU、IO、NET消耗 b)不能有效的利用覆盖索引

【强制】(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中编写SQLWHERE条件中有多个条件时,需要先看看当前表是否有现成的联合索引直接使用,注意各个条件的顺序尽量和索引的顺序一致。

【建议】(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的情况,影响查询性能。

解读:1、假设有查询条件为WHERE a=? and b=? ORDER BY c;存在索引:a_b_c,则此时可以利用索引排序。2、反例:在查询条件中包含了范围查询,那么索引有序性无法利用,如:WHERE a>10 ORDER BY b;索引a_b无法排序。

【建议】(8)在where中索引的列不能某个表达式的一部分,也不能是函数的参数。

解读:即是某列上已经添加了索引,但是若此列成为表达式的一部分、或者是函数的参数,Mysql无法将此列单独解析出来,索引也不会生效。

【建议】 (9)我们在where条件中使用范围查询时,索引最多用于一个范围条件,超过一个则后边的不走索引。

解读:Mysql能够使用多个范围条件里边的最左边的第一个范围查询,但是后边的范围查询则无法使用。

【建议】 (10)在多个表进行外连接时,表之间的关联字段类型必须完全一致

解读:当两个表进行Join时,字段类型若没有完全一致,则加索引也不会生效,这里的完全一致包括但不限于字段类型、字段长度、字符集、collection等等

参考

  • 《High.Performance.MySQL.3rd.Edition》
  • 《阿里巴巴java开发手册》

原作者:浮雷
原文链接:你真的用对数据库了吗?
原出处:掘金
侵删

f4d7a3b05ad352879e4fbe3bd01f8f0a.gif

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

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

相关文章

linux找不到动态链接库 .so文件的解决方法

如果使用自己手动生成的动态链接库.so文件,但是这个.so文件,没有加入库文件搜索路劲中,程序运行时可能会出现找不到动态链接库的情形。 可以通过ldd命名来查看可执行文件依赖的动态链接库,如下(其中D为可执行程序): 其…

mui的学习图片预览

css部分 <link href"./css/mui.min.css" rel"stylesheet"/> <style> html,body {margin: 0px;padding: 0px;background-color: white;} .mui-preview-image.mui-fullscreen { position: fixed;z-index: 20; background-co…

Kafka Connect在MapR上

在本周的白板演练中&#xff0c;MapR的高级产品营销经理Ankur Desai描述了Apache Kafka Connect和REST API如何简化和提高在处理来自包括旧数据库或数据仓库在内的各种数据源的流数据时的敏捷性。 他还解释了使用MapR Streams与Kafka进行数据传输时此体系结构的差异。 其他资源…

LeetCode--palindrome-number回文数

1、问题 Determine whether an integer is a palindrome. Do this without extra space. click to show spoilers. Some hints: Could negative integers be palindromes? (ie, -1) If you are thinking of converting the integer to string, note the restriction of u…

如何取消 登录_LSAT | 退考、缺考、取消成绩,各自的区别和流程是怎样的?

专注顶尖法学院JD/LLM申请指导咨询&#xff0c;更多内容请关注联才微信公众号&#xff1a;wisdom-linked排版 | 联才; 编辑 | 联才掐指一算&#xff0c;现在距离6/23亚洲场LSAT考试只剩下15天的时间了&#xff0c;你目前的备考进展如何呢&#xff1f;如果你拿不准是否要去考试&…

gtest 编译、安装和使用

本例以 gtest-1.7.0 为例进行讲解。一、要求&#xff1a;1. 安装 cmake二、编译1. 下载 gtest 源码包&#xff0c;并解压&#xff0c;如&#xff1a;/home/hdc/gtest-1.7.0&#xff1b; 2. 编译 gtest 动态库&#xff0c;进入 gtest-1.7.0 目录&#xff0c;编辑 CMakeLists.tx…

ReentrantReadWriteLock读写锁的使用

类ReentrantLock具有完全互斥排他的效果&#xff0c;即同一时间只有一个线程在执行ReentrantLock.lock()后面的代码。这样虽然保证了线程的安全性&#xff0c;但是效率低下。JDK提供了ReentrantReadWriteLock读写锁&#xff0c;使用它可以加快效率&#xff0c;在某些不需要操作…

idea如何把包变为模块_让我们将包变成模块系统!

idea如何把包变为模块使用构建系统将许多项目分为模块/子项目&#xff08; Maven &#xff0c; Gradle &#xff0c; SBT …&#xff09;&#xff1b; 编写模块化代码通常是一件好事。 将代码分为构建模块主要用于&#xff1a; 隔离代码部分&#xff08;减少耦合&#xff09; …

VS2017无法启动

新安装了VS2017&#xff0c;安装没问题&#xff0c;但是总出现启动时没反应的状况&#xff0c;鼠标双击后转圈&#xff0c;然后就没然后了。。 解决办法&#xff1a; 第一步&#xff1a; 开始-->所有程序-->Microsoft Visual Studio 2017文件夹-->VisualStudio Tool…

gm怎么刷东西 rust_Rust语言:解引用详述,搞不明白这个概念,趁早放弃Rust

Rust是内存安全的&#xff0c;对新手来说&#xff0c;最大的困难是可恶的编译器&#xff0c;在其他语言上面叱咤风云&#xff0c;偏偏被Rust搞到崩溃。所以&#xff0c;大家都戏谑道&#xff0c;Rust是面向编译器编程。和编译器做斗争的过程中&#xff0c;遇到最多的是&#xf…

VS2010中使用gtest简单案例

1、下载googletest代码 https://github.com/google/googletest 2、解压并进入找到msvc文件夹 googletest-master\googletest-master\googletest\msvc 3、打开gtest.sln文件 4、编译gtest和gtest_main工程&#xff0c;生成gtestd.lib和gtest_maind.lib&#xff0c;将这两个静…

记录一次Oracle注入绕waf

这个注入挺特殊的&#xff0c;是ip头注入。我们进行简单的探测: 首先正常发起一次请求&#xff0c;我们发现content-type是76 探测注入我习惯性的一个单引号: 一个单引号我发现长度还是76 我开始尝试单引号&#xff0c;双引号一起: 我失败了长度还是76 一般sql注入输入单引号一…

生成字节码

在这篇文章中&#xff0c;我们将看到如何为我们的语言生成字节码。 到目前为止&#xff0c;我们已经看到了如何构建一种语言来表达我们想要的东西&#xff0c;如何验证该语言&#xff0c;如何为该语言构建编辑器&#xff0c;但实际上我们仍然无法运行代码。 是时候解决这个问题…

Java迭代器contains的问题

功能&#xff1a;ArrayList去除集合中字符串的重复值(字符串的内容相同)&#xff0c;思路&#xff1a;创建新集合方式。 第一种编译运行没问题&#xff0c;第二种写法出错&#xff0c;原因是不可以两次使用it.next()。 错误提示&#xff1a;Exception in thread "main&q…

ad如何镜像器件_使用 Dockerfile 制作镜像

前面几篇文章已经给大家介绍了 Docker 的基本概念&#xff0c;相信大家也会使用 Docker 运行自己想要的容器了。但是只有学会制作镜像&#xff0c;才能将 Docker 应用到我们的项目中去。下面我们就来学习如何使用 Dockerfile 来制作镜像。Dockerfile 是一个文本文件&#xff0c…

centos7.5部署ELk

第1章 环境规划 1.1 ELK介绍 ELK是ElasticSerach、Logstash、Kibana三款产品名称的首字母集合&#xff0c;用于日志的搜集和搜索。 Elasticsearch&#xff1a;是一个开源分布式搜索引擎&#xff0c;提供搜集、分析、存储三大功能&#xff0c;特点是分布式、零配置、自动发…

使用Google Test的一个简单例子

0. 引子 本例是从 gtest-1.5.0 自带的 sample 中的 sample1 改写而来&#xff0c;笔者只添加了一个求 n 的阶层的函数&#xff0c;如下。 void Factorial(int n, int & result ) { result 1; for (int i 1; i < n; i) result * i; } 目的是想测试像这样将返回值放在参…

Java静态方法与非静态方法的泛型

Java中&#xff0c;非静态方法可以使用类的泛型&#xff0c;也可以定义自己的泛型&#xff1b;静态方法由于随着类的加载而加载&#xff0c;不能访问类的泛型&#xff08;因为在创建对象的时候才确定&#xff09;&#xff0c;因此必须定义自己的泛型类型。 详细请参考&#xf…

Android Studio 日志工具

在项目中提供5个方法打印日志 Log.v() 最常见的日志信息 Log.d() 调试信息 Log.i() 用于打印用户操作行为 Log.w()警告潜在风险 Log.e()报错信息 TAG 填入类名就好 msg:要打印的信息 也可以对信息进行过滤 点他弹出自定义的日志过滤器 转载于:https://www.cnblogs.com/feizianq…

jpa加密_使用JPA侦听器的数据库加密

jpa加密最近&#xff0c;我不得不将数据库加密添加到一些字段中&#xff0c;并且发现了很多不好的建议。 建筑问题 最大的问题是建筑。 如果持久性管理器静静地处理您的加密&#xff0c;那么根据定义&#xff0c;您的体系结构将在持久性和安全性设计之间要求紧密而不必要的绑…