「MySQL」 - SQL设计规范
一、数据库命名规范
A、对象名称使用小写字母、下划线分割
- Windows默认情况下无法建立大写库名
- Linux大小写敏感,MySQL数据文件(库名、表名、表别名严格区分大小写)
- Linux查询大小写敏感
- Windows查询大小写不敏感
- MySQL 5.6,lower_case_table_names,0:表示区分大小写、1:表示不区分大小写
- MySQL 5.7,lower_case_table_names,2:表示区分大小写、1:表示不区分大小写
- 统一命名使用全小写字母和下划线分割
- 列名与列表名在所有情况下忽略大小写
B、对象名禁止使用MySQL关键字/保留字
- 使用关键字,建表时不会报错,CURD时会提示SQL语句错误
- 对于SQL语句中的关键字,写SQL时需要单引号包围,该要求难以统一,还是不使用关键字作为表字段
- 关键字列表 - 9.3 Keywords and Reserved Words
C、对象命名做到见名知意,限定在32个字符范围内
- 字符过长增加网络传输开销
D、临时表,tmp前缀、日期作为后缀,方便筛选、倒库、清理
E、备份表,bak前缀、日期作为后缀,方便筛选、倒库、清理
- 大表,导出为SQL文件进行备份
F、存储相同数据的列名和列类型必须一致
- 关联列,类型不一致会导致隐式类型转换,引起索引失效,降低查询效率
二、基本设计规范
A、统一使用InnoDB存储引擎(5.6之后为默认)
- TODO MySQL不同存储引擎比较
B、统一使用utf8字符集
- 只存储中文字符,可以使用GBK、GB2312
- 对于emoj需要使用utf8mb4
- TODO utf8和utf8mb4之前还有争论,关注讨论结论
- 编码转换容易导致乱码,以及索引失效
C、所有表和字段都需添加注释
- 建库时维护好数据字典
D、控制数据量大小,控制在500w行
- InnoDB未做最大行限制,受限于存储设备和文件系统
- 分库分表
- TODO 分库分表策略
E、谨慎使用MySQL分区表
- 分区表在物理上表现为多个文件,逻辑上表现为一个文件
- 需要把多个物理文件分布于磁盘阵列,才能提高IO利用率
- 减少跨分区查询
- 更倾向于使用物理分表方式管理海量数据
F、减小表宽度、尽量做到冷热数据分离
- MySQL限制单表最多存储4096列
- 每行数据大小不超过65535 BYTE = 64K
- 控制宽度,对列进行垂直拆分
- 减少IO,保留热数据的内存缓存命中率
- 使用字段进行查询,避免读入无用的冷数据
G、禁止在表中建立预留字段
- 预留字段难以做到见名知意
- 预留字段难以确认存储类型
- 修改类型,会引起全表锁定
- 修改表字段代价 >> 增加表字段
H、禁止在数据库存储图片、文件等bin数据
I、禁止在线上库做压力测试
J、禁止从开发环境、测试环境直连生产环境数据库
三、索引设计规范
A、不滥用、乱用索引
- 建议单表索引不超过5个
- 提高查询效率,降低插入和更新效率
- MySQL优化器,会评估索引,生成最优执行计划,索引过多,导致生成执行计划时间过长,降低效率
B、InnoDB表,必须有一个主键 - B树
- InnoDB使用主键按照顺序组织表结构
- 如果没有主键,会按照表顺序,选择第一个非空唯一索引组织表结构
- 如果没有符合以上规则的,MySQL会自动生成6BYTE主键(性能不佳)、
- 不适用频繁更新的列作为主键
- 不使用联合索引作为主键
- 不使用UUID、MD5、HASH、字符串作为主键(无法保证顺序增长)
- 建议选择/使用自增ID列
- TODO 索引于B树
C、常见索引列
- SELECT、UPDATE、DELETE语句中WHERE从句中的列
- 包含ORDER BY、GROUP BY、DISTINCT中的列
- 多表的JOIN关联列
D、索引列顺序
- 联合索引从左向右使用
- 区分度最高的列(主键、唯一),置于联合索引的最左侧
- 字段长度小的列置于联合索引的最左侧
- 元素占用空间小,内存页中元素多,索引速度快
- 使用最频繁的列,置于联合索引的最左侧
- 避免冗余和重复索引
- 对于频繁的查询,优先考虑使用覆盖索引(所有的列都建立索引)
- 避免InnoDB索引的二次查找
- 把随机IO变为顺序IO加快查询效率
- 避免使用外键
- 外键用于保证数据的参照完整性,建议置于业务端实现
- 外键影响父表和子表的写操作,从而降低性能
- 不建议使用外键约束,但一定在表与表之间的关联键上建立索引
上述描述中有一条联合索引最左侧,使用数据区分度高的列。关于区分度,唯一值和总行数比值,区分度越高(接近1)。
SELECT
COUNT(DISTINCT cat_1)/COUNT(*) AS cat_1_rate,
COUNT(DISTINCT cat_6)/COUNT(*) AS cat_6_rate
FROM OuterCooperationDB.product_core;+------------+------------+
| cat_1_rate | cat_6_rate |
+------------+------------+
| 0.0002 | 0.0381 |
+------------+------------+
四、字段设计规范
A、优先选择符合存储需要的最小数据类型
- 将字符串转化为数字类型存储(INET_AION、IP->Integer;INET_NTOA、Integer->IP)
- 对于非负整数,优先使用无符号整型存储(id)
- VARCHAR(N)代表的是字符数,不是BYTE数
- VARCHAR(255),可以保存255中文字符,使用UTF8,实际占用765BYTE
- 过大长度消耗更多的内存
B、避免使用TEXT、BLOB数据类型
- TinyText、Text(64K)、MidumText、LongText
- 进行排序等查询,无法使用内存临时表,而必须使用磁盘临时表
- 读取数据时,需要二次查询
- 非用不可的情况,可以把BLOB和TEXT拆分到单独的拓展表中
C、避免使用ENUM数据类型
- 修改ENUM值需要使用ALTER语句
- 8 Reasons Why MySQL's ENUM Data Type Is Evil
D、尽可能把所有列定义为NOT NULL
- 索引NULL列,需要额外的空间,要占用更多的空间
- 进行比较和计算时,需要对NULL值做特别的处理
E、使用TIMESTAMP或DATETIME类型存储时间
- 禁止使用字符串存储日期型数据
- 无法用日期函数进行计算和比较
- 使用字符串存储占用更多的空间
- TIMESTAMP(4BYTE),DATETIME(8BYTE)
- TIMESTAMP范围小,1970-01-01 00:00:01 - 2038-01-19 03:14:07
- DATETIME范围大
F、金额相关类型,使用decimal类型存储
- float、double不精确
- decimal精确
- decimal占用空间由宽度决定
- 可以存储比bigint更大的整数数据
五、SQL开发规范
A、建议使用预编译语句进行数据库操作
- 重复使用执行计划、减少编译所需时间
- 传递参数比传递SQL语句,减少网络IO
- 避免动态SQL导致的注入问题
mysql> PREPARE stmt-> FROM 'SELECT SQRT(POW(?,2) + POW(?, 2)) AS hypotenuse';
mysql> SET @a = 3;
mysql> SET @b = 4;
mysql> EXECUTE stmt USING @a, @b;
mysql> DEALLOCATE PREPARE stmt;
B、避免类型隐式转换
- 常见于WHERE从句,列类型与参数类型不一致,可能出现隐式转换
- 隐式转换导致索引失效
C、充分利用表中已存在的索引
- 避免使用双%的查询条件,如a like %.log%
- 避免使用前置%的查询条件;对于后置%,可以利用列上索引
- 一个SQL只能利用联合索引中的一列进行范围查询
- 使用LEFT JOIN或NOT EXISTS来优化NOT IN查询
D、程序连接不同数据库,需使用不同账号,禁止跨库查询
- 为数据库迁移和分库分表留出余地
- 减低业务耦合度
- 避免权限过大而产生的安全风险
E、禁止使用SELECT *进行查询
- 避免消耗CPU和网络IO
- TEXT类型还会进行二次读取
- 无法使用覆盖索引
- 减少表结构变更对程序带来的影响
F、禁止使用不含字段列表的INSERT语句
- 减少表结构变更对程序带来的影响
G、避免使用子查询
- 子查询结果集无法使用索引,结果集数据量大则严重影响效率
- 子查询会产生临时表,消耗CPU和IO资源,引起慢查询
- 子查询可读性更高,但是会影响性能,可以优化为JOIN操作
H、避免使用JOIN关联太多的表
- 每JOIN一个表会多占用关联内存(join_buffer_size)
- MySQL最多允许61个表,建议不超过5个
I、减少通数据库交互次数
- 数据库更适合批量操作
- 提高SQL处理效率
J、使用IN代替OR语句
- IN不要超过500个
- IN操作可以有效利用索引
K、禁止使用ORDER BY RAND()进行随机排序
- 会把所有符合条件的数据加载到内存中,进行排序
- 通过业务代码完成随机数据获取
L、禁止WHERE从句中对列进行函数转换和计算
- 导致索引失效,WHERE DATE(createtime) = '20180925'
- 可以变通SQL,继续使用列索引,WHERE createtime >= '20180925' AND createtime < '20180926'
M、(明显不会有重复值时)使用UNION ALL而不是UNION进行结果集合并
- UNION会把所有数据放入临时表进行去重操作
N、拆分复杂大SQL为多个小SQL进行查询
- MySQL不支持一个SQL的多CPU并行计算
- SQL拆分后可以通过并行执行提高处理效率
六、数据库操作行为规范(开发、运维)
A、对于超过百万行的批量写操作,需要分批多次进行操作
- binlog日志为row格式时会产生大量的日志
- 大批量写操作,可能会导致严重的主从延迟
- 涉及事务,对大量数据进行锁定,产生大量阻塞,导致可用链接被消耗
B、对于大表结构修改
- pt-online-schema-change工具进行修改
- TODO 原理
- 避免大表修改产生的主从延迟
- 避免对表字段修改时的锁表
C、禁止为程序使用账号赋予super权限(维护)
- 遵循最小权限原则
- 原则上不具有DROP权限
「MySQL」 - SQL设计规范相关推荐
- mysql 递归_「MySQL」 - SQL Cheat Sheet - 未完成
近几个月的心情真是安排的妥妥的,呈现W状.多的不说了,这里对SQL的测试进行简单梳理,制作一份SQL Cheat Sheet. 0x01.数据库基本架构 Clinet层 Server层 连接器 网络连 ...
- 「MySQL」从零到删库
目录 零.数据库的产生 什么是数据库 database 抛出问题,数据库的产生 数据库萌芽阶段的发展历程 CRUD 层次模型 网状模型 关系型数据库 企业和我们都选什么数据库呢? 详见:零.数据库的产 ...
- 「MySQL」电商“人货场”指标体系
本文你将学到: 如何搭建电商"人货场"指标体系 MySQL:留存率分析 MySQL:RFM模型分析 MySQL:用户行为路径分析 细心的同学可能会发现,这个符号的「标题」都是实战项 ...
- 「MySQL」- 复杂的SQL查询语句
任意门 前言 聚合查询 1.聚合函数 count函数 sum函数 avg函数 max函数 min函数 2.分组查询 having子句 多表查询 1.笛卡尔积 2.内连接 3.外连接 左外连接 右外连接 ...
- mysql @@rowcount_「rowcount」SQL Server中Rowcount与@@Rowcount的用法 - seo实验室
rowcount rowcount的用法: rowcount的作用就是用来限定后面的sql在返回指定的行数之后便停止处理,比如下面的示例, set rowcount 10 select * from ...
- mysql pk uk_「fk」SQL中PK、UK、DF、CK、FK的意思 - seo实验室
fk PK 主键 constraint primary key UK 唯一约束 DF 约束默认 constrint default for CK 检查约束 constraint check() FK ...
- 「数据库」sql刷题(No.11)
喜欢就 关注 我们吧! 简介: Hello 各位 ,我是公号「八点半技术站」的创作者 - Bruce.D (姓氏:豆). 感谢微信给予的个人认证,专注于PHP.Go.数据库技术领域知识经验分享. 技 ...
- 事务复制提示初始快照不可用_「MySQL」数据库事务深入分析
推荐阅读:吊打面试官!MySQL灵魂100问,你能答出多少? 一.前言 只有InnoDB引擎支持事务,下边的内容均以InnoDB引擎为默认条件 二.常见的并发问题 1.脏读 一个事务读取了另一个事务未 ...
- 「MySQL」- 基础增删改查
目录 前言 新增/插入 ( insert ) 查询 ( select ) 1. 查询所有列 2.查询指定列 3.查询表达式字段 4.查询字段指定别名 5.去重查询 6.排序查询 7.条件查询 条件运算 ...
最新文章
- 【bzoj3924】[Zjoi2015]幻想乡战略游戏 动态点分治
- xsd的unique验证
- 大话数据结构(十)java程序——队列
- es6 find 数组内查询用法
- JAVA spring配置文件总结
- tomcat配置https_「Java」 - Tomcat amp; 配置HTTPS
- 超越阿里云,华为云网络服务竟然这么厉害!
- burp放包_详解BurpSuite软件 请求包 HTTP (9.23 第十天)
- 使用arcgis进行夜间灯光数据处理
- 第1章 数据库系统概论---数据库原理及应用
- Keil开发环境安装教程
- 深入安卓Package Manager|Package Installer
- 计算机网络自顶向下方法华为路由器IPV6到IPV4到IPV6的隧道及实现两端主机通信
- 网络冗余备份之浮动路由
- 未明学院:通往管理层的“特快列车”管培生项目如何甄别?
- k8s pod删不掉
- Heidisql中如何解决MySqlServer go away问题
- 小程序码(getUnlimited,createQRCode)
- git master手动合并到develop
- 旷视科技计算机视觉算法研究员年薪,旷视科技算法研究员面经(21个问答)
热门文章
- window安装mysql5.7解压版(解决乱码问题)
- 完成了C++作业,本博客现在开始全面记录acm学习历程,真正的acm之路,现在开始
- 【mysql的编程专题⑥】视图
- 在Activity的Title中加入进度条
- 继续Bargaining
- sql注入_1-4_post盲注
- ❤️时间管理大师!我是如何规划自己的时间的?充分利用每一分一秒!❤️
- 2015年第六届蓝桥杯 - 省赛 - C/C++大学C组 - B. 立方尾不变
- 从源代码学Python系列目录
- Martix工作室考核题 —— 2019-3-8 第三题