T31火车票购票系统-MySQL设计规约

190 阅读5分钟

规约,一般是指在国际社会具有重大意义的条约,通常指国际组织的章程。

建表规约

表、字段命名

  1. 必须使用小写字母或数字 - 匹配java命名规范
  2. 禁止出现数字开头 - 映射到java属性,编译出错
  3. 禁止两个下划线中间出现数字 - 映射到java后违反驼峰命名方式
  4. 不使用复数形式 - 约定
  5. 禁用保留字 - 可能引起sql执行错误
  6. 与否使用is_xxx方式命名 - 见名知意,约定

数据类型

  1. 小树类型使用decimal:可控的小数位数
  2. 货币单位使用最小货币单位,类型为bigint: 典型考虑的是算法原理
  3. 字符串长度几乎相等,使用char: 存储原理,减少2个字节存储长度;
  4. varchar长度不超过5000:存储原理,InnoDB每个默认大小是 16KB,页是 InnoDB管理磁盘的最小单位,也InnoDB中磁盘和内存交,如果数据过大会导致每页存储数据过少,最终导致磁盘多次IO

表必备三字段

  1. id
  2. create_time
  3. update_time

id作为主键不用说了,你不指定,mysql也会隐式生成一个类似rowno的字段,作为主键。

其他两个完全是经验之谈:比如同步数据,查询一些问题。

有的甚至还会吧创建人id和最近更新人的id也做存贮。

推荐规约

记录一个经验值:单表数据超过500万行或者单表超过2GB,才推荐进行分库分表,如果数据量大了查询性能依然满足要求,没必要一定进行分库分表,因为分库分表以后会导致系统复杂度提升,跨库join的问题等等。

索引规约

从不同维度来对索引分类

存储形式:聚簇索引(索引和数据在一起),非聚簇索引

数据约束:主键索引,唯一索引,非唯一索引

索引的数据结构原理

索引的数据结构

btree:每个节点都带数据,范围查找时会有多次的磁盘IO,不是最优解。

b+tree: 在btree基础上分支节点只存储索引值,叶子节点才存储数据;并且叶子节点是一个双向链表。

这样做全表扫描时,从第一个叶子节点到最后一个叶子遍历即可。

目前是mysql使用的存储结构,做到了存储和算法的最优实现。

索引名称规约

主键pk_xxx, 唯一索引 uk_xxx, 普通索引idx_xxx

创建索引规约

  1. 唯一特性的字段必须简称唯一索引: 算法原理上看,唯一性索引,一旦匹配到就停止了。
  1. varchar字段上建索引,必须指定索引长度:这个经常被忽略,存储原理,小的索引节省存储空间,一般头一二十位的就足够区分了。
  2. 建索引是,区分度最高在最左边: 算法角度,可以减少匹配次数。

索引误区

认为一张表只需要一个索引;

吝啬创建索引:认为索引会消耗空间,拖慢记录更新速度;

抵制唯一索引:不用唯一索引,应用真的无法保证唯一性,我自己也经常遇到,被逼无奈才加唯一索引。

SQL规约

count用法

  1. 使用count(*) 来代替count(列)或count(1)sql官方推荐,有内部优化
  2. count(distinct col) 计算除了null之外的不重复行数;
  3. 当某一个列是null时,count(col)结果是0,但是sum(col)结果是null

分页

  1. 如果count为0,应该直接返回,不用查了
  2. 很多页之后,mysql其实每一个页的数据都要从磁盘中读出来,数一遍,再返回数到的数据,io一个没落下,所以最好通过一些条件,能够先过滤到要查询的数据位置,减少不必要的io。

null值

要求:使用isnull()来判断是否为null

和null比,结果都是null; 就像很认真的和一个傻子吵架,吵赢吵输,都证明你自己也是个傻子。

闭坑指南

  1. 禁用外键,关联关系在应用层解决。外键容易造成DBA操作的不便利;
  2. 禁用存储过程:基本不用提了,现在年轻人都不知道啥叫存储过程了
  3. navcat中用sql刷数据,一定要现select,再去update
  4. 多表时,使用别名:否则今天写的sql没错,n天后出错。当你添加一个冗余字段时,就可能影响哦。
  5. sql语句别名前加as,并且以t1,t2顺序命名
  6. in集合数量,控制再1000内

sql优化目标

sql优化就是要让sql用到索引,索引减少读取的数量量,降低io,提高性能。

sql执行计划

explain工具,查看执行计划,分析使用到索引;

如果不知道使用的是哪个索引,通过key_length可以辅助分析用到的哪个索引。

索引失效

1.有or的情况;
2.组合索引未用左列字段;
3.like以%开头;
4.隐式类型转换;
5.where中索引列有运算;
6.where中索引列使用了函数;
7.如果mysql觉得全表扫描更快时(数据少);