Author:sakte
Time:2013/02/27
mysql开发规范文档
1.mysql数据库命名规范
2.表结构设计、数据类型选择
3.开发注意事项
1.mysql数据库命名规范
1.1 命名规范:
Table/view/procedure/function/package:
object类型简称+功能模块简称的小写字母+“_”+业务意义小写单词,如:
主键/外键/索引:
object类型简称+”_”+表名简称+字段名
object类型简称:
Table:t
View:v
Procedure:p
Function:fn
Package:pk
主键 :pk
外键 :fk
索引 :idx
Eg:
Trader后台功能:tbk_operate_log
搜索功能表:ts_operate_log
索引命令:idx_tablename_column
2.表结构设计、数据类型选择
2.1 常用数据类型:
整型:tinyint,smallint,mediumint,int,bigint。一般int就够用了
浮点型:DECIMAL(M,D)精准,不建议用DECIMAL,建议乘以固定倍数转换成整数存储,可以节省存储空间,且不会带来任何附加维护成本
字符型:varchar,char,ENUM和SET,text
字符列选择类型时,尽量不要使用TEXT数据类型,lob类型更是要坚决杜绝,仅当字符数超过20000时,可以采用text类型,且所有使用text类型的字段,必须和原表拆分,与原表主键单独存储在另外一个表里。它的处理方式决定了它的性能要低于char或者是varchar类型的处理。定长字段,建议使用CHAR类型,不定长字段尽量使用VARCHAR,且仅仅设定适当的最大长度,而不是非常随意的给一个很大的最大长度限定,因为不同的长度范围,MySQL也会有不一样的存储处理。对于状态字段,可以采用char类型,也可以尝试使用ENUM来存放,因为可以极大的降低存储空间,而且即使需要增加新的类型,只要增加于末尾,修改结构也不需要重建表数据。如果是存放可预先定义的属性数据呢?可以尝试使用SET类型,即使存在多种属性,同样可以游刃有余,同时还可以节省不小的存储空间。
日期时间:常用TIMESTAMP,date
需要精确(年月日时分秒)的时间字段,可以使用datetime,timestamp ;如果时间字段只需要精确到天,那就用date类型
2.2 表结构基本设计:
2.2.1.字段字段使用not null:
MySQL NULL类型和Oracle的NULL有差异,会进入索引中,如果是一个组合索引,那么这个NULL类型的字段会极大影响整个索引的效率。此外,NULL 在索引中的处理也是特殊的,也会占用额外的存放空间
2.2.2.适当的拆分/冗余
A.当我们的表中存在类似于 TEXT 或者是很大的 VARCHAR类型的大字段的时候,如果我们大部分访问这张表的时候都不需要这个字段,我们就该义无反顾的将其拆分到另外的独立表中,以减少常用数据所占用的存储空间。这样做的一个明显好处就是每个数据块中可以存储的数据条数可以大大增加,既减少物理 IO 次数,也能大大提高内存中的缓存命中率。
B.被频繁引用且只能通过Join 2张(或者更多)大表的方式才能得到的独立小字段,这样的场景由于每次Join仅仅只是为了取得某个小字段的值,Join到的记录又大,会造成大量不必要的IO,完全可以通过空间换取时间的方式来优化。不过,冗余的同时需要确保数据的一致性不会遭到破坏,确保更新的同时冗余字段也被更新。
2.2.3.控制表的大小
mysql在处理大表(char的表>500W行,或int表>1000W)时,性能就开始明显降低,所以要采用不同的方式控制单表容量
A:根据数据冷热,对数据分级存储,历史归档
B:采用分库/分表/分区表,横向拆分控制单表容量
C:对于OLTP系统,控制单事务的资源消耗,遇到大事务可以拆解,采用化整为零模式,避免特例影响大众
D:单库不要超过500个表
E:单表字段数不要太多,最多不要大于50个
2.2.4.表的定义参数
mysql> show create table utf8\G;
*************************** 1. row ***************************
Table: utf8
Create Table: CREATE TABLE `utf8` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(10) DEFAULT NULL,
`createtime` timestamp NULL DEFAULT NULL,
`istrue` tinyint(4) DEFAULT '1',
`a` decimal(10,0) DEFAULT NULL,
`b` decimal(10,4) DEFAULT NULL,
`c` datetime DEFAULT NULL,
`d` date DEFAULT NULL,
`e` enum('a','b','c') DEFAULT NULL,
`f` set('a','b','c') DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `name_UNIQUE` (`name`),
UNIQUE KEY `createtime_UNIQUE` (`createtime`)
) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=utf8 ROW_FORMAT=dynamic
engine:根据自己的业务需要选择合适的存储引擎,一般事务表选择innodb,只读表选择myisam
AUTO_INCREMENT:自增列的初始化值
CHARSET:根据自己业务需求,定义表的字符集,对于多种语言环境选择utf8
ROW_FORMAT:行的存储格式
说明:
mysql文件存储格式
antelope
Barracuda
mysql行存储格式
antelope:提供compact和redundant两种行格式,redundant为兼容之前版本保留的。默认情况下保存的格式为compact格式
Barracuda:Innodb plugin引入新的文件格式,Barracuda文件格式包含两种新的行记录格式:Dynamic和Compressed。Compressed对于字符类型数据有很好压缩功能,可以提高效率
2.2.5.创建合适所索引
索引需要额外的维护成本、访问成本和空间成本,所以创建索引一定要谨慎,使单个索引尽量覆盖多的sql,更新频率比较高的表要控制索引的数量。
A. 对于非常大更新量的数据,索引的维护成本会非常高,如果其检索需求很少,而且对检索效率并没有非常高的要求的时候,并不建议创建索引,或者是尽量减少索引。
B. 对于数据量极小到通过索引检索还不如直接遍历来得快的数据,也并不适合使用索引。
C. 应该尽量让查找条件尽可能多的在索引中,尽可能通过索引完成所有过滤,回表只是取出额外的数据字段。
D. 字段的顺序对组合索引效率有至关重要的作用,过滤效果越好的字段需要更靠前
E. 需要读取的数据量占整个数据量的比例较大或者说索引的过滤效果并不是太好的时候,使用索引并不一定优于全表扫描。
F. 在实际使用过程中,一次数据访问一般只能利用1个索引,这一点在索引创建过程中一定要注意,不是说一条SQL语句中Where子句里面每个条件都有索引能对应上就可以了.
G.在高并发环境不要使用外键,太容易产生死锁,应由程序保证约束
H.字符字段必须使用前缀索引。
3. 开发注意事项
3.1 不在索引列上进行数学运算或函数运算
3.2 避免大sql,拆解多个小sql
3.3 避免是用select *
3.4 用in() /union替换or,并注意in的个数小于300
3.5 避免使用%前缀模糊前缀查询
3.6 避免使用子查询
----end----