ORACLE 查询SQL优化

1 使用EXPLAIN PLAN

使用EXPLAIN PLAN查看查询的执行计划,这可以帮助你理解查询是如何被Oracle执行的。基于执行计划,你可以确定是否存在索引缺失、不必要的全表扫描等问题。

以下是几种使用EXPLAIN PLAN的方法:

使用EXPLAIN PLAN FOR:

你可以在SQL*Plus、SQL Developer或其他Oracle工具中运行以下命令:

|-----------------------------------------------------------------------------------------------------------------------------|
| EXPLAIN PLAN FOR ``SELECT * FROM your_table WHERE your_column = 'some_value'; SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY); |

第一条命令为指定的SQL查询生成执行计划,但它不会直接显示结果。第二条命令使用DBMS_XPLAN.DISPLAY来格式化并显示执行计划。

格式化执行计划输出:

使用DBMS_XPLAN.DISPLAY时,你可以使用各种选项来格式化输出。例如,要显示详细的执行计划并包括统计信息,你可以这样做:

|------------------------------------------------------------------------------------|
| SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY(FORMAT=>'ALLSTATS PREDICATE LAST COST')); |

这将显示执行计划的每个步骤,包括它们的成本、估计的行数、使用的索引等。

FORMAT还有一些附加的选项可用于定制化输出行为,使用中可以通过逗号和空格分隔来声明多个关键字,同时可以使用"+"和"-"符号来包含或排除相应的显示元素,这些附加的选项在官方文档中可以查到:

1.ROWS -- 显示被优化器估算的记录的行号
2.BYTES -- 显示优化器估算的字节数
3.COST -- 显示优化器计算的成本信息
4.PARTITION -- 显示分区的分割信息
5.PARALLEL -- 显示并行执行信息
6.PREDICATE -- 显示谓语
7.PROJECTION -- 显示列投影部分(每一行的那些列被传递给其父列已经这些列的大小)
8.ALIAS -- 显示查询块名称已经对象别名
9.REMOTE -- 显示分布式查询信息
10.NOTE -- 显示注释
11.IOSTATS -- 显示游标执行的IO统计信息
12.MEMSTATS -- 为内存密集运算如散列联结,排序,或一些类型的位图运算显示内存管理统计信息
13.ALLSTATS -- 与'IOSTATS MEMSTATS'等价
14.LAST -- 显示最后执行的执行计划统计信息,默认显示为ALL类型,并且可以累积。

查看特定SQL ID的执行计划:

如果你知道SQL语句的SQL ID(通常可以在AWR报告或V$SQL视图中找到),你可以使用DBMS_XPLAN.DISPLAY_CURSOR来查看其执行计划:

|------------------------------------------------------------------------------|
| SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY_CURSOR('your_sql_id', 'ALLSTATS')); |

请注意替换'your_sql_id'为你想要查看的SQL语句的ID。

清除之前的执行计划:

如果你之前为多个查询生成了执行计划,并希望清除它们以便为新的查询生成执行计划,你可以使用以下命令:

|------------------------------------------|
| EXECUTE DBMS_XPLAN.CLEAR_PLAN_TABLE(); |

这将清除PLAN_TABLE$(存储执行计划的地方)中的内容。注意,这可能会影响到其他会话中正在查看的执行计划。

在SQL*Plus中使用AUTOTRACE:

在SQL*Plus中,你可以使用SET AUTOTRACE ON来自动显示查询的执行计划:

|--------------------------------------------------------------------------------------------|
| SET AUTOTRACE ON EXPLAIN ``SELECT * FROM your_table WHERE your_column = 'some_value'; |

这将执行查询并显示其执行计划。

使用SQL Developer等图形化执行计划

如果你使用Oracle SQL Developer,你可以直接点击查询结果上方的"执行计划"选项卡来查看图形化的执行计划(或者快捷键,如PL/SQL快捷键为"F5")。SQL Developer会自动为你生成并显示执行计划。

2 索引优化

  • 确保在经常用于搜索、排序和连接的列上创建了索引。
  • 避免在索引列上使用函数或表达式,这可能导致索引失效。
  • 定期审查和维护索引,删除不必要的索引,因为索引也会占用存储空间并影响插入、更新和删除操作的性能。
  • 多表查询关联时,关联条件字段数据类型不一致时,可能会导致索引失效,尽量保证关联的索引字段数据类型保持一致。

3 SQL语句优化

  • 尽量减少SELECT语句中选择的列数,只选择需要的列。

  • 使用IN代替多个OR条件。

  • 使用连接(JOIN)代替子查询,当可能时。

  • 避免在WHERE子句中使用非SARGable(Search ARGumentable)表达式,这些表达式不能有效地利用索引。

  • 避免SELECT *,使用SELECT* 会返回表中的所有列,这可能会消耗更多的I/O资源。只选择需要的列。

  • 通过创建适当的索引和优化查询来减少全表扫描。

  • 对于大型查询,考虑使用Oracle的并行查询功能来加速查询的执行。这可以在多个CPU或磁盘上并行处理查询。

  • 当用到子查询时,子查询中的查询条件最好使用主查询中结果集最少的表,避免大结果集匹配子查询;当可能时,可在条件中加入 rownum=1,如:

    sql 复制代码
    --使用
    select (select itable.col0 from itable where itable.col1 = table1.col1) as result
      from table1, table2
     where table1.col2 = 'xx'
       and table1.col1 = table2.col1;
    
    --不使用
    select (select itable.col0 from itable where itable.col1 = table2.col1) as result
      from table1, table2
     where table1.col2 = 'xx'
       and table1.col1 = table2.col1;
    
    --使用
    select (select itable.col0
              from itable
             where itable.col1 = table1.col1
               and rownum = 1) as result
      from table1, table2
     where table1.col2 = 'xx'
       and table1.col1 = table2.col1;
    
    --不使用
    select (select itable.col0 from itable where itable.col1 = table1.col1) as result
      from table1, table2
     where table1.col2 = 'xx'
       and table1.col1 = table2.col1;

4 分区

对于非常大的表,考虑使用分区来提高查询性能。分区允许你将数据分成更小的、更易于管理的片段,每个片段可以独立存储、备份和索引。


Oracle提供了多种分区方法,包括范围分区、列表分区、散列分区和复合分区等。以下是各种分区方法的简要说明:

  1. 范围分区:根据表中某个列的值的范围将数据划分为不同的分区。例如,可以根据日期范围将销售数据划分为不同的季度或年份分区。

    • 优点:适用于可以按自然范围进行分区的表,如时间序列数据。
    • 示例:PARTITION BY RANGE (sales_date) (PARTITION p1 VALUES LESS THAN (TO_DATE('2023-01-01','YYYY-MM-DD')))
  2. 列表分区:明确指定要包含在特定分区中的值的列表。与范围分区不同,列表分区支持基于非连续或不规则的值进行分区。

    • 优点:适用于需要明确控制行如何映射到分区的场景。
    • 示例:PARTITION BY LIST (region) (PARTITION reg1 VALUES ('North', 'South'), PARTITION reg2 VALUES ('East', 'West'))
  3. 散列分区:根据指定的散列函数将数据均匀地分布到不同的分区中。这通常用于确保数据的均匀分布和负载平衡。

    • 优点:自动将数据均匀分布到不同的分区中,无需手动指定范围或值。
    • 示例:PARTITION BY HASH (employee_id) (PARTITIONS 4)
  4. 复合分区:结合使用范围分区和列表分区或散列分区的方法。通常首先使用范围分区将数据划分为较大的逻辑部分,然后在每个范围内使用列表或散列分区进行更细粒度的划分。

    • 优点:结合了范围分区和列表/散列分区的优点,提供了更灵活的数据划分方式。

如何对已有表进行分区

对于已经存在的表,Oracle提供了在线重定义表的功能来将其转换为分区表。这通常涉及创建一个新的分区表,然后将原始表的数据复制到新表中,并重新命名或删除原始表。这个过程可以在数据库正常运行时进行,但可能需要一些时间和资源。

查询分区信息

可以使用Oracle提供的数据字典视图(如DBA_TAB_PARTITIONSUSER_TAB_PARTITIONS等)来查询有关分区表的信息,包括分区的名称、大小、存储参数等。


5 数据库统计信息

确保定期收集表和索引的统计信息,因为Oracle优化器使用这些统计信息来选择最佳的执行计划。

6 使用绑定变量

在PL/SQL代码或JDBC/ODBC等接口中,使用绑定变量而不是硬编码值,这可以减少硬解析的数量,并提高性能。

7 使用Oracle的SQL调优顾问

Oracle提供了SQL调优顾问(SQL Tuning Advisor),它可以分析SQL语句并提供可能的优化建议。

8 考虑物化视图

对于复杂的查询或聚合操作,考虑使用物化视图来存储预计算的结果。这可以加快查询速度,但请注意,物化视图需要定期刷新以保持数据的准确性。

硬件和配置优化

确保数据库服务器具有足够的RAM、CPU和磁盘I/O资源。此外,检查Oracle的配置参数,如SGA(系统全局区)的大小,以确保它们已针对你的工作负载进行了优化。

定期维护

定期运行数据库维护任务,如重新构建索引、更新统计信息、清理碎片化的数据等,以保持数据库的最佳性能。

监控和诊断

使用Oracle的性能监控工具(如AWR、ASH、ADDM等)来监控数据库的性能并诊断潜在的问题。这些工具可以提供关于查询性能、等待事件、资源消耗等方面的详细信息。

相关推荐
小宇成长录4 分钟前
Mysql:数据库和表增删查改基本语句
数据库·mysql·数据库备份
团儿.1 小时前
解锁MySQL高可用新境界:深入探索MHA架构的无限魅力与实战部署
数据库·mysql·架构·mysql之mha架构
程序猿小D1 小时前
第二百六十七节 JPA教程 - JPA查询AND条件示例
java·开发语言·前端·数据库·windows·python·jpa
权^2 小时前
MySQL--聚合查询、联合查询、子查询、合并查询(上万字超详解!!!)
大数据·数据库·学习·mysql
OLDERHARD2 小时前
Java - MyBatis(上)
java·oracle·mybatis
Code成立2 小时前
1、深入理解Redis线程模型
数据库·redis·bootstrap
缘友一世4 小时前
macos安装mongodb
数据库·mongodb·macos
万事大吉CC6 小时前
mysql单表查询·3
数据库·mysql
bin91536 小时前
【EXCEL数据处理】000010 案列 EXCEL文本型和常规型转换。使用的软件是微软的Excel操作的。处理数据的目的是让数据更直观的显示出来,方便查看。
大数据·数据库·信息可视化·数据挖掘·数据分析·excel·数据可视化
Miqiuha7 小时前
lock_guard和unique_lock学习总结
java·数据库·学习