zoukankan      html  css  js  c++  java
  • SQL优化

    开发初期数据较少,体现不出SQL性能的优劣,随着数据量的增加,优质SQL和劣质SQL之间的性能就会有很大差别

    一般情况下,Oracle是通过索引来更快的遍历表,优化器根据定义的索引来提高性能,但是,如果在where字句中的代码不合理,优化器会删去索引而进行全表扫描

    where字句中需要注意的问题:

    1. IS NULL 和IS NOT NULL
      不能用null做索引,任何包含null值的列都不会包含在索引中
      在where字句中使用is null 或is not null 优化器是不允许使用索引的
    2. 联接列
      select * from employss where first_name||”||last_name =’Beill Cliton';优化器没有使用基于last_name创建的索引
      select * from employss where first_name =’Beill’ and last_name =’Cliton';这样就可以使用基于last_name创建的索引
    3. 通配符%的LIKE语句
      通配符在词首,优化器不会使用索引
      select * from employee where last_name like ‘%cliton%';
      通配符出现在字符串的其他位置 优化器就可以使用索引
      select * from employee where last_name like ‘c%';
    4. Order by子句
      Order by子句中的非索引项和计算表达式都会降低查询速度
      解决:为Order by使用的列建立另外一个索引,同时避免在Order by中使用表达式
    5. NOT
      where not (status =’VALID’)等价于where status <>’INVALID   即使不显示的用NOT, NOT也在运算符中

      select * from employee where salary<3000 or salary>3000;
      这种不实用NOT的 查询速度较快,因为可以对salary使用索引

     http://blog.csdn.net/timliang18601860/article/details/6724857

    https://www.cnblogs.com/alsf/p/6144798.html

    SQL优化总结:

    1. 选择最有效率的表名顺序
      Oracle解析器是从右到左处理from子句中的表的,from子句中写在最后的表是基础表,最先被处理
      多表情况下,选择记录条数最少的表作为基础表
      三个以上的表连接查询,使用交叉表作为基础表,交叉表是被其他表所引用的那个表

    2. where子句中的连接顺序
      Oracle是自下而上的顺序解析where子句,所以在where子句中,表之间的连接写在前面,那些可以过滤掉最大量数据的条件写在后面

    3. select子句中避免使用 * 
      Oracle通过查询数据字典,把* 依次转换成所有的列名,会耗费大量时间

      Oracle内部要执行很多工作,解析SQL语句,估算索引的利用率,绑定变量,读数据块等,所以要减少访问数据库的次数,减少工作量

      设置SQL*Plus , SQL*Forms和Pro*C的ARRAYSIZE参数,建议值200,可以增加每次访问数据库的检索数据量

    4. 使用DECODE函数来减少处理时间
      主要作用:将查询结果翻译成其他值 如:decode(columnname,值1,翻译值1,值2,翻译值2,...值n,翻译值n,缺省值)
    5.  删除重复记录



    6. 用TRUNCATE替代DELETE
      删除表中的所有行
      truncate速度比delete快

    7. 尽量多使用COMMIT
      性能得到提高,因为commit会释放资源

    8. 减少对表的查询

    9. 用EXISTS替代IN  用NOT EXISTS替代NOT IN 

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

    11. 用索引提高效率
      通过索引查询数据比全表扫描要快

    12. 用EXISTS替换DISTINCT
      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) 高效

    13. 使用大写
      Oracle会解析SQL语句,然后将小写转换为大写再执行

    14. java代码中尽量少用连接符“+”连接字符串

    15. 避免在索引列上使用NOT
      Oracle遇到NOT时,会停止使用索引,转而执行全表扫描

    16. 避免在索引列上使用计算
      低效:SELECT … FROM DEPT WHERE SAL * 12 > 25000; 
      高效:SELECT … FROM DEPT WHERE SAL > 25000/12;

    17. >=替代>
      低效:SELECT * FROM EMP WHERE DEPTNO >3  
      高效:SELECT * FROM EMP WHERE DEPTNO >=4  

    18. UNION替换OR (适用于索引列)
      对索引列使用OR会造成全表扫描
      低效:  
      SELECT LOC_ID , LOC_DESC , REGION FROM LOCATION WHERE LOC_ID = 10 OR REGION = “MELBOURNE”
      高效:
      SELECT LOC_ID , LOC_DESC , REGION  FROM LOCATION  WHERE LOC_ID = 10  
      UNION  
      SELECT LOC_ID , LOC_DESC , REGION  FROM LOCATION  WHERE REGION = “MELBOURNE”


    19. IN替换OR
      低效:  
      SELECT…. FROM LOCATION WHERE LOC_ID = 10 OR LOC_ID = 20 OR LOC_ID = 30
      高效  
      SELECT… FROM LOCATION WHERE LOC_IN IN (10,20,30);

    20. 避免在索引列上使用IS NULL和IS NOT NULL
      低效: (索引失效)  
      SELECT … FROM DEPARTMENT WHERE DEPT_CODE IS NOT NULL;  
      高效: (索引有效)  
      SELECT … FROM DEPARTMENT WHERE DEPT_CODE >=0;

    21. 总是使用索引的第一个列
      如果索引是建立在多个列上, 只有在它的第一个列(leading column)被where子句引用时,优化器才会选择使用该索引. 这也是一条简单而重要的规则,当仅引用索引的第二个列时,优化器使用了全表扫描而忽略了索引

    22. UNION-ALL 替换UNION
      用UNION ALL替代UNION, 这样排序就不是必要了. 效率就会因此得到提高

    23. WHERE替代ORDER BY
      ORDER BY 子句只在两种严格的条件下使用索引.  
      ORDER BY中所有的列必须包含在相同的索引中并保持在索引中的排列顺序.  
      ORDER BY中所有的列必须定义为非空.  
      WHERE子句使用的索引和ORDER BY子句中所使用的索引不能并列.
      例如:  
      表DEPT包含以下列:  
      DEPT_CODE PK NOT NULL  
      DEPT_DESC NOT NULL  
      DEPT_TYPE NULL
      低效: (索引不被使用)  
      SELECT DEPT_CODE FROM DEPT ORDER BY DEPT_TYPE  
      高效: (使用索引)  
      SELECT DEPT_CODE FROM DEPT WHERE DEPT_TYPE > 0

    24. 避免改变索引列的类型
      当比较不同数据类型的数据时, 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 WHERETO_NUMBER(EMP_TYPE)=123  
      因为内部发生的类型转换, 这个索引将不会被用到! 为了避免ORACLE对你的SQL进行隐式的类型转换, 最好把类型转换用显式表现出来. 注意当字符和数值比较时, ORACLE会优先转换数值类型到字符类型

    25. 需要当心的WHERE子句
      某些SELECT 语句中的WHERE子句不使用索引. 这里有一些例子.  
      (1)‘!=' 将不使用索引. 记住, 索引只能告诉你什么存在于表中, 而不能告诉你什么不存在于表中.
      (2) ‘||'是字符连接函数. 就象其他函数那样, 停用了索引.
      (3) ‘+'是数学函数. 就象其他数学函数那样, 停用了索引.
      (4)相同的索引列不能互相比较,这将会启用全表扫描.


    26. a. 如果检索数据量超过30%的表中记录数.使用索引将没有显著的效率提高.  
      b. 在特定情况下, 使用索引也许会比全表扫描慢, 但这是同一个数量级上的区别. 而通常情况下,使用索引比全表扫描要块几倍乃至几千倍

    27. 避免使用耗费资源的操作:
      带有DISTINCT,UNION,MINUS,INTERSECT,ORDER BY的SQL语句会启动SQL引擎  
      执行耗费资源的排序(SORT)功能. DISTINCT需要一次排序操作, 而其他的至少需要执行两次排序. 通常, 带有UNION, MINUS , INTERSECT的SQL语句都可以用其他方式重写. 如果你的数据库的SORT_AREA_SIZE调配得好, 使用UNION , MINUS, INTERSECT也是可以考虑的, 毕竟它们的可读性很强

    28. 优化GROUP BY:
      提高GROUP BY 语句的效率, 可以通过将不需要的记录在GROUP BY 之前过滤掉
      低效:  
      SELECT JOB , AVG(SAL)  
      FROM EMP  
      GROUP by JOB  
      HAVING JOB = ‘PRESIDENT'  
      OR JOB = ‘MANAGER'  
      高效:  
      SELECT JOB , AVG(SAL)  
      FROM EMP  
      WHERE JOB = ‘PRESIDENT'  
      OR JOB = ‘MANAGER'  
      GROUP by JOB
  • 相关阅读:
    【Leetcode】23. Merge k Sorted Lists
    【Leetcode】109. Convert Sorted List to Binary Search Tree
    【Leetcode】142.Linked List Cycle II
    【Leetcode】143. Reorder List
    【Leetcode】147. Insertion Sort List
    【Leetcode】86. Partition List
    jenkins 配置安全邮件
    python 发送安全邮件
    phpstorm 同步远程服务器代码
    phpUnit 断言
  • 原文地址:https://www.cnblogs.com/gucl/p/8284025.html
Copyright © 2011-2022 走看看