阿里sql规范学习

(一)建表规约
1.【强制】表名、字段名必须使用小写字母或数字,因为数据库字段名的修改代价很大,无法进行预发布,所以字段名称需要慎重考虑。 
说明:MySQL在Windows下不区分大小写,但在Linux下默认是区分大小写。 
2.【强制】禁用保留字,如desc、delayed等,请参考MySQL官方保留字。 

3.【强制】主键索引名为pk_字段名;唯一索引名为uk_字段名;普通索引名则为idx_字段名。 
说明:pk_ 即primary key;uk_ 即uniquekey;idx_ 即index的简称。
4.【强制】小数类型为decimal,禁止使用float和double。 
说明:float和double在存储的时候,存在精度损失的问题,很可能在值的比较时,得到不正确的结果。 

补充:

(1).float和double都是浮点型,而decimal是定点型;float,double等非标准类型,在DB中保存的是近似值,而Decimal则以字符串的形式保存数值。

  • float:浮点型,含字节数为4,32bit,数值范围为-3.4E38~3.4E38(7个有效位)
  • double:双精度实型,含字节数为8,64bit数值范围-1.7E308~1.7E308(15个有效位)
  • decimal:数字型,128bit,不存在精度损失,常用于银行帐目计算。(28个有效位)

(2). decimal,整数部分和小数部分是分开存储的,每9个数字占用4个字节,在mysql内部使用的二进制存储,基本没有长度的限制;

(3).浮点型和定点型应用场景:  decimal数据类型用于要求非常高的精确度的计算中,其他的一些自然数据,当我们对精度要求不高的时候,可以使用float/double

(4).如果存储的数据范围超过decimal的范围,建议将数据拆成整数和小数分开存储。 
5.【强制】如果存储的字符串长度几乎相等,使用char定长字符串类型。 
6.【强制】varchar是可变长字符串,不预先分配存储空间,长度不要超过5000,如果存储长度大于此值,定义字段类型为text,独立出来一张表,用主键来对应,避免影响其它字段索引效率。

从存储上讲:
- text 是要要进overflow存储。 也是对于text字段,不会和行数据存在一起。但原则上不会全部overflow , 
会有768字节和原始的行存储在一块,多于768的行会存在和行相同的Page或是其它Page上。

变长字段的缺点:

- 在Innobase中,变长字段,是尽可能的存储到一个Page里,这样,如果使用到这些大的变长字段,会造成一个Page里能容纳的行 
数很少,在查询时,虽然没查询这些大的字段,但也会加载到innodb buffer pool中,等于浪费的内存。 (buffer pool 
的缓存是按page为单位)(不在一个page了会增加随机的IO)

 

7.【强制】表必备三字段:id,create_time和update_time。 
说明:其中id必为主键,类型为unsigned bigint、单表时自增、步长为1。 
8.【推荐】如果修改字段含义或对字段表示的状态追加时,需要及时更新字段注释。 

例如:alter table_name add column varchar(*);
COMMENT ON COLUMN table_name IS '注释注释注释注释注释注释注释注释';
9.【推荐**】字段允许适当冗余,以提高查询性能,但必须考虑数据一致。 
冗余字段应遵循: 
1)不是频繁修改的字段。 
2)不是varchar超长字段,更不能是text字段。 
正例:商品类目名称使用频率高,字段长度短,名称基本一成不变,可在相关联的表中冗余存储类目名称,避免关联查询。 

10.【参考】合适的字符存储长度,不但节约数据库表空间、节约索引存储,更重要的是提升检索速度。 

(二)索引规约
1.【强制】业务上具有唯一特性的字段,即使是多个字段的组合,也必须建成唯一索引。 
说明:唯一索引影响insert的速度,这个速度损耗可以忽略,但提高查找速度是明显的; 
另外,即使在应用层做了非常完善的校验控制,只要没有唯一索引,总会有一种情况使脏数据产生。 
2.【强制】超过三个表禁止join。需要join的字段,数据类型必须绝对一致; 
多表关联查询时,保证被关联的字段需要有索引。说明:即使双表join也要注意表索引、SQL性能。 
3.【强制】页面搜索严禁左模糊或者全模糊,如果需要请走搜索引擎来解决。 like本身效率较低

select * fromdoc where title like '%XX'    和    select * fromdoc where title like 'XX%'
4.【强制】索引文件具有B-Tree的最左前缀匹配特性 ,最左侧查询需求,并不是指 SQL 语句的 where 顺序要和联合索引一致。

下面的 SQL 语句也可以命中 (login_name, passwd) 这个联合索引。

select uid, login_time from user where passwd=? andlogin_name=?

5.【推荐】如果有orderby的场景,请注意利用索引的有序性。 
orderby最后的字段是组合索引的一部分,并且放在索引组合顺序的最后,避免出现file_sort的情况,影响查询性能。 

/*应当构建索引idx_a_b_c*/
select * from table_name where a=value1 and b=value3 order by c

反例:索引中有范围查找,那么索引有序性无法利用。 如:WHERE a>10 ORDER BY b; 索引 a_b 无法排序。

6.【推荐】利用覆盖索引来进行查询操作,避免回表。 
正例:能够建立索引的种类:主键索引、唯一索引、普通索引,而覆盖索引是一种查询的一种效果,用explain的结果,extra列会出现:usingindex。 

/*应当构建索引idx_a_b_c*/
select c from table_name where a=value1 and b=value2
7.【推荐】利用延迟关联或者子查询优化超多分页场景。 
说明:MySQL并不是跳过offset行,而是取offset+N行,然后返回放弃前offset行,返回N行, 
当offset特别大的时候,效率就非常的低下,要么控制返回的总页数,要么对超过特定阈值的页数进行SQL改写。 
正例:先快速定位需要获取的id段,然后再关联:

//select a.* from table_a (select id from table_a where xxx limit no1,no2) b where a.id = b.id

#1
select hotel_seq
from table_name
where id in (select id
 from table_name where table_name > 2000000 and id < 2000030)

#2

select hotel_seq from table_name order by id limit 30 offset 2000030

8.【参考】创建索引时避免有如下极端误解: 
1)宁滥勿缺。认为一个查询就需要建一个索引。 
2)宁缺勿滥。认为索引会消耗空间、严重拖慢更新和新增速度。 
3)抵制惟一索引。认为业务的惟一性一律需要在应用层通过“先查后插”方式解决。

(新加)判断方式:在一个读多写少的表中,可以多添加一些索引,但是一个表如果是删除和添加操作较多的时候,就要权衡添加索引是否合适。

(三)SQL语句
1.【强制】不得使用外键与级联,一切外键概念必须在应用层解决。 
外键与级联更新适用于单机低并发,不适合分布式、高并发集群; 
级联更新是强阻塞,存在数据库更新风暴的风险;外键影响数据库的插入速度。 
2.【强制】禁止使用存储过程,存储过程难以调试和扩展,更没有移植性。 
3.【强制】数据订正时,删除和修改记录时,要先select,避免出现误删除,确认无误才能执行更新语句。 
4.【推荐】in操作能避免则避免,若实在避免不了,需要仔细评估in后边的集合元素数量,控制在1000个之内。 
5.【参考】如果有全球化需要,所有的字符存储与表示,均以utf-8mb4编码,注意字符统计函数的区别。 
说明: 
SELECT LENGTH(“轻松工作”);返回为8 (在pgsql中结果为4)
SELECT CHARACTER_LENGTH(“轻松工作”);返回为4 
6.【参考】TRUNCATE TABLE比DELETE速度快,且使用的系统和事务日志资源少, 
但TRUNCATE无事务且不触发trigger,有可能造成事故,故不建议在开发代码中使用此语句。 
说明: 
TRUNCATETABLE在功能上与不带WHERE子句的DELETE语句相同。

 

 

 

引用:http://www.matools.com/blog/190441377

你可能感兴趣的:(个人学习笔记)