一、MySQL 开发规范概述


原则:SQL开发规范制定是基于良好的编码习惯和可读性;
目的:消除冗余,数据简约,提高效率,提高安全;
范围:《SQL开发规范手册》

二、MySQL 开发规范手册【设计原则】


【1】任何语句使用前通过 EXPLAIN 查看执行计划是否用到索引:【链接
【2】不要从明细表查统计结果,定期统计插入到汇总表:这个做互联网的深有感触,一张表几千万的数据,统计一个数据,性能真心很低。

1 EXPLAIN
2 SELECT COUNT(user_no) AS u_no,
3 SUM(bid_no) AS b_no
4 FROM user
5 WHERE registered_date >= '2013-02-07 18:11:40';

Query_time: 18.229131 Lock_time: 0.000474 Rows_sent: 0 Rows_examined:100289。
 注:从明细表查询时检索记录数为 100289,从汇总表查询时检索记录数为 1,需要改为从汇总表查询。

【3】禁止使用SELECT *,必须指定字段名称,同样,INSERT 后边需要指定字段;
【4】明细统计时,只统计编码,不要关联名称等冗余字段。注:名称显示可查询全局 hashtable(写 300万/秒 读1200万/秒)。
其他 KV工具:Memcached(读写 8万/秒,多线程更快,适合小数据)Redis (读写10万/秒,单线程,可多进程,适合大数据和复杂数据结构)注:一般 php 用 Memcached,Java 用 Redis,小量数据时推荐 static 变量。
【5】联合查询时,每个表必须加别名,否则系统需要自己生成别名,影响性能。关联字段必须是索引(最好是主键),where 条件用以过滤主表;注:提高 SQL 解析效率,便于代码阅读,注意字段前边也要加别名。

1 --问题语句:bid_no 就没有指定别名
2 SELECT a.*, b.user_name
3 FROM user a
4 LEFT JOIN class_name b
5 ON a.uid = b.uid AND b.student = 0
6 WHERE bid_no = '31001383713';

【6】每个查询结果集使用的内存量不要超过 256M,可以通过时间范围控制,如 RK BETWEEN A AND B,大表按可小时操作。注:可通过分批查询返回大量数据;

1 SELECT user_no, bid_no, evaluate_no, registered_date, updated_date, operator, time_stamp FROM user;
2 Query_time: 239.269626 Lock_time: 0.000151 Rows_sent: 2271775 Rows_examined: 2271775

【7】页面查询在 10 秒内要返回结果,服务器超时限制默认为 65 秒。定期查看慢查询日志 xxx-slow.log。注: show variables like '%cache%' 查看 query cache 是否足够大和命中率;

Query_time: 67.432783 Lock_time: 0.000373 Rows_sent: 1 Rows_examined: 168671

【8】语句中避免子查询,子查询无法使用索引(少数子查询使用索引,参考执行计划)。注:子查询结果集记录极少时可以使用,否则效率很差;
【9】语句中避免使用 GROUP BY,可通过批量程序定期汇总。注:频繁 GROUP BY 需要创建临时结果集;

1 SELECT MIN (b.bid_no) FROM user b
2 GROUP BY b.bid_no

【10】禁止语句级并行;
【11】大表 join 用临时表代替 (create temporary table);

三、MySQL 开发规范手册【字段设计】


【1】尽可能使用更小的数据类型,如 TINYINT、SMALLINT、MEDIUMINT、INT、BIGINT。注:int(11) 的11代表客户端显示宽度,并不是取值范围,精度:tinyint -2^8-2^8-1 smallint - 2^15-2^15-1 int -2^31-2^31-1 bigint -2^63-2^63-1;

 1 --问题语句:int 类型长度应该根据实际设定
2 DROP TABLE IF EXISTS `user`;
3 CREATE TABLE `user` (
4 `user_no` int(32) NOT NULL DEFAULT '',
5 `bid_no` int(32) NULL DEFAULT NULL,
6 `evaluate_no` int(32) NULL DEFAULT NULL,
7 `registered_date` datetime NULL DEFAULT NULL,
8 `updated_date` datetime NULL DEFAULT NULL,
9 `operator` varchar(255) CHARACTER SET latin1 COLLATE latin1_swedish_ci NULL DEFAULT NULL,
10 `time_stamp` datetime NULL DEFAULT NULL,
11 PRIMARY KEY USING BTREE (`user_no`)
12 ) ENGINE = InnoDB CHARACTER SET = latin1 COLLATE = latin1_swedish_ci ROW_FORMAT = Compact;

【2】尽量少用 TEXT、BLOB、CLOB 等专有类型 (大数据如图片等可用链接代替),注:CLOB 等类型在性能和兼容性表现不好;

1 --问题语句:after_value_text 字段使用了 CLOB
2 DROP TABLE IF EXISTS `user`;
3 CREATE TABLE `user` (
4 `user_no` int(11) NOT NULL DEFAULT '',
5 `bid_no` int(11) NULL DEFAULT NULL,
6 `evaluate_no` int(11) NULL DEFAULT NULL,
7 `after_value_text` CLOB,
8 PRIMARY KEY USING BTREE (`user_no`)
9 ) ENGINE = InnoDB CHARACTER SET = latin1 COLLATE = latin1_swedish_ci ROW_FORMAT = Compact;

【3】相同属性对应的数据类型,如字符型,数值型不能混合使用,依赖后期转换;

1 --问题语句:默认bid_no 应该是 int,否则需要隐式转化
2 DROP TABLE IF EXISTS `user`;
3 CREATE TABLE `user` (
4 `user_no` int(11) NOT NULL DEFAULT '',
5 `bid_no` char(11) NULL DEFAULT NULL,
6 PRIMARY KEY USING BTREE (`user_no`)
7 ) ENGINE = InnoDB CHARACTER SET = latin1 COLLATE = latin1_swedish_ci ROW_FORMAT = Compact;

【4】相同字段不同表中的类型和长度要一致;
【5】字段名称不能使用关键字;
【6】不要指定字段级编码,建议全库统一。可以设置编码的有数据源、表,语句。如果语句中没有设置编码就会遵循表的编码,表的编码不存在时,则遵循数据源的编码,注:字段级编码在导入导出时可能乱码;
【7】默认值要规范,例如日期不要使用 0000-00-00;

1 --问题语句:特有默认值在 ETL 时会导致异常
2 DROP TABLE IF EXISTS `user`;
3 CREATE TABLE `user` (
4 `user_no` int(11) NOT NULL DEFAULT '',
5 `bid_no` int(11) NULL DEFAULT NULL,
6 `time_stamp` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
7 PRIMARY KEY USING BTREE (`user_no`)
8 ) ENGINE = InnoDB CHARACTER SET = latin1 COLLATE = latin1_swedish_ci ROW_FORMAT = Compact;

【8】不要用自增ID做主键,无法同步,无约束意义。自增在分表分库的业务场景下也不实用,容易导致主键ID冲突。注:字段设计需要精雕细琢,尽量符合三范式,确定没有索引的表可以使用自增主键;

1 --问题语句:user_no 使用了自增
2 DROP TABLE IF EXISTS `user`;
3 CREATE TABLE `user` (
4 `user_no` int(11) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT 'ID号',
5 `bid_no` int(11) NULL DEFAULT NULL,
6 PRIMARY KEY USING BTREE (`user_no`)
7 ) ENGINE = InnoDB CHARACTER SET = latin1 COLLATE = latin1_swedish_ci ROW_FORMAT = Compact;

【9】不要使用外键和触发器,注:外键和触发器不适合大数据;
【10】事务相关记录保留时间戳,建议只增不改;在必须对记录进行修改的时候,保留更改时间戳;

1 -- 正确示例:可用于同步和跟踪
2 ctime datetime NOT NULL COMMENT '创建时间',
3 utime timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间'

【11】精度要求高的字段使用 decimal(number, numeric) 代替 double, float(real)。需要选对场景:精度要求非常高的计算中,要保证有效数字的总个数足够多,需要使用 decimal。注:用在与金额有关的地方;
【12】禁止非英文字段名称,使用中文字段名会创造很多困难点;

四、MySQL 开发规范手册【索引使用】


【1】一般情况下,一次查询只会用到一个索引。特定情况出现 merge index的情况,如下可能出现 ( a=1 or b=2 ) 会合并 a 和 b 的索引,或者使用 union all。因为 or 会破坏索引的最左原则;
【2】每个表索引越少越好,建议1-3个,最多5个 (oltp 1-5,olap 5以上)。注:表索引过多影响操作效率, GreenPlum 数据库可合理利用分区和分布键;
【3】每个查询必须用到索引 (小表可能全表更好,视数据量决定)。注:如果没有索引,即使加了 rownum = 1,也会全表扫描;
 
【4】建立组合索引时,WHERE 条件中用到等于的字段放前边,用到范围的字段放后边。注:如 DD=100000 AND SJ BETWEEN A AND B 。
 
【5】删除重复字段的索引,减少 DML IO。注:索引过多影响操作效率,重复索引可能导致执行计划异常;

1 --问题语句:下面的 key 属于重复key 第一个可以删除掉
2 DROP TABLE IF EXISTS `user`;
3 CREATE TABLE `user` (
4 `user_no` int(11) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT 'ID号',
5 `bid_no` int(11) NULL DEFAULT NULL,
6 PRIMARY KEY USING BTREE (`user_no`),
7 KEY RoadLineID (`bid_no`),
8 KEY RoadLineID2 (`bid_no`,`evaluate_no`)
9 ) ENGINE = InnoDB CHARACTER SET = latin1 COLLATE = latin1_swedish_ci ROW_FORMAT = Compact;

【6】除了主键外,避免建立其他唯一性索引。注:业务逻辑通过业务应用控制,数据库设计时要选择正确的主键;

1 --问题语句:bid_no 数据量大的话不应该定义为唯一索引
2 DROP TABLE IF EXISTS `user`;
3 CREATE TABLE `user` (
4 `user_no` int(11) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT 'ID号',
5 `bid_no` int(11) NULL DEFAULT NULL,
6 PRIMARY KEY USING BTREE (`user_no`),
7 UNIQUE KEY index_bid_no (bid_no)
8 ) ENGINE = InnoDB CHARACTER SET = latin1 COLLATE = latin1_swedish_ci ROW_FORMAT = Compact;

【7】索引中重复的记录数越少,效率越高,效率最高的是主键。注:如果同一记录超过50%,全表扫描定期 analyze table 收集统计信息和直方图,如果可以加 not null 的最好加上。例如性别这个字段就不适合体检索引;
【8】索引字段最好不要存在 NULL,NULL可用 0 替代,建议把默认值设置为 0。注:在 null远多于非null的情况下,建议表设计 default 0;
【9】组合索引可以只使用第一个,或者前两个,或者前几个,不能从第二个开始用,也不能跳着使用。注:索引使用从前缀开始,多字段索引到 between或者<,>等以后字段不会使用索引,排序最好在索引中实现。
【10】 关联查询用到的索引的编码必须一致,建议都采用UTF-8。注:如果编码不一致,索引无效;

五、MySQL 开发规范手册【查询条件】


【1】SQL 语句的 WHERE 条件避免使用无效条件、无效括号、无效排序,如 (1=1)、order by。注:示例语句中使用了无效条件、无效括号,对性能有极大影响;

1 --问题语句:
2 SELECT user_no, bid_no, evaluate_no
3 FROM user
4 WHERE (1=1)
5 AND ( (user_no LIKE '%') AND (bid_no LIKE '%') )
6 AND ( evaluate_no <> 0 )
7 AND ( operator <> 0 )
8 ORDER BY user_no ASC;
9 Query_time: 10.688586 Lock_time: 0.000070 Rows_sent: 55561 Rows_examined: 59075

【2】 SQL语句中不要加用不到的排序。注:类似 order by null 等无效排序会影响执行效率;
【3】控制临时结果集,包括中间结果和中间排序。注:合理横向和纵向拆分,一次处理数据量不要太大;

select * from v$sort_usage,show status like %temp%;、

【4】 WHERE 条件中最好不要用 IN 和 LIKE。注:可使用 exists 代替 in, 使用 = 代替 like;
【5】 WHERE 条件中不要使用 NOW() 等进行判断,避免影响执行计划。注:使用 now() 的存储过程无法重复运行,且影响执行计划。
【6】禁止使用未经认证的 hint,如 SELECT SQL_NO_CACHE f FROM t。注:使用标准SQL,便于版本间兼容;
【7】索引相关字段不要使用函数或者进行运算,如 field1 + 1 = field2、ADDDATE(field1,…CAST。注:大多数字段使用函数不会使用索引,只有确定性 function 使用函数索引;

--问题语句:会导致索引失效
SELECT * FROM user WHERE CAST(CONCAT(updated_date, ' ', time_stamp) AS datetime) BETWEEN '2014-06-10 10:30:00'

【8】禁止字段格式转换,如 SELECT x FROM GS WHERE BM=200000,数值两边不要加引号。注:要区分数值、日期和字符串,科学计数法更要慎重使用;
 

六、MySQL 开发规范手册【存储过程】


【1】存储过程中操作的记录数超过1000条时不能使用游标 (可用临时表代替,禁止使用触发器、自定义函数)。注:也不能使用 while,大批量数据操作对应脚本必须进行压力测试,以保证可用性;
【2】在存储过程的关键步骤开始和结束都要记录信息到日志表,用于监控和调试。注:提交要及时,记录要详细;
【3】 使用标准操作符,不要使用双引号、!= 等过渡性操作符。注:非标准操作符可能导致其他无法预期问题;
【4】存储过程要能够重复执行,执行时需要清空历史冲突记录。注:非常重要,多种情况下需要存储过程重复运行;
【5】使用自制事务(autonomous transaction)控制写日志,独立日志操作存储过程。注:用以避免回滚时无法记录日志;
【6】所有过程必须定义异常处理,并自定义错误代码,从-20001开始;

 1 CREATE OR REPLACE PROCEDURE ap AS
2 BEGIN
3 NULL;
4 --body
5 EXCEPTION
6 WHEN OTHERS
7 THEN
8 NULL;
9 -- exception handler
10 END;

【7】过程避免每条语句提交。注:控制提交频率大于1秒;
【8】禁止使用递归。注:使用递归时,性能消耗无法控制;

七、MySQL 开发规范手册【远程表】


【1】远程表结构要与原始表一致,尤其是索引。注:同时编码要一致;
【2】远程表数据不要大于256M,远程表的 WHERE 无效。注:远程表先下载到本地,再进行其他操作,所以不宜过大;
【3】远程表一般用来全表小数据全量同步。注:远程表大数据操作时很慢;
【4】远程表操作完毕提交操作。注:默认远程表只用来读操作,如果进行写操作,则锁全表;

八、MySQL 开发规范手册【性能优化】


【1】 文件格式改为 XFS 可以提升 5%,增加 1/6 磁盘可以提升 1/6,优化索引和结构,一般可以提升 100-1000 倍。注:了解SQL原理,让数据经过一次读操作即能返回结果时最快;
【2】使用 TYPE=HEAP 的临时表。注:适合频繁删除和更新;

九、MySQL 开发规范手册【引擎使用】


【1】使用 INNODB 引擎操作大批量数据时,在过程结尾提交,避免过度 COMMIT。注:通过事务提交可以提高大数据操作效率,同时有序插入、合并插入也可以大幅提高数据库效率。

1 --正确语句:
2 START TRANSACTION;
3 INSERT INTO t(datetime, UID, content, TYPE) VALUES ('0', 'userid_0', 'content_0', 0),('1',
4 'userid_1', 'content_1', 1);
5 INSERT INTO t(datetime, UID, content, TYPE) VALUES ('2', 'userid_2', 'content_2', 2),('3',
6 'userid_3', 'content_3', 3);
7 COMMIT;

【2】避免跨引擎操作,如表分别为 InnodB  和 MyISAM。问题语句:(不能用函数、需要有索引、先汇总再关联、要查汇总表、表引擎要一致、表编码要一致、字段类型要一致)。注:跨引擎操作时,事务失效,推荐都使用 InnodB;

十 、MySQL 开发规范手册【权限控制】


【1】 PHP 连接 MYSQL  的用户只分配对应库 SIUD。注:权限越大,被攻击时受到的破坏越大。注:权限越大,被攻击时受到的破坏越大;
【2】所有客户端提交的变量都要进行转义操作,防止非法注入。注:可通过工具 AppScan 统一检测;

1 -- 问题脚本:
2 $username = isset($_REQUEST["username"]) ? $_REQUEST["username"] : "";
3 $sql_gh="select EMPID,USERPASS,EMPSTATUS from ydserver.yd_cas_emp where EMPID='$username'";
 

MySQL 开发规范【X千万/表级别】的更多相关文章

  1. [转发] 老叶观点:MySQL开发规范之我见

    原文: http://imysql.com/2015/07/23/something-important-about-mysql-design-reference.shtml 老叶观点:MySQL开发 ...

  2. [转载] 根据多年经验整理的《互联网MySQL开发规范》

    原文: http://weibo.com/p/2304181380b3f180102vsg5 根据多年经验整理的<互联网MySQL开发规范> 写在前面:无规矩不成方圆.对于刚加入互联网的朋 ...

  3. 从MySQL开发规范处看创业

    版权声明:本文为博主原创文章.未经博主同意不得转载. https://blog.csdn.net/n88Lpo/article/details/78099185 作者:唐勇.深圳市环球易购.MySQL ...

  4. 建议收藏 - 专业的MySQL开发规范

    为了项目的稳定,代码的高效,管理的便捷,在开发团队内部会制定各种各样的规范 这里分享一份我们定义的MySQL开发规范,欢迎交流拍砖 数据库对象命名规范 数据库对象 命名规范的对象是指数据库SCHEMA ...

  5. 根据多年经验整理的《互联网MySQL开发规范》

    一.基础规范 使用 INNODB 存储引擎 表字符集使用 UTF8  所有表都需要添加注释 单表数据量建议控制在 5000W 以内 不在数据库中存储图⽚.文件等大数据 禁止在线上做数据库压力测试 禁⽌ ...

  6. 老叶观点:MySQL开发规范之我见

    来源:http://ourmysql.com/archives/1396 大多数MySQL规范在网上也都能找得到相关的分享,在这里要分享的是老叶个人认为比较重要的,或者容易被忽视的,以及容易被混淆的一 ...

  7. 老叶观点:MySQL开发规范之我见(更新版)

    转自:http://mp.weixin.qq.com/s?__biz=MjM5NzAzMTY4NQ==&mid=207239419&idx=2&sn=bddbe0a657758 ...

  8. 《互联网MySQL开发规范》

    一.基础规范 使用 INNODB 存储引擎 表字符集使用 UTF8  所有表都需要添加注释 单表数据量建议控制在 5000W 以内 不在数据库中存储图⽚.文件等大数据 禁止在线上做数据库压力测试 禁⽌ ...

  9. 一份完整的 MySQL 开发规范,进大厂必看!

    作者:听风 https://www.cnblogs.com/huchong/p/10219318.html 一.数据库命令规范 1.所有数据库对象名称必须使用小写字母并用下划线分割 2.所有数据库对象 ...

  10. 一文总结高并发大数据量下MySQL开发规范【军规】

    在互联网公司中,MySQL是使用最多的数据库,那么在并发量大.数据量大的互联网业务中,如果高效的使用MySQL才能保证服务的稳定呢?根据本人多年运维管理经验的总结,梳理了一些核心的开发规范,希望能给大 ...

随机推荐

  1. 微信小程序注册、登录小功能都在这

    微信小程序实现注册.登录页面的小功能整理,希望对大家有帮助. 1. 正则验证手机号码 var mobile = that.data.phone;     var myreg = /^(((13[0-9 ...

  2. java发送短信验证码带倒计时

    分享一个完整的java发送短信验证码的完整实例,这是一个官方的使用demo,带有60秒倒计时功能. 效果: 我使用的是榛子云短信平台, 官网地址:http://smsow.zhenzikj.com 我 ...

  3. React++antd+ProComponents可编辑表格EditableProTable组件实现表单中的可编辑列表组件

    需求: 在新增&编辑表单中,共分三个表单模块,第二个模块设计为一个可编辑表格组件,其中可选下拉列表依赖外层第一个模块的某条数据值,提供新增.编辑.删除.按规定条件去重等功能,并在第三个模块中自 ...

  4. node16 以上版本不能安装 node-sass

    最近多次遇到这个问题,node16+版本安装或者初始化带有node-sass和sass-loader包的项目报错. 方法一: 卸载旧版本的node-sass和sass-loader,安装sass和sa ...

  5. 主要转引本地的pycharm如何与服务器连接

    需求:本地电脑pycharm上编写程序,在服务器端运行代码. 主要参考了这两篇文章: 1. https://blog.csdn.net/qq_43391414/article/details/1205 ...

  6. AutoCAD2018

    「AutoCAD_2018_SC.exe」https://www.aliyundrive.com/s/GvpR9yg6TWg 点击链接保存,或者复制本段内容,打开「阿里云盘」APP ,无需下载极速在线 ...

  7. constexpr 和常量表达式

    常量表达式(是const expression) 是指值不会改变并且在编译过程中就能得到计算结果的表达式.显然,字面值属于常量表达式,用常量 表达式初始化的const 对象也是常量表达式.后面将会提到 ...

  8. 5.Vue前后端交互

    一.前后端交互模式 1.1 接口调用方式 原生ajax 基于JQuery的ajax fetch axios 返回一个完整的HTML页面 也可以只返回特定格式的数据,比如json 1.2 URL地址格式 ...

  9. 在DeepIn系统中使用eclipse创建maven的Web项目

    1. 安装好jdk和eclipse以后,启动eclipse 2. 创建maven项目,选择Maven Project 3. 在创建项目过程中,创建简单Maven项目,不使用archetype创建(会联 ...

  10. centos7.6 挂载镜像配置本地yum源

    镜像下载 http://mirrors.aliyun.com/centos-vault/7.6.1810/isos/x86_64/ 配置本地yum源 1.安装Centos后默认的Yum源如下 [roo ...