MySQL 开发规范

库名、表名、字段名必须使用小写字母,“_”分割。

库名、表名、字段名必须不超过 12 个字符。

库名、表名、字段名见名知意,建议使用名词而不是动词。

建议使用 InnoDB 存储引擎。

存储精确浮点数必须使用 DECIMAL 替代 FLOAT 和 DOUBLE。

建议使用 UNSIGNED 存储非负数值。

建议使用 INT UNSIGNED 存储 IPV4。

整形定义中不添加长度,比如使用 INT,而不是 INT(4)。

使用短数据类型,比如取值范围为 0-80 时,使用 TINYINT UNSIGNED。

不建议使用 ENUM 类型,使用 TINYINT 来代替。

尽可能不使用 TEXT、BLOB 类型。

VARCHAR(N),N 表示的是字符数不是字节数,比如 VARCHAR(255),可以最大可存

储 255 个汉字,需要根据实际的宽度来选择 N。

VARCHAR(N),N 尽可能小,因为 MySQL 一个表中所有的 VARCHAR 字段最大长度

是 65535 个字节,进行排序和创建临时表一类的内存操作时,会使用 N 的长度申请内存。

表字符集选择 UTF8。

使用 VARBINARY 存储变长字符串。

存储年使用 YEAR 类型。

存储日期使用 DATE 类型。

存储时间(精确到秒)建议使用 TIMESTAMP 类型,因为 TIMESTAMP 使用 4 字节, DATETIME 使用 8 个字节。

建议字段定义为 NOT NULL。

将过大字段拆分到其他表中。

禁止在数据库中使用 VARBINARY、BLOB 存储图片、文件等。

表结构变更需要通知 DBA 审核。

二、 索引

非唯一索引必须按照“idx_字段名称_字段名称[_字段名]”进行命名。

唯一索引必须按照“uniq_字段名称_字段名称[_字段名]”进行命名。

索引名称必须使用小写。

索引中的字段数建议不超过 5 个。

单张表的索引数量控制在 5 个以内。

唯一键由 3 个以下字段组成,并且字段都是整形时,使用唯一键作为主键。

没有唯一键或者唯一键不符合 5 中的条件时,使用自增(或者通过发号器获取)id 作为

主键。

唯一键不和主键重复。

索引字段的顺序需要考虑字段值去重之后的个数,个数多的放在前面。

ORDER BY,GROUP BY,DISTINCT 的字段需要添加在索引的后面。

使用 EXPLAIN 判断 SQL 语句是否合理使用索引,尽量避免 extra 列出现:Using File

Sort,Using Temporary。

UPDATE、DELETE 语句需要根据 WHERE 条件添加索引。

不建议使用%前缀模糊查询,例如 LIKE “%weibo”。

对长度过长的 VARCHAR 字段建立索引时,添加 crc32 或者 MD5 Hash 字段,对 Hash 字段建立索引。

合理创建联合索引(避免冗余),(a,b,c) 相当于 (a) 、(a,b) 、(a,b,c)。 合理利用覆盖索引。
SQL 变更需要确认索引是否需要变更并通知 DBA。

三、 SQL 语句

使用 prepared statement,可以提供性能并且避免 SQL 注入。
SQL 语句中 IN 包含的值不应过多。
UPDATE、DELETE 语句不使用 LIMIT。
WHERE 条件中必须使用合适的类型,避免 MySQL 进行隐式类型转化。
SELECT 语句只获取需要的字段。

SELECT、INSERT 语句必须显式的指明字段名称,不使用 SELECT *,不使用 INSERT INTO table()。

使用 SELECT column_name1, column_name2 FROM table WHERE [condition]而 不是 SELECT column_name1 FROM table WHERE [condition]和 SELECT column_name2 FROM table WHERE [condition]。

WHERE 条件中的非等值条件(IN、BETWEEN、<、<=、>、>=)会导致后面的条件 使用不了索引。

避免在 SQL 语句进行数学运算或者函数运算,容易将业务逻辑和 DB 耦合在一起。

INSERT 语句使用 batch 提交(INSERT INTO table VALUES(),(),()…),values 的个

数不应过多。
避免使用存储过程、触发器、函数等,容易将业务逻辑和 DB 耦合在一起,并且 MySQL

的存储过程、触发器、函数中存在一定的 bug。 避免使用 JOIN。

使用合理的 SQL 语句减少与数据库的交互次数。
不使用 ORDER BY RAND(),使用其他方法替换。
建议使用合理的分页方式以提高分页的效率。
统计表中记录数时使用 COUNT(*),而不是 COUNT(primary_key)和 COUNT(1)。 禁止在从库上执行后台管理和统计类型功能的 QUERY。

四、 散表

每张表数据量建议控制在 5000w 以下。
可以结合使用 hash、range、lookup table 进行散表。
散表如果使用 md5(或者类似的 hash 算法)进行散表,表名后缀使用 16 进制,比如

user_ff。
推荐使用 CRC32 求余(或者类似的算术算法)进行散表,表名后缀使用数字,数字必

须从 0 开始并等宽,比如散 100 张表,后缀从 00-99。 使用时间散表,表名后缀必须使用特定格式,比如按日散表 user_20110209、按月散表

user_201102。

五、 其他

批量导入、导出数据需要 DBA 进行审查,并在执行过程中观察服务。

批量更新数据,如 update,delete 操作,需要 DBA 进行审查,并在执行过程中观察服

务。

产品出现非数据库平台运维导致的问题和故障时,如前端被抓站,请及时通知 DBA,便 于维护服务稳定。

业务部门程序出现 bug 等影响数据库服务的问题,请及时通知 DBA,便于维护服务稳定。 业务部门推广活动,请提前通知 DBA 进行服务和访问评估。 如果出现业务部门人为误操作导致数据丢失,需要恢复数据,请在第一时间通知 DBA,

并提供准确时间,误操作语句等重要线索。



FAQ 1-1.库名、表名、字段名必须使用小写字母,“_”分割。

a) MySQL 有配置参数 lower_case_table_names,不可动态更改,linux 系统默认为 0,即库表名以 实际情况存储,大小写敏感。如果是 1,以小写存储,大小写不敏感。如果是 2,以实际情况存储, 但以小写比较。

b) 如果大小写混合用,可能存在 abc,Abc,ABC 等多个表共存,容易导致混乱。
c) 字段名显示区分大小写,但实际使用不区分,即不可以建立两个名字一样但大小写不一样的字段。

d) 为了统一规范, 库名、表名、字段名使用小写字母。

back

1-2.库名、表名、字段名必须不超过 12 个字符。
库名、表名、字段名支持最多 64 个字符,但为了统一规范、易于辨识以及减少传输量,必须不超过

12 字符。

back

1-3.库名、表名、字段名见名知意,建议使用名词而不是动词。

a) 用户评论可用表名 usercomment 或者 comment。

b) 库表是一种客观存在的事物,一种对象,所以建议使用名词。

back

1-4.建议使用 InnoDB 存储引擎。

a) 5.5 以后的默认引擘,支持事务,行级锁,更好的恢复性,高并发下性能更好,对多核,大内存, ssd 等硬件支持更好。

b) 具体比较可见附件的官方白皮书。

back

1-5.存储精确浮点数必须使用 DECIMAL 替代 FLOAT 和 DOUBLE。

a) mysql 中的数值类型(不包括整型):

IEEE754 浮点数: float (单精度) , double 或 real (双精度)
定点数: decimal 或 numeric
单精度浮点数的有效数字二进制是 24 位,按十进制来说,是 8 位;双精度浮点数的有效数字二进

制是 53 位,按十进制来说,是 16 位
一个实数的有效数字超过 8 位,用单精度浮点数来表示的话,就会产生误差!同样,如果一个实

数的有效数字超过 16 位,用双精度浮点数来表示,也会产生误差
b) IEEE754 标准的计算机浮点数,在内部是用二进制表示的,但在将一个十进制数转换为二进制浮 点数时,也会造成误差,原因是不是所有的数都能转换成有限长度的二进制数。

即一个二进制可以准确转换成十进制,但一个带小数的十进制不一定能够准确地用二进制来表示。

实例:
drop table if exists t;

create table t(value float(10,2));

insert into t values(131072.67),(131072.68);

select value from t; ±----------+
| value |

±----------+

| 131072.67 |
| 131072.69 |
±----------+
back
1-6.建议使用 UNSIGNED 存储非负数值。
同样的字节数,存储的数值范围更大。如 tinyint 有符号为 -128-127,无符号为 0-255 back

1-7. 如何使用 INT UNSIGNED 存储 ip?
使用 INT UNSIGNED 而不是 char(15)来存储 ipv4 地址,通过 MySQL 函数 inet_ntoa 和 inet_aton

来进行转化。Ipv6 地址目前没有转化函数,需要使用 DECIMAL 或者两个 bigINT 来存储。例如: SELECT INET_ATON(‘209.207.224.40’);
3520061480
SELECT INET_NTOA(3520061480);

209.207.224.40

back

1-8. INT[M],M 值代表什么含义?

注意数值类型括号后面的数字只是表示宽度而跟存储范围没有关系,比如 INT(3)默认显示 3 位,空 格补齐,超出时正常显示,python、java 客户端等不具备这个功能。

back

1-10.不建议使用 ENUM、SET 类型,使用 TINYINT 来代替。

a) ENUM,有三个问题:添加新的值要做 DDL,默认值问题(将一个非法值插入 ENUM(也就是说, 允许的值列之外的字符串),将插入空字符串以作为特殊错误值),索引值问题(插入数字实际是插入 索引对应的值)

实例:
drop table if exists t;
create table t(sex enum(‘0’,‘1’)); insert into t values(1);
insert into t values(‘3’);
select * from t;
±-----+
|sex |

±-----+

|0|

||

±-----+

2 rows in set (0.00 sec)

back

1-11.尽可能不使用 TEXT、BLOB 类型。

a) 索引排序问题,只能使用 max_sort_length 的长度或者手工指定 ORDER BY SUBSTRING(column, length)的长度来排序

b) Memory 引擘不支持 text,blog 类型,会在磁盘上生成临时表 c) 可能浪费更多的空间
d) 可能无法使用 adaptive hash index
e) 导致使用 where 没有索引的语句变慢

back

1-13. VARCHAR 中会产生额外存储吗?

VARCHAR(M),如果 M<256 时会使用一个字节来存储长度,如果 M>=256 则使用两个字节来存储

长度。

back

1-14.表字符集选择 UTF8。

a) 使用 utf8 字符集,如果是汉字,占 3 个字节,但 ASCII 码字符还是 1 个字节。
b) 统一,不会有转换产生乱码风险
c) 其他地区的用户(美国、印度、台湾)无需安装简体中文支持,就能正常看您的文字,并且不会 出现乱码
d) ISO-8859-1 编码(latin1)使用了单字节内的所有空间,在支持 ISO-8859-1 的系统中传输和存储 其他任何编码的字节流都不会被抛弃。即把其他任何编码的字节流当作 ISO-8859-1 编码看待都没有 问题,保存的是原封不动的字节流。

back

1-15.使用 VARBINARY 存储变长字符串。

二进制字节流,不存在编码问题
back

1-18. 为什么建议使用 TIMESTAMP 来存储时间而不是 DATETIME?

DATETIME 和 TIMESTAMP 都是精确到秒,优先选择 TIMESTAMP,因为 TIMESTAMP 只有 4 个字 节,而 DATETIME8 个字节。同时 TIMESTAMP 具有自动赋值以及自动更新的特性。

如何使用 TIMESTAMP 的自动赋值属性?

a)

b)

将当前时间作为 ts 的默认值:ts TIMESTAMP DEFAULT CURRENT_TIMESTAMP。 当行更新时,更新 ts 的值:ts TIMESTAMP DEFAULT 0 ON UPDATE CURRENT_TIMESTAMP。

c) CURRENT_TIMESTAMP。

可以将 1 和 2 结合起来:ts TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE

back

1-19.建议字段定义为 NOT NULL。

a)如果 null 字段被索引,需要额外的 1 字节 b)使索引,索引统计,值的比较变得更复杂 c)可用 0,’'代替 d)如果是索引字段,一定要定义为 not null back

1-21.禁止在数据库中使用 VARBINARY、BLOB 存储图片、文件等。 采用分布式文件系统更高效
back
2. 为什么 MySQL 的性能依赖于索引?

MySQL 的查询速度依赖良好的索引设计,因此索引对于高性能至关重要。合理的索引会加快查询速

度(包括 UPDATE 和 DELETE 的速度,MySQL 会将包含该行的 page 加载到内存中,然后进行 UPDATE 或者 DELETE 操作),不合理的索引会降低速度。

MySQL 索引查找类似于新华字典的拼音和部首查找,当拼音和部首索引不存在时,只能通过一页一 页的翻页来查找。当 MySQL 查询不能使用索引时,MySQL 会进行全表扫描,会消耗大量的 IO。

back

2-5. 为什么一张表中不能存在过多的索引?

InnoDB 的 secondary index 使用 b+tree 来存储,因此在 UPDATE、DELETE、INSERT 的时候需 要对 b+tree 进行调整,过多的索引会减慢更新的速度。

back

2-11. EXPLAIN 语句

EXPLAIN 语句(在 MySQL 客户端中执行)可以获得 MySQL 如何执行 SELECT 语句的信息。通过 对 SELECT 语句执行 EXPLAIN,可以知晓 MySQL 执 行该 SELECT 语句时是否使用了索引、全表扫 描、临时表、排序等信息。尽量避免 MySQL 进行全表扫描、使用临时表、排序等。详见官方文档。

back

2-13.不建议使用%前缀模糊查询,例如 LIKE “%weibo”。

会导致全表扫描

2-14. 如何对长度大于 50 的 VARCHAR 字段建立索引?

下面的表增加一列 url_crc32,然后对 url_crc32 建立索引,减少索引字段的长度,提高效率。

CREATE TABLE url(

url VARCHAR(255) NOT NULL DEFAULT 0, url_crc32 INT UNSIGNED NOT NULL DEFAULT 0,

index idx_url(url_crc32) )

back

2-16. 什么是覆盖索引?

InnoDB 存储引擎中,secondary index(非主键索引)中没有直接存储行地址,存储主键值。如果 用户需要查询 secondary index 中所不包含的数据列时,需要先通过 secondary index 查找到主键 值,然后再通过主键查询到其他数据列,因此需要查询两次。

覆盖索引的概念就是查询可以通过在一个索引中完成,覆盖索引效率会比较高,主键查询是天然的覆 盖索引。

合理的创建索引以及合理的使用查询语句,当使用到覆盖索引时可以获得性能提升。
比如 SELECT email,uid FROM user_email WHERE uid=xx,如果 uid 不是主键,适当时候可以将

索引添加为 index(uid,email),以获得性能提升。

back

3-3.UPDATE、DELETE 语句不使用 LIMIT。

a) 可能导致主从数据不一致

b) 会记录到错误日志,导致日志占用大量空间

3-4. 为什么需要避免 MySQL 进行隐式类型转化?

因为 MySQL 进行隐式类型转化之后,可能会将索引字段类型转化成=号右边值的类型,导致使用不 到索引,原因和避免在索引字段中使用函数是类似的。

back

3-6. 为什么不建议使用 SELECT *?

增加很多不必要的消耗(cpu、io、内存、网络带宽);增加了使用覆盖索引的可能性;当表结构发 生改变时,前段也需要更新。

back

3-13. 如何减少与数据库的交互次数?

使用下面的语句来减少和 db 的交互次数:

INSERT … ON DUPLICATE KEY UPDATE

REPLACE

INSERT IGNORE

INSERT INTO values(),()如何结合使用多个纬度进行散表散库?

例如微博 message,先按照 crc32(message_id)%16 将 message 散到 16 个库中,然后针对每个库 中的表,一天生成一张新表。

back

3-14. 为什么不能使用 ORDER BY rand()?

因为 ORDER BY rand()会将数据从磁盘中读取,进行排序,会消耗大量的 IO 和 CPU,可以在程序 中获取一个 rand 值,然后通过在从数据库中获取对应的值。

back

3-15. MySQL 中如何进行分页?

假如有类似下面分页语句:
SELECT * FROM table ORDER BY TIME DESC LIMIT 10000,10; 这种分页方式会导致大量的 io,因为 MySQL 使用的是提前读取策略。 推荐分页方式:

SELECT * FROM table WHERE TIME<last_TIME ORDER BY TIME DESC LIMIT 10.

SELECT * FROM table inner JOIN(SELECT id FROM table ORDER BY TIME LIMIT 10000,10) as t USING(id)

back

3-17.为什么避免使用复杂的 SQL?

拒绝使用复杂的 SQL,将大的 SQL 拆分成多条简单 SQL 分步执行。原因:简单的 SQL 容易使用到 MySQL 的 query cache;减少锁表时间特别是 MyISAM;可以使用多核 cpu。

back

  1. InnoDB 存储引擎为什么避免使用 COUNT(*)?

InnoDB 表避免使用 COUNT(*)操作,计数统计实时要求较强可以使用 memcache 或者 redis,非实 时统计可以使用单独统计表,定时更新。

微博Mysql数据库规范相关推荐

  1. MySQL 数据库规范--调优篇(终结篇)

    前言 这篇是MySQL 数据库规范的最后一篇--调优篇,旨在提供我们发现系统性能变弱.MySQL系统参数调优,SQL脚本出现问题的精准定位与调优方法. 目录 1.MySQL 调优金字塔理论 2.MyS ...

  2. MySQL数据库规范

    MySQL数据库规范 前言 今天我们来聊一聊MySQL数据库常见的一些建议设计规范,参考阿里的<JAVA开发手册泰山版>,我们简单挑出几处进行简单分析和回顾复习,如果有不正确或者不足的地方 ...

  3. 新华字典 mysql数据库_mysql系列一、mysql数据库规范

    一. 表设计 库名.表名.字段名必须使用小写字母,"_"分割. 库名.表名.字段名必须不超过12个字符. 库名.表名.字段名见名知意,建议使用名词而不是动词. 表必须使用InnoD ...

  4. MySQL数据库规范及解读

    一.基础规范 第一条:必须使用InnoDB存储引擎 解读:支持事务.行级锁.并发性能更好.CPU及内存缓存页优化使得资源利用率更高 第二条:必须使用utf8(utf8mb4)字符集 解读:万国码,无需 ...

  5. 推荐:新浪微博,腾讯微博 mysql数据库主表设计

    用户信息表(t_user_info) 字段名称 字节数 类型 描述 User_id 4 uint32 用户编号(主键) User_name 20 Char[20] 名称 Msg_count 4 uin ...

  6. 新浪微博,腾讯微博mysql数据库主表猜想

    用户信息表(t_user_info) 字段名称 字节数 类型 描述 User_id 4 uint32 用户编号(主键) User_name 20 Char[20] 名称 Msg_count 4 uin ...

  7. mysql 微博 数据表_推荐:新浪微博,腾讯微博 mysql数据库主表设计

    用户信息表(t_user_info) 字段名称 字节数 类型 描述 User_id 4 uint32 用户编号(主键) User_name 20 Char[20] 名称 Msg_count 4 uin ...

  8. mysql 数据库设计说明书_1.2 Mysql 数据库规范

    ## 1.数据库版本 1. mysql 5.6以上 ## 2.数据库排序规则 1. utf_general_ci ## 3. 命名规则 **_一律使用小写字母+数字_** 1.数据库命名规范 数据库, ...

  9. MySQL 数据库规范--开发篇

    1.sql语句编写 1.执行大的delete.update.insert操作要慎重,特别是对业务繁忙的系统,要尽量避免对线上业务产生影响. 解决办法是:大操作切割为小操作,使用limit子句限制每次操 ...

  10. mysql数据库:最全MySQL数据库设计建库、建表规范及经验(踩过坑才能积累经验!)

    废话 这两天还是在做刚接手的小项目,也是第一次一个人负责整个项目的所有流程,最后交给客户. 当自己去接触项目时,真的会踩很多很多坑,当然解决了就是很大的进步与成长.昨晚我就意识到自己给自己留了一个大坑 ...

最新文章

  1. YYAsyncLayer 学习
  2. linux切换到顶层命令,一些在Linux下提高工作效率的常用命令
  3. Python- 反射 及部份内置属性方法
  4. Segmentation fault到底是何方妖孽
  5. 【SHARE】WEB前端学习资料
  6. OSPF 邻接关系建立
  7. Java并发编程之堵塞队列介绍以及SkipList(跳表)
  8. docker 部署rabbitmq,k8s部署rabbitmq集群,跟踪和监控rabbitmq
  9. vue项目跨域问题完全解决
  10. 不收费的数据恢复软件好用吗?数据丢失这样恢复
  11. CDD数据库文件制作(三)——DID
  12. AD高级培训PPT总结
  13. (微信小程序)页面导航
  14. 2019年2月1日训练日记
  15. php批量获得经纬度,批量调用百度地图API获取地址经纬度坐标
  16. unity 可视化渲染管线_如何为高端可视化设置Unity的高清渲染管道
  17. HTML5——如何在网页中加入图片和超链接。
  18. vue中的插槽--slot和v-slot
  19. js 获取与设置cookie
  20. Andriod 显式启动、隐式启动练习简析

热门文章

  1. Pandas 库之 DataFrame
  2. 手机序列号和IMEI号的区别
  3. 哪种硬盘坏道检测工具最好,有硬盘坏道怎么修复
  4. 【邢不行|量化小讲堂系列05-Python量化入门】计算创业板平均市盈率
  5. 一周信创舆情观察(5.6~5.9)
  6. html5多重阴影怎么设置,使用CSS3 box-shadow属性实现按钮的多重阴影效果
  7. MacBook 快捷键
  8. 如何查计算机配件的配置,如何查看电脑配置信息?教你四种方法
  9. 计算机应用基础输入法教案,计算机应用基础教案第二讲:五笔字型输入法(中职教育).doc...
  10. 字体设计符号组合多功能微信小程序源码