数据库SQL语句书写注意事项
1. 从多个表中选择记录(表名顺序)
执行顺序采用从右往左的方式进行处理,在这种情况下将记录数较少的表格放置在右侧位置作为基准层。当存在超过三个表格进行关联查询时,则选择交叉表格作为基准层(即该张表格会被其他相关联的表格引用使用)
具体来说,在这种情况下我们主要关注的是那些具有较高关联度的数据源通过交叉分析来提取关键信息从而实现业务目标
2. WHERE子句中的连接顺序
ORACLE遵循自左向右的工作流程;也就是说,在WHERE子句中排列能够筛选出最多记录条目的条件应当放置于其最末端的位置。
3.SELECT子句中一定避免使用 ‘ * ‘
注意一定别是用* ,巨耗时。
4. 删除重复记录
避免表中出现重复记录。
Oracle中最高效的删除重复记录方法的例子:
DELETE FROM EMP E WHERE E.ROWID > (SELECT MIN(X.ROWID) FROM EMP X WHERE X.EMP_NO = E.EMP_NO);
5 尽量多使用COMMIT
只要有可能,在程序中尽可能多地使用COMMIT操作,并以此为基础进行优化以提升性能。COMMIT操作所释放的具体资源包括:首先,在回滚段中用于恢复数据的信息;其次,在程序执行过程中所持有的锁;再次,在redone log buffer中有待于重新写入的空间;最后,则是由ORACLE数据库管理系统用来管理上述三种资源内部开销的部分。
6 用Where子句替换HAVING子句
应尽量避免使用HAVING子句;该处理涉及排序以及总计等操作;然而,在这种情况下若能通过WHERE子句来限定符合条件的数据数量,则可以在一定程度上降低相关的计算开销。
7 使用表的别名(Alias)
在执行复杂的SQL语句以连接多个数据源时,引用表别名并附加前缀到每个列上是一种常用的技术手段。这种做法能够有效降低解析所需的时间,并避免由于列名称冲突导致的语法错误。
8 用EXISTS替代IN、用NOT EXISTS替代NOT IN
常用于EXISTS(包括NOT EXISTS)通常会提升查询效率。不管在什么场景下, NOT IN通常是相对最不高效的 (因为它要求子查询中的表进行全表扫描).
例子:
(高效)SELECT * FROM EMP (基础表) WHERE EMPNO > 0 AND EXISTS (SELECT ‘X' FROM DEPT WHERE DEPT.DEPTNO = EMP.DEPTNO AND LOC = ‘MELB')
(低效)SELECT * FROM EMP (基础表) WHERE EMPNO > 0 AND DEPTNO IN(SELECT DEPTNO FROM DEPT WHERE LOC = ‘MELB')
9 用索引提高效率
由于索引在内存中占用额外的空间并涉及运算处理,多余的无用索引会导致查询响应速度减缓.因此,定期对数据结构进行优化是维护系统高效运行的关键措施:
ALTER INDEX <INDEXNAME> REBUILD <TABLESPACENAME>
10 用EXISTS替换DISTINCT
当处理涉及一对多关系(如部门表与员工表)的查询时,在SELECT子句中应尽量避免使用DISTINCT关键字。通常建议用EXIST替代DISTINCT以提高效率。由于RDBMS的核心模块一旦满足子查询条件就会立即返回结果,请注意这一特性对性能优化的重要性。例如,在以下情况下可以考虑采用该方法:
(低效): SELECT DISTINCT DEPT_NO,DEPT_NAME FROM DEPT D , EMP E WHERE D.DEPT_NO = E.DEPT_NO
(高效): SELECT DEPT_NO,DEPT_NAME FROM DEPT D WHERE EXISTS ( SELECT ‘X' FROM EMP E WHERE E.DEPT_NO = D.DEPT_NO);
11 sql语句用大写的
因为oracle总是先解析sql语句,把小写的字母转换成大写的再执行
12 避免在索引列上使用NOT 通常
应尽量避免在索引列中定义NOT字段, 因为这可能导致与在索引列上应用函数产生相同的效果. 当ORACLE处理到NOT字段时, 它将不再利用索引来加快查询速度, 转而进行全表扫描以获取结果.
13 避免在索引列上使用计算
假如索引列是函数的一部分.优化器将不使用索引而使用全表扫描.举例:
低效:SELECT … FROM DEPT WHERE SAL * 12 > 25000;
高效: SELECT … FROM DEPT WHERE SAL > 25000/12;
14 用>=替代>
高效:SELECT * FROM EMP WHERE DEPTNO >=4
低效:SELECT * FROM EMP WHERE DEPTNO >3
两者的区别在于, 前者DBMS将直接跳转至第一条DEPT值为4的记录, 而后者则首先定位至DEPTNO=3的记录, 并且继续向前扫描直至找到第一条DEPT值超过3的记录.
15 避免在索引列上使用IS NULL和IS NOT NULL
在索引中判空,将无法使用该索引.
低效: (索引失效) SELECT … FROM DEPARTMENT WHERE DEPT_CODE IS NOT NULL;
高效: (索引有效) SELECT … FROM DEPARTMENT WHERE DEPT_CODE >=0;
16 需要当心的WHERE子句
第一,! 会导致索引无效;该处应引发错误信息
第二,' 充当字符连接函数;该处会产生错误提示
第三,+ 运算符 该处将产生异常结果
