常用的SQL优化技巧

从使用索引来考虑SQL语句

  • 避免索引列上的函数,如SUBSTR/UPPER/NVL/TO_CHAR/TO_DATE/TRUNC

  • 避免索引列上的计算公式:如果索引列上使用了计算公式,则索引不能使用,可以通过更改计算公式来避免
    不使用索引:Select e.Ename From Emp e Where e.Sal * 1.1 > 900
    使用索引:Select e.Ename From Emp e Where e.Sal > 900 / 1.1
    低效: Select … FROM DEPARTMENT Where DEPT_CODE IS NOT NULL;
    高效: Select … FROM DEPARTMENT Where DEPT_CODE >=0;

  • 避免使用not in,使用not exists代替
    Select e.Ename From Emp e Where e.Deptno Not In (Select d.Deptno From Dept d)
    Select e.Ename From Emp e Where e.Deptno Not Exists (Select ‘x’ From Dept d Where d.Deptno = e.Deptno)

  • LIKE的使用: LIKE用于模糊检索,LIKE检索的样式有三种:前匹配(XX%)、中间匹配(X%X)、后匹配(%XX),对于前匹配可以使用索引,而使用中间匹配和后匹配,都不能使用索引。因此除非必要,否则应尽量避免使用中间匹配和后匹配

  • 复合索引的使用:要使用复合索引,where语句中必须包括复合索引中的所有列或前几个列。如果复合索引的第一个列不在where语句中则不应该使用该复合索引

从减少系统负荷来考虑SQL语句

  • 使用表别名:通过对表附加别名,SQL编译时可以明确列的来源表,从而使得SQL的编译时间缩短

  • ROWNUM的使用:ROWNUM可以限制检索数据的数量,如果为了判断对象是否存在,使用ROWNUM=1是非常有效的

  • UNION和UNION ALL:如果确定联合中不会出现重复数据的话,必须设定UNION ALL来取消自动分类以提高检索速度

  • 替代DISTINCT:尽量少使用DISTINCT,使用DISTINCT将引起内部排序处理,如果可以的话,尽量使用EXISTS、NOT EXISTS或子查询来避免
    Select Distinct d.Deptno, d.Dname From Dept d, Emp e Where d.Deptno = e.DeptnoSelect d.Deptno, d.Dname From Dept d Where Exists (Select ‘x’ From Emp e Where d.Deptno = e.Deptno)

  • 避免视图滥用:如果查询只检索基表的几个字段,应避免直接使用视图,造成不必要的数据块检索

  • 编写可再利用性的SQL语句:需要动态组合条件时,应避免直接将变量值组合到条件中去,而应该使用变量绑定,从而提高SQL语句的再利用性

Select子句中避免使用*

当你想在SELECT子句中列出所有的COLUMN时,使用动态SQL列引用 * 是一个方便的方法.不幸的是,这是一个非常低效的方法. 实际上,ORACLE在解析的过程中, 会将 * 依次转换成所有的列名, 这个工作是通过查询数据字典完成的, 这意味着将耗费更多的时间.

使用decode函数来减少处理时间

使用DECODE函数可以避免重复扫描相同记录或重复连接相同的表.

例如:
select count() from pts_work_centers t where t.organization_id = 85
and t.work_center_name like ‘%氧化%’;
select count(
) from pts_work_centers t where t.organization_id = 86
and t.work_center_name like ‘%氧化%’;

用decode可以写成:
select count(decode(t.organization_id,85,‘X’)),
count(decode(t.organization_id,86,‘X’))
from pts_work_centers t
where t.work_center_name like ‘%氧化%’;

用Where子句替换HAVING子句

避免使用HAVING子句, HAVING 只会在检索出所有记录之后才对结果集进行过滤. 这个处理需要排序,总计等操作. 如果能通过WHERE子句限制记录的数目,那就能减少这方面的开销.

低效:
select t.organization_id,count(*)
from pts_work_centers t
group by t.organization_id
having t.organization_id not in(85,86);

高效:
select t.organization_id,count(*)
from pts_work_centers t
where t.organization_id not in(85,86)
group by t.organization_id

HAVING 中的条件一般用于对一些集合函数的比较,如COUNT() 等等. 除此而外,一般的条件应该写在WHERE子句中

需要当心的Where子句:

某些Select 语句中的Where子句不使用索引. 这里有一些例子.
在下面的例子里

  • ‘!=’ 将不使用索引. 记住, 索引只能告诉你什么存在于表中, 而不能告诉你什么不存在于表中.
  • ‘||'是字符连接函数. 就象其他函数那样, 停用了索引.
  • ‘+'是数学函数. 就象其他数学函数那样, 停用了索引.
  • 相同的索引列不能互相比较,这将会启用全表扫描.

利用空值不会出现在索引的原则来提高SQL性能

假如某个字段,对于大多数记录而言是一个固定值,只有少数记录是另外其他值,而我们的程序中通常要查询这些少数据记录。

例如,库存事务表的‘成本核算’字段,大多数记录肯定是已核算成本,只有少部分记录是未核算成本,而成本管理器就仅仅想查询这些未核算成本的记录,如果我们设计‘已核算’状态的值为‘Y’,‘未核算’状态为‘N’,那这个查询会消耗巨大。如果我们设计‘已核算’状态的值为‘’,‘未核算’状态为‘N’,那么查询速度会非常快: select transaction_id from mmt where cost_flag = ‘N’

避免改变索引列的类型

避免ORACLE对你的SQL进行隐式的类型转换, 最好把类型转换用显式表现出来. 注意当字符和数值比较时, ORACLE会优先转换数值类型到字符类型.

假设 EMPNO是一个数值类型的索引列.
SELECT …
FROM EMP
WHERE EMPNO = ‘123’
实际上,经过ORACLE类型转换, 语句转化为:
SELECT …
FROM EMP
WHERE EMPNO = TO_NUMBER(‘123’)
幸运的是,类型转换没有发生在索引列上,索引的用途没有被改变.

现在,假设EMP_TYPE是一个字符类型的索引列.
SELECT …
FROM EMP
WHERE EMP_TYPE = 123
这个语句被ORACLE转换为:
SELECT …
FROM EMP
WHERE TO_NUMBER(EMP_TYPE)=123
因为内部发生的类型转换, 这个索引将不会被用到!

识别’低效执行’的SQL语句

用下列SQL找出低效SQL:
SELECT EXECUTIONS , DISK_READS, BUFFER_GETS,
ROUND((BUFFER_GETS-DISK_READS)/BUFFER_GETS,2) Hit_radio,
ROUND(DISK_READS/EXECUTIONS,2) Reads_per_run,
SQL_TEXT
FROM V$SQLAREA
WHERE EXECUTIONS>0
AND BUFFER_GETS > 0
AND (BUFFER_GETS-DISK_READS)/BUFFER_GETS < 0.8
ORDER BY 4 DESC;

select * from (  
    select * from V$SQLSTATS        
    -- 最耗时的 SQL  
    -- ELAPSED_TIME 指的是总耗时(毫秒),平均耗时 = ELAPSED_TIME/EXECUTIONS  
    -- order by ELAPSED_TIME DESC  
      
    -- 查询执行次数最多的 SQL  
    -- order by EXECUTIONS DESC  
      
    -- 读硬盘最多的 SQL  
    -- order by DISK_READS DESC  
      
    -- 最费 CPU 的 SQL  
    -- order by BUFFER_GETS DESC  

) where rownum <=50; 

查找前十条性能差的sql
SELECT * FROM
(
SELECT PARSING_USER_ID
EXECUTIONS,
SORTS,
COMMAND_TYPE,
DISK_READS,
sql_text
FROM v$sqlarea
ORDER BY disk_reads DESC
) WHERE ROWNUM<10 ;

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
数仓中常用的SQL查询技巧有很多,以下是一些常见的技巧和建议: 1. 使用窗口函数:窗口函数(Window Function)是SQL中强大的功能之一,它可以在查询结果中对数据集进行分组、排序和聚合操作,常用的窗口函数包括RANK、ROW_NUMBER、LEAD、LAG等。 2. 优化查询性能:在处理大规模数据时,优化查询性能是非常重要的。可以通过创建合适的索引、避免全表扫描、使用合适的连接方式等方式来提高查询效率。 3. 使用子查询:子查询(Subquery)可以嵌套在主查询中,用于限制结果集或作为计算字段的来源。使用子查询可以简化复杂的查询逻辑,并提高可读性。 4. 使用临时表或表变量:当需要多次使用相同的结果集时,可以将查询结果存储在临时表或表变量中,避免重复查询和计算,提高性能。 5. 使用CTE(Common Table Expression):CTE是一种临时命名的查询结果集,可以在查询中多次引用,提高可读性和维护性。 6. 使用合适的连接方式:在进行表之间的关联查询时,选择合适的连接方式(如INNER JOIN、LEFT JOIN、RIGHT JOIN等)可以确保查询结果正确且高效。 7. 利用索引进行查询优化:合理创建和使用索引可以加快查询速度,尤其是在大型数据表中。根据查询的字段和条件,选择合适的索引策略,可以显著提高查询性能。 8. 使用视图(View):视图是一种虚拟的表,可以将复杂的查询逻辑封装为一个视图,使查询更简洁、可复用。 9. 使用合适的聚合函数:根据需要,选择合适的聚合函数(如SUM、AVG、COUNT、MAX、MIN等)进行数据统计和分析。 10. 使用合适的数据类型和字段命名:选择合适的数据类型可以节省存储空间和提高查询效率,良好的字段命名可以提高代码可读性和维护性。 这些只是一些常见的SQL查询技巧,实际用中还会根据具体场景和需求进行调整和优化。希望对您有所帮助!

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值