SQL使用规范
SELECT语句规范
【强制】禁止使用 select * 进行查询,要具体到相应的列。
【强制】禁止使用DISTINCT * 操作,可使用DISTINT(Col1)。
【推荐】单条语句表数量限制3个或3个以内。超过3个时建议进行SQL语句拆分,开发过程中可根据具体业务场景综合比较性能,基本原则是3个以内的联表查询比单表多SQL查询快1至2倍,但超过一定数量的多表联表查询并不一定快。
【推荐】避 免不带条件的select,使用框架传值时,需对值进行非空判断,防止出现全表扫描导致jvm崩溃。框架应针对查询结果集条数限制。
【推荐】Join语句关联表的数量不能超过3个。
【强制】禁止笛卡尔乘积,例如:
-
SELECT * FROM table1 CROSS JOIN table2;
-
SELECT * FROM table1 JOIN table2;
-
SELECT * FROM table1 , table2;
【推荐】注意count(*)与count(列名)的区别,count(列名)不会统计此列为NULL的行。
【推荐】应尽量避免在where 子句中使用 != 或 <> 操作符。
【强制】如果没有创建trgm gin索引,则不推荐使用前模糊查询例如like '%abc%'。
【强制】避免使用标量子查询,需改写成联表查询。
反例:
- select t1.c1,(select c2 from t2 where t2.c1=t1.c1) as c2 from t1;
正例:
- select t1.c1,t2.c2 from t1 left join t2 on t1.c1=t2.c1;
【推荐】子查询数量默认限定3个或3个以内。
【推荐】推荐使用inner join ,避免使用left join和right join。
【强制】空值处理。
-
PG模式与ORACLE模式的空字符串 '' 处理方式不同,PG 模式空字符串 '' 与 NULL 不等价;ORACLE模式默认情况下空字符串 '' 与 NULL 等价(为了和Oracle数据库兼容),但是可以通过参数 oracle.transform_null_string 控制
-
set oracle.transform_null_string=on;
-
select '' is null;
-
set oracle.transform_null_string=off;
-
select '' is null;
-
-
基于HALO端开发时,无NOT NULL约束的字段,业务优先显式使用NULL进行插入,PG模式下允许但不建议使用空字符串 '' 插入。建议平台层面实现转换,统一调整为 '' 由NULL进行替代。(原因:如果混合使用空字符串和NULL,程序代码中需要分别判断该字段是空字符串还是NULL来确定该字段是否为空值)
-
基于HALO端开发时,存在NOT NULL约束的字段,PG模式下业务控制不允许有空字符串 '' 的插入。(原因:空字符串同步到Oracle后会转换成NULL,导致插入失败同步中断)
-
空值判断。PG模式下如果混合使用了空字符串和NULL,为了程序的兼容性,对于空值的判断要同时判断 '' 和NULL的情况,例句如下:
判断为空:
select c1,c2 from t1 where ( c1 = '' or c1 is null);
判断不为空:
- select c1,c2 from t1 where (c1 != '' and c1 is not null);
- 对于整型,字段定义时要设置成NOT NULL,如果有空值,需要赋值成0。
UPDATE语句规范
【强制】禁止单条SQL语句同时更新多个表。
【强制】UPDATE应仅针对有修改的字段进行。 UPDATE操作时,应该做到仅对有修改的字段UPDATE,避免对表中无修改的字段也一并更新,后者的做法将耗费更多的CPU、内存。
【强制】避免不带where条件的update全量更新。
DELETE语句规范
【推荐】建议有定期历史数据删除需求的业务,表按时间分区,删除时不要使用DELETE操作,而是DROP或者TRUNCATE对应的表。
【强制】禁止不带where条件的delete全量表删除操作。
INSERT语句规范
【强制】必须在insert语句中指定列名,减少表结构变更带来的影响,特别是自定义SQL。
【强制】禁止insert into A select * from B,全表备份转移,需要带分段条件。
GROUP BY使 用规范
【推荐】GROUP BY 的列最好是整型,或者非常短的字符串,例如VARCHAR(10)等。
【推荐】GROUP BY 的列不要超过两个。
【强制】GROUP BY 的列不要计算。在应用层中实现计算。例如,禁止这样写GROUP BY MOD(ID,5)。
【推荐】为GROUP BY字段结合过滤条件建索引。
ORDER BY使用规范
【强制】ORDER BY 列不得做计算,可在设计时对字段进行拆分
【强制】不得使用ORDER BY RAND(),禁止使用随机排序。
【推荐】为ORDER BY字段结合过滤条件建索引。
JOIN/IN/EXISTS/UNION使用规范
【推荐】根据业务场景需要,避免使用left/right join,尽量使用内连接,若业务上必须使用left/right join,应选择小表作为驱动表。左连接时,如果右表有过滤条件,等价于inner join,避免使用left join。
【推荐】HALO 对or的查询条件,会使用bitmap or进行索引的过滤,所以不需要改SQL语句,可以直接使用。例如,以下查询都可以走索引:
select * from tbl where col1 =1 or col1=2 or col2=1 or ...;
select * from tbl where col1 in (1,2);
【推荐】很多时候用 exists 代替 in 是一个好的选择
select c1 from tbl1 where c1 in (select c2 from tbl2);
用下面的语句替换:
select c1 from tbl1 where exists (select 1 from tbl2 where tbl1.c1=tbl2.c2);
【推荐】建议使用UNION ALL,UNION会将两个结果集中的记录进行排除重复记录的操作,UNION ALL没有该操作,因此使用后者可以更快返回记录,在业务上没有特殊要求的时候,应该优先使用UNION ALL。
【强制】确保 SQL 中 join 列数据类型一致,避免发生隐式转换。
其他使用规范
【强制】确保SQL中谓词条件数 据类型与列实际数据类型一致,避免出现隐式转换。
在SQL中,谓词就是返回boolean值即true或者false的函数,或是隐式转换为boolean的函数。SQL中的谓词主要有 LIKE、BETWEEN、IS NULL、IS NOT NULL、IN、EXISTS。
【强制】数据订正时,删除和修改记录时,要先select,避免出现误删除,确认无误才能提交执行。
【推荐】高峰期对大表添加包含默认值的字段,会导致表的rewrite,建议只添加不包含默认值的字段,业务逻辑层面后期处理默认值。