携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第17天,点击查看活动详情 >>
最佳实践
3.5【参考】关于 SELECT COUNT(1) 与 SELECT COUNT(*)
说明:
有人总是说“SELECT COUNT(1)”的效率比“SELECT COUNT(*)”的执行效率要高,
而且长久以来我们也一直这么认为。其实,在 Oracle 高版本中两者的效率基本一
致,没有本质差别。
这里还是推荐前一种写法,统一风格。
3.6【推荐】清空表记录用 TRUNCATE 替代 DELETE
说明:
当删除表中的记录时,在通常情况下,回滚段(rollback segments ) 用来存放可以
被恢复的信息。如果你没有 COMMIT 事务,ORACLE 会将数据恢复到删除之前的状态
(准确地说是恢复到执行删除命令之前的状况) 。而当运用 TRUNCATE 时,回滚段不
再存放任何可被恢复的信息。当命令运行后,数据不能被恢复,因此很少的资源被
调用,执行时间也会很短。
TRUNCATE 只在删除全表或者一个分区时适用,TRUNCATE 是 DDL 不是 DML。
3.7【推荐】用 EXISTS 替换 DISTINCT
说明:
当提交一个包含一对多表信息(比如部门表和雇员表)的查询时,避免在 SELECT 子句
中使用 DISTINCT。一般可以考虑用 EXISTS 替换,EXISTS 使查询更为迅速,因为
RDBMS 核心模块将在子查询的条件一旦满足后,立刻返回结果。
举例:
Demo
Avoided
SELECT DISTINCT DEPT_NO,DEPT_NAME
FROM DEPT D,
EMP E
WHERE D.DEPT_NO = E.DEPT_NO
Preferred
SELECT DEPT_NO,DEPT_NAME
FROM DEPT D
WHERE EXISTS (
SELECT ‘X'
FROM EMP E
WHERE E.DEPT_NO = D.DEPT_NO
)
3.8【强制】用 UNION 替换 OR(适用于索引列)
说明:
通常情况下,用 UNION 替换 WHERE 子句中的 OR 将会起到较好的效果。对索引列使用
OR 将造成全表扫描。注意,以上规则只针对多个索引列有效。 如果有 column 没有
被索引,查询效率可能会因为你没有选择 OR 而降低。
12C 数据库现在可以自动将 OR 分析为 UNION,但是有条件限制 :比如 SQL 里面
不能有 DISTINCT、COUNT 、MAX 等,所以还是建议 SQL 直接用 UNION 替换 OR。
在下面的例子中,LOC_ID 和 REGION 上都建有索引。
Note:非索引列的不强制,需要结合具体业务场景分析处理。
Demo
Avoided
SELECT LOC_ID,LOC_DESC,REGION
FROM LOCATION
WHERE LOC_ID=10
OR REGION=‘MELBOURNE’
Preferred
SELECT LOC_ID,LOC_DESC,REGION
FROM LOCATION
WHERE LOC_ID=10
UNION
SELECT LOC_ID,LOC_DESC,REGION
FROM LOCATION
WHERE REGION=‘MELBOURNE’
3.9【参考】关于索引效率
说明:
如果检索数据量超过 30%的表中记录数,使用索引将没有显著的效率提高。在特定
情况下,使用索引也许会比全表扫描慢,但这是同一个数量级上的区别,即这个情
况下使用索引的效率并不比全表扫描的效率差太多。而通常情况下,使用索引比全
表扫描要块几倍乃至几千倍。
3.10【参考】尽量减少 SQL 复杂度
说明:
尽量减少 SQL 复杂度,用简单 SQL 完成任务,复杂的逻辑在代码中实现。对一个大
结果集做排序,或者求唯一值,都是比较昂贵的计算,会占用大量数据库系统资源,
如果在业务上确实有这方面的需求,尽量放在业务代码中实现。
3.11【强制】表名、视图名、索引名长度
说明:
oracle11g 和 oracle12c中上述长度是不同的,12c长度<=128,而11g中只能长度<=30,
我们强制规范 表名、视图名、索引名长度 <= 30