一、数据库命名规范

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设计规范相关推荐

  1. mysql 递归_「MySQL」 - SQL Cheat Sheet - 未完成

    近几个月的心情真是安排的妥妥的,呈现W状.多的不说了,这里对SQL的测试进行简单梳理,制作一份SQL Cheat Sheet. 0x01.数据库基本架构 Clinet层 Server层 连接器 网络连 ...

  2. 「MySQL」从零到删库

    目录 零.数据库的产生 什么是数据库 database 抛出问题,数据库的产生 数据库萌芽阶段的发展历程 CRUD 层次模型 网状模型 关系型数据库 企业和我们都选什么数据库呢? 详见:零.数据库的产 ...

  3. 「MySQL」电商“人货场”指标体系

    本文你将学到: 如何搭建电商"人货场"指标体系 MySQL:留存率分析 MySQL:RFM模型分析 MySQL:用户行为路径分析 细心的同学可能会发现,这个符号的「标题」都是实战项 ...

  4. 「MySQL」- 复杂的SQL查询语句

    任意门 前言 聚合查询 1.聚合函数 count函数 sum函数 avg函数 max函数 min函数 2.分组查询 having子句 多表查询 1.笛卡尔积 2.内连接 3.外连接 左外连接 右外连接 ...

  5. mysql @@rowcount_「rowcount」SQL Server中Rowcount与@@Rowcount的用法 - seo实验室

    rowcount rowcount的用法: rowcount的作用就是用来限定后面的sql在返回指定的行数之后便停止处理,比如下面的示例, set rowcount 10 select * from ...

  6. 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 ...

  7. 「数据库」sql刷题(No.11)

    喜欢就 关注 我们吧! 简介:  Hello 各位 ,我是公号「八点半技术站」的创作者 - Bruce.D (姓氏:豆). 感谢微信给予的个人认证,专注于PHP.Go.数据库技术领域知识经验分享. 技 ...

  8. 事务复制提示初始快照不可用_「MySQL」数据库事务深入分析

    推荐阅读:吊打面试官!MySQL灵魂100问,你能答出多少? 一.前言 只有InnoDB引擎支持事务,下边的内容均以InnoDB引擎为默认条件 二.常见的并发问题 1.脏读 一个事务读取了另一个事务未 ...

  9. 「MySQL」- 基础增删改查

    目录 前言 新增/插入 ( insert ) 查询 ( select ) 1. 查询所有列 2.查询指定列 3.查询表达式字段 4.查询字段指定别名 5.去重查询 6.排序查询 7.条件查询 条件运算 ...

最新文章

  1. 【bzoj3924】[Zjoi2015]幻想乡战略游戏 动态点分治
  2. xsd的unique验证
  3. 大话数据结构(十)java程序——队列
  4. es6 find 数组内查询用法
  5. JAVA spring配置文件总结
  6. tomcat配置https_「Java」 - Tomcat amp; 配置HTTPS
  7. 超越阿里云,华为云网络服务竟然这么厉害!
  8. burp放包_详解BurpSuite软件 请求包 HTTP (9.23 第十天)
  9. 使用arcgis进行夜间灯光数据处理
  10. 第1章 数据库系统概论---数据库原理及应用
  11. Keil开发环境安装教程
  12. 深入安卓Package Manager|Package Installer
  13. 计算机网络自顶向下方法华为路由器IPV6到IPV4到IPV6的隧道及实现两端主机通信
  14. 网络冗余备份之浮动路由
  15. 未明学院:通往管理层的“特快列车”管培生项目如何甄别?
  16. k8s pod删不掉
  17. Heidisql中如何解决MySqlServer go away问题
  18. 小程序码(getUnlimited,createQRCode)
  19. git master手动合并到develop
  20. 旷视科技计算机视觉算法研究员年薪,旷视科技算法研究员面经(21个问答)

热门文章

  1. window安装mysql5.7解压版(解决乱码问题)
  2. 完成了C++作业,本博客现在开始全面记录acm学习历程,真正的acm之路,现在开始
  3. 【mysql的编程专题⑥】视图
  4. 在Activity的Title中加入进度条
  5. 继续Bargaining
  6. sql注入_1-4_post盲注
  7. ❤️时间管理大师!我是如何规划自己的时间的?充分利用每一分一秒!❤️
  8. 2015年第六届蓝桥杯 - 省赛 - C/C++大学C组 - B. 立方尾不变
  9. 从源代码学Python系列目录
  10. Martix工作室考核题 —— 2019-3-8 第三题