自己遇到的一些SQL优化

字符的分隔

(思想,先构造在拼接)

SELECTa.id,b.NAME,A.WORK_TYPE,b."ID"

FROMCRD.T_CRD_SCORE_CONFIGa

leftJOINEMERP.T_BASE_WORK_TYPE_ALLbon','||A.WORK_TYPE||','like'%,'||b.id||',%'GROUPBYA.ID

分组函数:GROUP BY

  分组函数,可以多次分组

  提高GROUP BY 语句的效率,可以通过将不需要的记录在GROUP BY 之前过滤掉

子查询

   这次写代码的时候,有一些字段上线前着急要和实际的业务逻辑,使用了子查询,有的可以使用连接查询,但是没有优化

记录的标记字段

这次编写代码的时候,标记这条记录是否删除,使用,显示,在编写SQL的时候出现了一些漏写的字段,以后再写的时候,一定要注意全

表空间(用户)

在编写SQL的时候,没有注意在表前标记空间名(用户)。

OR的使用

OR一定要合理运用,总忘记这个

ORDER BY 的使用

1. 只有ORDER BY 子句中可以使用select列表中列的别名

2. 使用了ORDER BY子句的查询不能用作表表达式(视图、内联表值函数、子查询、派生表和共用表达式)

3. 在分页的时候,如果是多表连接的,要是条件排序的条件的值一致,在分页的时候可能两次的结果有重复数据。

exts和in用法

1. exists对外表做循环,每次循环对内表查询;in将内表和外表做hash连接

2. 使用exists oracle会先检查主查询,使用in,首先执行子查询,将结果存储在临时表中

3. 如果两个表大小相当,in和exists差别不大

4. 如果两个表大小相差较大则子查询表大的用exists,子查询表小的用in

5.尽量不要使用not in

union和union all

  1. 使用场景:需要将两个select语句结果整体显示时,可以使用union和unionall

2.union对两个结果集取并集不包含重复结果同时进行默认规则的排序;而union all对两个结果集去并集,包括  重复行,不进行排序

  3.union需要进行重复值扫描,效率低,如果没有要删除重复行,应该使用union all

  4.insersect和minus分别交集和差集,都不包括重复行,并且进行默认规则的排序

 5.可以将多个结果集合并

  6.必须保证select集合的结果有相同个数的列,并且每个列的类型是一样的(列名不一定要相同,会默认将第一个结果的列名作为结果集的列名)

指定where的条件顺序

1. 默认情况下,Oracle采用自下而上的顺序解析where字句,因此在处理多表查询的时候,表之间的连接必须写在其他的where条件之前,但是过滤数据记录的条件则必须写在where子句的尾部,以便在过滤了数据之后再进行连接处理,这样可以提升sql语句的性能

LEFT--JOIN  注释事项

在使用left-join的时候一定要注意顺序问题。

SQL语句尽量用大写的

因为oracle总是先解析SQL语句,把小写的字母转换成大写的再执行。

使用表的别名

    当在SQL语句中连接多个表时, 尽量使用表的别名并把别名前缀于每个列上。这样一来,就可以减少解析的时间并 减少那些由列歧义引起的语法错误。

选择最有效率的表名顺序(只在基于规则的优化器(RBO)中有效)

  ORACLE 的解析器按照从右到左的顺序处理FROM子句中的表名,FROM子句中写在最后的表(基础表也称为驱动表,driving table)将被最先处理,在FROM子句中包含多个表的情况下,必须选择记录条数最少的表作为基础表。如果有3个以上的表连接查询, 那就需要选择交叉表(intersection table)作为基础表, 交叉表是指那个被其他表所引用的表。

避免使用耗费资源的操作

 带有DISTINCT、UNION、MINUS、INTERSECT、ORDER BY的SQL语句会启动SQL引擎执行

耗费资源的排序(SORT)功能。DISTINCT需要一次排序操作,而其他的至少需要执行两次排序。

通常,带有UNION、MINUS、INTERSECT的SQL语句都可以用其他方式重写。

 如果数据库的SORT_AREA_SIZE调配得好,使用UNION,MINUS,INTERSECT也是可以考虑。 

用Where子句替换HAVING子句

    避免使用HAVING子句,HAVING只会在检索出所有记录之后才对结果集进行过滤。这个处理需要排序,总计等操作。最好能通过WHERE子句限制记录的数目。(非oracle中)on、where、having这三个都可以加条件的子句中,on是最先执行,where次之,having最后。

避免在索引列上使用计算

  WHERE子句中,如果索引列是函数的一部分,优化器将不使用索引而使用全表扫描。

BETWEEN    AND

取值是两边都要。

NVL2(expr1,expr2,expr3)

NVL2(表达式,不为空设值,为空设值)

to_char用法

(1)用作日期转换

    to_char(date,'格式');

    select to_char(sysdate,'yyyy-MM-dd HH24:mi:ss') from dual;

(2)处理数字

    to_char(number,'格式');

     select to_char(88877) from dual;

     select to_char(1234567890,'099999999999999')  from dual;

     select to_char(12345678,'999,999,999,999')  from dual;

     select to_char(123456,'99.999')  from dual;

     select to_char(1234567890,'999,999,999,999.9999')  from dual;

(3) 处理钱

    to_char(salary,'$99,99');

  select TO_CHAR(123,'$99,999.9') from dual;

(4)用于进制转换:将10进制转换为16进制;

    select to_char(4567,'xxxx') from dual;

    select to_char(123,'xxx') from dual;

to_date

select sysdate,to_date('20170615','yyyymmdd')from dual;

select sysdate,to_date('20170615','yyyy-mm-dd')from dual;

select sysdate,to_date('20170615','yyyy/mm/dd')from dual;

select sysdate,to_date('20170615','yyyy-mm-dd hh24:mi:ss')from dual;

应尽量避免在 where 子句中使用 or 来连接条件

select id from t where num=10 or Name = 'admin'

可以这样查询:

select id from t where num = 10

union all

select id from t where Name = 'admin'

模糊查询

当模糊匹配以%开头时,该列索引将失效,若不以%开头,该列索引有效。

常用函数

FLOOR(x)   返回小于x的最大整数值

AVG(col)返回指定列的平均值

COUNT(col)返回指定列中非NULL值的个数

MIN(col)返回指定列的最小值

MAX(col)返回指定列的最大值

SUM(col)返回指定列的所有值之和

LEFT(str,x)返回字符串str中最左边的x个字符

TRIM(str)去除字符串首部和尾部的所有空格

UCASE(str)或UPPER(str) 返回将字符串str中所有字符转变为大写后的结果

优化总结口诀

​ 全值匹配我最爱,最左前缀要遵守;

​ 带头大哥不能死,中间兄弟不能断;

​        索引列上少计算,范围之后全失效;

​ LIKE百分写最右,覆盖索引不写星;

​ 不等空值还有or,  索引失效要少用;

​        VAR引号不可丢,SQL高级也不难;

如何分析SQL

1.观察,至少跑一天,看看生产的慢SQL情况。

2.开启慢查询日志,设置阀值,比如超过5秒钟就是慢SQL,并将它抓取出来

3.explain+慢SQL分析

4.show profile

5.DBA进行SQL数据库服务器的参数调优

总结:

1.慢查询的开启并捕获

2.explain+慢SQL分析

3.show profile查询SQL在MySql里面的执行细节和生命周期情况

4.SQl数据服务器的参数调优

你可能感兴趣的:(自己遇到的一些SQL优化)