数据库设计规范|数据库设计三大规范( 二 )


【建议】存储金钱的字段,建议用int,程序端乘以100和除以100进行存取 。因为int占用4字节,而double占用8字节,空间浪费 。
【建议】文本数据尽量用varchar存储 。因为varchar是变长存储,比char更省空间 。MySQL server层规定一行所有文本最多存65535字节,因此在utf8字符集下最多存21844个字符,超过会自动转换为mediumtext字段 。而text在utf8字符集下最多存21844个字符,mediumtext最多存2^24/3个字符,longtext最多存2^32个字符 。一般建议用varchar类型,字符数不要超过2700 。
【建议】时间类型尽量选取timestamp 。因为datetime占用8字节,timestamp仅占用4字节,但是范围为1970-01-01 00:00:01到2038-01-01 00:00:00 。更为高阶的方法,选用int来存储时间,使用SQL函数unix_timestamp()和from_unixtime()来进行转换 。
详细存储大小参加下图:
数据库设计规范|数据库设计三大规范


4、 索引设计

    【强制】InnoDB表必须主键为id int/bigint auto_increment,且主键值禁止被更新 。
    【建议】主键的名称以“pk_”开头,唯一键以“uk_”或“uq_”开头,普通索引以“idx_”开头,一律使用小写格式,以表名/字段的名称或缩写作为后缀 。
    【强制】InnoDB和MyISAM存储引擎表,索引类型必须为BTREE;MEMORY表可以根据需要选择HASH或者BTREE类型索引 。
    【强制】单个索引中每个索引记录的长度不能超过64KB 。
    【建议】单个表上的索引个数不能超过7个 。

    【数据库设计规范|数据库设计三大规范】

    【建议】在建立索引时,多考虑建立联合索引,并把区分度最高的字段放在最前面 。如列userid的区分度可由select count(distinct userid)计算出来 。
    【建议】在多表join的SQL里,保证被驱动表的连接列上有索引,这样join执行效率最高 。
    【建议】建表或加索引时,保证表里互相不存在冗余索引 。对于MySQL来说,如果表里已经存在key(a,b),则key(a)为冗余索引,需要删除 。
5、 分库分表、分区表
    【强制】分区表的分区字段(partition-key)必须有索引,或者是组合索引的首列 。
    【强制】单个分区表中的分区(包括子分区)个数不能超过1024 。
    【强制】上线前RD或者DBA必须指定分区表的创建、清理策略 。
    【强制】访问分区表的SQL必须包含分区键 。
    【建议】单个分区文件不超过2G,总大小不超过50G 。建议总分区数不超过20个 。
    【强制】对于分区表执行alter table操作,必须在业务低峰期执行 。
    【强制】采用分库策略的,库的数量不能超过1024
    【强制】采用分表策略的,表的数量不能超过4096
    【建议】单个分表不超过500W行,ibd文件大小不超过2G,这样才能让数据分布式变得性能更佳 。
    【建议】水平分表尽量用取模方式,日志、报表类数据建议采用日期进行分表 。
6、 字符集
    【强制】数据库本身库、表、列所有字符集必须保持一致,为utf8或utf8mb4 。
    【强制】前端程序字符集或者环境变量中的字符集,与数据库、表的字符集必须一致,统一为utf8 。
2、 SQL编写规范数据库设计规范|数据库设计三大规范


1、 DML语句
    【强制】SELECT语句必须指定具体字段名称,禁止写成* 。因为select *会将不该读的数据也从MySQL里读出来,造成网卡压力 。且表字段一旦更新,但model层没有来得及更新的话,系统会报错 。
    【强制】insert语句指定具体字段名称,不要写成insert into t1 values(…),道理同上 。
    【建议】insert into…values(XX),(XX),(XX)… 。这里XX的值不要超过5000个 。值过多虽然上线很很快,但会引起主从同步延迟 。
    【建议】SELECT语句不要使用UNION,推荐使用UNION ALL,并且UNION子句个数限制在5个以内 。因为union all不需要去重,节省数据库资源,提高性能 。
    【建议】in值列表限制在500以内 。例如select… where userid in(….500个以内…),这么做是为了减少底层扫描,减轻数据库压力从而加速查询 。
    【建议】事务里批量更新数据需要控制数量,进行必要的sleep,做到少量多次 。
    【强制】事务涉及的表必须全部是innodb表 。否则一旦失败不会全部回滚,且易造成主从库同步终端 。
    【强制】写入和事务发往主库,只读SQL发往从库 。
    【强制】除静态表或小表(100行以内),DML语句必须有where条件,且使用索引查找 。
    【强制】生产环境禁止使用hint,如sql_no_cache,force index,ignore key,straight join等 。因为hint是用来强制SQL按照某个执行计划来执行,但随着数据量变化我们无法保证自己当初的预判是正确的,因此我们要相信MySQL优化器!