my sql 使用规范

20
MySQL 使用规范 ——by 技术委员会

Upload: mask-wang

Post on 02-Jul-2015

283 views

Category:

Technology


0 download

TRANSCRIPT

Page 1: My sql 使用规范

MySQL 使用规范

——by 技术委员会

Page 2: My sql 使用规范

概述

• 以下规范适用在线交易(OLTP)系统的数据库。

• 数据仓库与分析系统也可以参考。

Page 3: My sql 使用规范

命名规范

• 表名、字段名、索引名使用小写字母、数字,采用下划线分割

• 表名、字段名不超过 32 个字符

• 存储实体数据的表,名称使用名词,单数

• 索引名称采用 idx_ 前缀,之后顺序跟随索引的字段名,字段名直接以下划线分割

• 不使用保留字

• 存储实体表间多对多对应关系的表,名称建议采用 noun_verb_noun 这样的模式。例如:member_like_property、property_has_tag。

Page 4: My sql 使用规范

命名规范

SQL 语句中,

• 保留字使用全大写• 字符串使用单引号(')

--正确SELECT id, title FROM xiaoqu WHERE id = 1 SELECT id, title FROM xiaoqu WHERE areacode = '000100010001'

--错误select ID, title from XiaoQu where id = 1 SELECT id, title FROM xiaoqu WHERE areacode = "000100010001"

Page 5: My sql 使用规范

表的设计MySQL 存储引擎使用 InnoDB不用纠结,没有特殊原因的情况下,作为 OLTP 的 MySQL 使用 InnoDB 引擎。

字符集使用 UTF-8Charset 为 utf8;Collation 为 utf8_general_ci。

正确使用时间类型MySQL 应当正确设置 time_zone。• 精确到秒的时间采用 TIMESTAMP• 精确到日期使用 DATE• 一般不使用 DATETIME 类型• 不允许使用字符串类型存储时间

Page 6: My sql 使用规范

表的设计字段定义为 NOT NULL真的需要 NULL 值吗?如果不确定,就将字段设置为 NOT NULL。

字段设置 DEFAULT 值设置为 NOT NULL 的字段,需要设置一个缺省值。

不使用浮点类型(FLOAT、DOUBLE)没有充分的理由,不要使用浮点数。

例如金额可以用分为单位,然后采用 INT。如果依然要以元为单位,可以采用DECIMAL。

Page 7: My sql 使用规范

表的设计字段个数不超过 32 个一个表有很多很多字段,是坏设计的味道。请再认真考虑设计是否正确。

不直接存储图片、音频、视频等大容量内容

请使用分布式文件系统来存储图片、音频、视频等内容。数据库里只存储文件的位置。

使用 INT UNSIGNED 来存储 IPv4 地址使用 INET_ATON 将 IP 地址的字符串形式转换成数字形式;使用 INET_NTOA 将 IP 地址数字形式转换成字符串形式,以便查看。

Page 8: My sql 使用规范

表的设计当要查询某段的 IP 时,请参考以下示例:

SELECT user_id FROM user_ipWHERE ip > INET_ATON('192.168.0.0') AND ip < INET_ATON('192.168.255.255')

当程序使用自带的函数进行 IP 地址的字符串形式与数字形式之间的转换时,需要注意数字的存储类型至少应为 32 位的无符号整型(如 uint32_t),并注意字节顺。

Page 9: My sql 使用规范

索引

使用数字主键存储实体数据的表,其主键应该是数字类型。

不使用联合主键存储实体数据的表,不使用联合主键。

存储实体表间多对多对应关系的表(仅有两个字段)允许例外。

不使用外键所有的表不建立外键约束。

Page 10: My sql 使用规范

索引

联合索引字段数不超过 5 个一个联合索引的字段数太多,很可能是设计得不好,还很难符合命名的规范。

前缀索引长度不超过 8 个字符对字符串类型的字段建立索引,采用前缀索引,且长度不超过 8 个字符。

Page 11: My sql 使用规范

SQL 语句禁止在查询条件中对字段进行数学运算、函数调用、隐式类型转换这类查询语句在使用索引时将非常困难。

-- 禁止SELECT id FROM property WHERE NOW() - update_time < 3600SELECT id FROM property WHERE update_time + 3600 > NOW()

-- 改为SELECT id FROM property WHERE update_time > NOW() - 3600

Page 12: My sql 使用规范

SQL 语句-- 禁止SELECT id FROM property WHERE CHAR_LENGTH(title) > 20

-- 假设字段 property.status 的类型为 TINYINT-- 禁止SELECT id FROM property WHERE status = '1'

-- 改为SELECT id FROM property WHERE status = 1

Page 13: My sql 使用规范

SQL 语句禁止隐式类型转换不仅在查询条件中禁止隐示类型转换,INSERT,UPDATE 也不允许隐式类型转换。

-- 假设字段 property.status 的类型为 TINYINT-- 禁止INSERT INTO property (..., status) VALUES (..., '1')UPDATE property SET status = '1' WHERE id = '43'

-- 改为INSERT INTO property (..., status) VALUES (..., 1)UPDATE property SET status = 1 WHERE id = 43

Page 14: My sql 使用规范

SQL 语句禁止使用 % 前导查询尽量不使用 LIKE 查询,不得不用的情况下也禁止使用 % 前导查询。

-- 禁止SELECT id FROM property WHERE title LIKE '%最%‘

不使用联表查询OLTP 不使用 JOIN 联合查询。

不使用子查询没有特别好的理由,OLTP 不允许使用子查询。

Page 15: My sql 使用规范

SQL 语句不使用负向查询负向查询是指,如果查询条件描述的是不要什么数据,其余的都要。例如 !=、<>、NOT EXISTS、NOT IN 以及 NOT LIKE 等就是负向查询,它们利用索引将会很辛苦。

一次查询的结果集不超过 100 行必要时使用 LIMIT 100

Page 16: My sql 使用规范

SQL 语句LIMIT m, n,其中 m 应当小于 500使用 SELECT ... LIMIT offset, row_count 或者 SELECT ... LIMIT row_count OFFSET offset时,当 offset 小于 500 时,允许使用。

-- 允许SELECT ... FROM property WHERE broker_id=? ORDER BY update_time LIMIT 40, 20-- 不允许SELECT ... FROM property WHERE areacode=? ORDER BY update_time LIMIT 4000, 20

Page 17: My sql 使用规范

SQL 语句能够不使用 offset 的情况应当避免,如下面的例子(其中 id 是主键),

-- 建议SELECT ... FROM property WHERE broker_id=? AND id>? ORDER BY id LIMIT 20-- 避免SELECT ... FROM property WHERE broker_id=? ORDER BY id LIMIT 40, 20

Page 18: My sql 使用规范

SQL 语句避免使用 COUNT() 函数能不使用就不使用,尽量用其他方法来解决。例如判断经纪人是否有房源,可以不使用 COUNT() 函数,

-- 正确SELECT 1 FROM propertys WHERE broker_id=? LIMIT 1

-- 错误SELECT COUNT(*) FROM propertys WHERE broker_id=?

Page 19: My sql 使用规范

SQL 语句一次 COUNT() 可能扫描的行数应当确保小于 500 行COUNT() 函数需要扫描所有的结果集之后才能得出结果。而结果集的大小需要业务知识来判断(EXPLAIN 方法只能来来检验某一个条件下的当前情况)。因此需要使用 COUNT() 查询的代码应当经过审阅。

-- 允许。审阅。经纪人的房源数不允许超过 200 套SELECT COUNT(*) FROM property WHERE broker_id=?

-- 不允许。一个区域板块下的房源数量不定,可能非常多SELECT COUNT(*) FROM property WHERE areacode=?

其他聚合函数,例如 SUM()、AVG()、MAX() 等,同样适用。

Page 20: My sql 使用规范

SQL 语句统一使用 COUNT(*) 而不是 COUNT(1)当统计行数时,

• 统一使用 COUNT(*) 而不是 COUNT(1)。• 不使用 COUNT(PK) 或 COUNT(column),除非真的是想统计 Nullable 字段的行数。