规约,一般是指在国际社会具有重大意义的条约,通常指国际组织的章程。
建表规约
表、字段命名
- 必须使用小写字母或数字 - 匹配java命名规范
- 禁止出现数字开头 - 映射到java属性,编译出错
- 禁止两个下划线中间出现数字 - 映射到java后违反驼峰命名方式
- 不使用复数形式 - 约定
- 禁用保留字 - 可能引起sql执行错误
- 与否使用is_xxx方式命名 - 见名知意,约定
数据类型
- 小树类型使用decimal:可控的小数位数
- 货币单位使用最小货币单位,类型为bigint: 典型考虑的是算法原理
- 字符串长度几乎相等,使用char: 存储原理,减少2个字节存储长度;
- varchar长度不超过5000:存储原理,InnoDB每个页默认大小是 16KB,页是 InnoDB管理磁盘的最小单位,也InnoDB中磁盘和内存交,如果数据过大会导致每页存储数据过少,最终导致磁盘多次IO
表必备三字段
- id
- create_time
- update_time
id作为主键不用说了,你不指定,mysql也会隐式生成一个类似rowno的字段,作为主键。
其他两个完全是经验之谈:比如同步数据,查询一些问题。
有的甚至还会吧创建人id和最近更新人的id也做存贮。
推荐规约
记录一个经验值:单表数据超过500万行或者单表超过2GB,才推荐进行分库分表,如果数据量大了查询性能依然满足要求,没必要一定进行分库分表,因为分库分表以后会导致系统复杂度提升,跨库join的问题等等。
索引规约
从不同维度来对索引分类
存储形式:聚簇索引(索引和数据在一起),非聚簇索引
数据约束:主键索引,唯一索引,非唯一索引
索引的数据结构原理
索引的数据结构
btree:每个节点都带数据,范围查找时会有多次的磁盘IO,不是最优解。
b+tree: 在btree基础上分支节点只存储索引值,叶子节点才存储数据;并且叶子节点是一个双向链表。
这样做全表扫描时,从第一个叶子节点到最后一个叶子遍历即可。
目前是mysql使用的存储结构,做到了存储和算法的最优实现。
索引名称规约
主键pk_xxx, 唯一索引 uk_xxx, 普通索引idx_xxx
创建索引规约
- 唯一特性的字段必须简称唯一索引: 算法原理上看,唯一性索引,一旦匹配到就停止了。
- varchar字段上建索引,必须指定索引长度:这个经常被忽略,存储原理,小的索引节省存储空间,一般头一二十位的就足够区分了。
- 建索引是,区分度最高在最左边: 算法角度,可以减少匹配次数。
索引误区
认为一张表只需要一个索引;
吝啬创建索引:认为索引会消耗空间,拖慢记录更新速度;
抵制唯一索引:不用唯一索引,应用真的无法保证唯一性,我自己也经常遇到,被逼无奈才加唯一索引。
SQL规约
count用法
- 使用count(*) 来代替count(列)或count(1)sql官方推荐,有内部优化
- count(distinct col) 计算除了null之外的不重复行数;
- 当某一个列是null时,count(col)结果是0,但是sum(col)结果是null
分页
- 如果count为0,应该直接返回,不用查了
- 很多页之后,mysql其实每一个页的数据都要从磁盘中读出来,数一遍,再返回数到的数据,io一个没落下,所以最好通过一些条件,能够先过滤到要查询的数据位置,减少不必要的io。
null值
要求:使用isnull()来判断是否为null
和null比,结果都是null; 就像很认真的和一个傻子吵架,吵赢吵输,都证明你自己也是个傻子。
闭坑指南
- 禁用外键,关联关系在应用层解决。外键容易造成DBA操作的不便利;
- 禁用存储过程:基本不用提了,现在年轻人都不知道啥叫存储过程了
- navcat中用sql刷数据,一定要现select,再去update
- 多表时,使用别名:否则今天写的sql没错,n天后出错。当你添加一个冗余字段时,就可能影响哦。
- sql语句别名前加as,并且以t1,t2顺序命名
- in集合数量,控制再1000内
sql优化目标
sql优化就是要让sql用到索引,索引减少读取的数量量,降低io,提高性能。
sql执行计划
explain工具,查看执行计划,分析使用到索引;
如果不知道使用的是哪个索引,通过key_length可以辅助分析用到的哪个索引。
索引失效
1.有or的情况;
2.组合索引未用左列字段;
3.like以%开头;
4.隐式类型转换;
5.where中索引列有运算;
6.where中索引列使用了函数;
7.如果mysql觉得全表扫描更快时(数据少);