命名规范
库名、表名、字段名必须使小写字符,并采用下划线分割
库名、表名、字段名禁止超过32个字符。须见名知意
库名、表名、字段名禁止使用MySQL保留字
临时库、表名必须以tmp为前缀,并以日期为后缀
备份库、表必须以bak为前缀,并以日期为后缀
例子:
create table TTT (insert
int(10) not null …)
create table abc_1202 …
alter table t add index idx_uid_mid_time(uid,mid,time)
alter table t add index idx_uid(uid,mid,time) ->NO
tmp_test01_0704 ->NO bak_test01_20130704web
基础规范
使用INNODB存储引擎
表字符集使?UTF8
全部表都须要添加注释
单表数据量建议控制在5000W之内 ->500W内性能最佳
不在数据库中存储图片、文件件等大数据
禁止在线上作数据库压力测试
禁止从测试、开发环境直连数据库数据库
库表设计
慎用分区表
拆分大字段和访问频率低的字段,分离冷热数据
用HASH进行散表,表名后缀使十进制数,下标从0开始
按日期时间分表需符合YYYY[MM][DD][HH]格式
采用合适的分库分表策略。例如千库十表、十库百表等 、
例子:
comment_20120815
comment_20120816
comment_120817
user_39
user_3A
user_3B
user_3C网络
字段设计
尽量不使用TEXT、BLOB类型
用DECIMAL代替FLOAT和DOUBLE存储精确浮点数
Simple is good
将字符转化为数字
使用TINYINT来代替ENUM类型
Generosity can be unwise
存储 “hello”时VARCHAR(5) VS VARCHAR(200)
The best strategy is to allocate only as much space as you really need.
ENUM(‘Mercury’, ‘Venus’, ‘Earth’) numbers ENUM(‘0’,’1’,’2’)
存储index,而不是字符串
枚举值改变会致使DDL
Avoid null if possible
可为NULL的列影响索引统计数据生成
可为NULL的列加索引会占用额外空间
全部字段均定义为NOT NULL
Smaller is usually better
使用UNSIGNED存储非负整数
INT类型固定占用4字节存储
使用timestamp存储时间
使用INT UNSIGNED存储IPV4
使用VARBINARY存储大小写敏感的变长字符串
禁止在数据库中存储明文密码app
索引规范
索引的用途
去重
加速定位
避免排序
覆盖索引
索引数量控制
单张表中索引数量不超过5个
单个索引中的字段数不超过5个
对字符串使用前缀索引,前缀索引长度不超过8个字符
建议优先考虑前缀索引,必要时可添加伪列并创建索引
主键准则
表必须有主键
不使用更新频繁的列
尽可能不选择字符串列
不使用UUID MD5 HASH
默认使非空的惟一键
建议选择自增或发号器
重要的SQL必须被索引
区分度最大的字段放在前面
核心SQL优先考虑覆盖索引
避免冗余和重复索引
索引不是越多越好
综合评估数据密度和分布
考虑查询和更新比例
索引是一把双刃剑:下降插入和更新速度,占用磁盘空间
索引禁忌
不在低基数列上创建索引,例如“性别”
不在索引列进行数学运算和函数运算
尽可能不使用外键
外键用来保护参照完整性,可在业务端实现
对父表和子表的操做会相互影响,下降可用性
INNODB自己对online DDL的限制
不使用%前导的查询,如like “%ab”
不使用负向查询,如not in/like
没法使用索引,致使全表扫描
全表扫描致使bufer pool利用率下降
尺有所短,寸有所长,换一种工具试试!svg
SQL设计
避免使用存储过程、触发器、UDF、events等
让数据库作最擅长的事
下降业务耦合度,为scale out、sharding留有余地
避开BUG
避免使用大表的JOIN
MySQL最擅长的是单表的主键/二级索引查询
JOIN消耗较多内存,产生临时表
避免在数据库中进行数学运算
MySQL不擅长数学运算和逻辑判断
没法使用索引
md5()/order by rand()
select … where to_days(current_date) - to_days(date_col)<=10
select … where date_col>=date_sub(current_date, interval 10 day)
select … where date_col>=date_sub(‘2013-08-17’, interval 10 day)
select … where date_col>=‘2013-08-07’
数据库是有状态的服务,调整代码部署更灵活、简单、高效!
减小与数据库的交互次数
INSERT … ON DUPLICATE KEY UPDATE
REPLACE INTO、INSERT IGNORE 、INSERT INTO VALUES(),(),()
UPDATE … WHERE ID IN(10,20,50,…)
合理的使用分页
限制分页展开的页数
只能点击上一页、下一页
采用延迟关联(join的延迟)
拒绝大SQL,拆分红小SQL
充分利用QUERY CACHE
充分利用多核CPU
使用in代替or,in的值不超过1000个 (所在列没有索引的状况差异巨大)
禁止使用order by rand()
使用EXPLAIN诊断,避免生成临时表
用union all而不是union(union会多作一次去重的操做)
程序应有捕获SQL异常的处理机制
禁止单条SQL语句同时更新多个表
不使用select *
消耗CPU和IO、消耗网络带宽
没法使用覆盖索引
减小表结构变动带来的影响
由于大,select/join 可能生成临时表
select * from opp where phone=‘12345678’ or phone=‘234234234’
select * from opp where phone in (’12345678’, ‘234234234’)
select * from app where phone=‘010-88886666’ or cellphone=‘18618111111’
select * from opp where phone=’010-88886666’
union all select * from opp where cellphone=’ 18618111111’函数
行为规范
批量导入、导出数据必须提早通知DBA协助观察
禁止在线上从库执行后台管理和统计类查询
禁止有super权限的应用程序帐号存在
产品出现非数据库致使的故障时及时通知DBA协助排查
推广活动或上线新功能必须提早通知DBA进行流量评估
数据库数据丢失,及时联系DBA进行恢复
对单表的屡次alter操做必须合并为一次操做
不在MySQL数据库中存放业务逻辑
重要项目的数据库方案选型和设计必须提早通知DBA参与
对特别重要的库表,提早与DBA沟通肯定维护和备份优先级
不在业务高峰期批量更新、查询数据库
提交线上建表改表需求,必须详细注明全部相关SQL语句
良好的线上环境须要你们共同的努力! 工具