Oracle中基于hint的3种执行计划控制方法详细介绍

yizhihongxing

首先,我们需要明确什么是执行计划。执行计划是数据库在执行SQL语句时的一种预估性的计划,它会告诉我们数据库在执行该SQL语句时的具体操作步骤和执行顺序。通过调整执行计划,我们可以优化SQL语句的性能。

在Oracle数据库中,基于hint的3种执行计划控制方法包括:

  1. 使用INLINE提升性能

INLINE是一个hint,它可以让Oracle把一些短小简单的SQL代码嵌入到调用它们的SQL块中,可以减少操作的时间和I/O等待时间。这个hint应该只用于简单的SQL语句,如:

SELECT /*+ INLINE(w) */ w.worker_id, w.first_name, w.last_name, w.job_title
FROM workers w
WHERE w.job_title = 'Manager'
ORDER BY w.last_name, w.first_name;

这段代码中,我们使用了INLINE hint来嵌入SQL语句,提升查询的性能。

  1. 使用INDEX提示强制使用索引

有时候,Oracle的优化器会决定不使用索引来执行查询语句,从而导致性能下降。在这种情况下,我们可以使用INDEX hint来强制使用索引,如:

SELECT /*+ INDEX(w, workers_idx) */ w.worker_id, w.first_name, w.last_name, w.job_title
FROM workers w
WHERE w.job_title = 'Manager'
ORDER BY w.last_name, w.first_name;

这段代码中,我们使用了INDEX hint来强制使用名为workers_idx的索引,以提高查询性能。

  1. 使用FULL提示强制全表扫描

相比使用索引,有时候全表扫描可能更快。在这种情况下,我们可以使用FULL hint来强制进行全表扫描,如:

SELECT /*+ FULL(w) */ w.worker_id, w.first_name, w.last_name, w.job_title
FROM workers w
WHERE w.job_title = 'Manager'
ORDER BY w.last_name, w.first_name;

这段代码中,我们使用FULL hint来强制进行全表扫描,以提高查询性能。

以上就是基于hint的3种执行计划控制方法。在使用这些hint时,需要注意,最好只在知晓其效果后才使用。如果过度使用或误用这些hint,可能会导致SQL语句性能下降。同时也需要了解各个hint的语法和功能特点。

示例1:

原始查询语句如下:

SELECT w.worker_id, w.first_name, w.last_name, w.job_title
FROM workers w
WHERE w.job_title = 'Manager'
ORDER BY w.last_name, w.first_name;

查询计划如下:

Execution Plan  
----------------------------------------------------------
Plan hash value: 2005743770

---------------------------------------------------------------------------
| Id  | Operation          | Name    | Rows  | Bytes | Cost (%CPU)| Time     |
---------------------------------------------------------------------------
|   0 | SELECT STATEMENT   |         |     4 |   192 |     2   (0)| 00:00:01 |
|*  1 |  TABLE ACCESS FULL | WORKERS |     4 |   192 |     2   (0)| 00:00:01 |
---------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   1 - filter("JOB_TITLE"='Manager')

Statistics
-----------------------------------------------------------
          0  recursive calls
          0  db block gets
          3  consistent gets
          0  physical reads
          0  redo size
        747  bytes sent via SQL*Net to client
        573  bytes received via SQL*Net from client
          1  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
          4  rows processed

可以看到,执行计划是使用了全表扫描操作来执行查询。

现在我们使用FULL hint强制全表扫描,查询语句如下:

SELECT /*+ FULL(w) */ w.worker_id, w.first_name, w.last_name, w.job_title
FROM workers w
WHERE w.job_title = 'Manager'
ORDER BY w.last_name, w.first_name;

查询计划如下:

Execution Plan  
----------------------------------------------------------
Plan hash value: 2005743770

-------------------------------------------------------------
| Id  | Operation         | Name    | Rows | Bytes | Cost (%CPU)| Time    |
-------------------------------------------------------------
|   0 | SELECT STATEMENT  |         |    4 |   192 |     2   (0)| 00:00:01|
|   1 |  TABLE ACCESS FULL| WORKERS |    4 |   192 |     2   (0)| 00:00:01|
-------------------------------------------------------------

Statistics
-----------------------------------------------------------
          0  recursive calls
          0  db block gets
          3  consistent gets
          0  physical reads
          0  redo size
        747  bytes sent via SQL*Net to client
        573  bytes received via SQL*Net from client
          1  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
          4  rows processed

可以看到,执行计划并未发生变化,这说明本身就是最优执行计划。

示例2:

原始查询语句如下:

SELECT d.department_id, COUNT(w.worker_id)
FROM departments d
JOIN workers w ON w.department_id = d.department_id
WHERE d.department_name = 'Sales'
GROUP BY d.department_id;

查询计划如下:

Execution Plan  
----------------------------------------------------------
Plan hash value: 183478260

---------------------------------------------------------------------------
| Id  | Operation          | Name       | Rows  | Bytes | Cost (%CPU)| Time     |
---------------------------------------------------------------------------
|   0 | SELECT STATEMENT   |            |     1 |    22 |     3   (0)| 00:00:01 |
|   1 |  SORT GROUP BY     |            |     1 |    22 |     3   (0)| 00:00:01 |
|*  2 |   HASH JOIN        |            |    14 |   308 |     2   (0)| 00:00:01 |
|   3 |    TABLE ACCESS FULL| DEPARTMENTS|     1 |    11 |     1   (0)| 00:00:01 |
|   4 |    TABLE ACCESS FULL| WORKERS    |   107 |  2675 |     1   (0)| 00:00:01 |
---------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   2 - access("W"."DEPARTMENT_ID"="D"."DEPARTMENT_ID")

Statistics
-----------------------------------------------------------
          0  recursive calls
          0  db block gets
         26  consistent gets
          0  physical reads
          0  redo size
        556  bytes sent via SQL*Net to client
        546  bytes received via SQL*Net from client
          2  SQL*Net roundtrips to/from client
          1  sorts (memory)
          0  sorts (disk)
          1  rows processed

可以看到,执行计划使用了HASH JOIN操作,因为这个查询需要把两个大表进行连接。

现在我们使用INLINE hint嵌入到查询语句中,查询语句如下:

SELECT /*+ INLINE(d) */ d.department_id, COUNT(w.worker_id)
FROM departments d /*+ INLINE */ JOIN workers w /*+ INLINE */
    ON w.department_id = d.department_id
WHERE d.department_name = 'Sales' /*+ INLINE */
GROUP BY d.department_id;

查询计划如下:

Execution Plan  
----------------------------------------------------------
Plan hash value: 2362383159

------------------------------------------------------------
| Id  | Operation         | Name        | Rows | Bytes | Cost (%CPU)| Time     |
------------------------------------------------------------
|   0 | SELECT STATEMENT  |             |     1 |    30 |     3   (0)| 00:00:01 |
|   1 |  HASH GROUP BY    |             |     1 |    30 |     3   (0)| 00:00:01 |
|   2 |   NESTED LOOPS    |             |    14 |   420 |     2   (0)| 00:00:01 |
|*  3 |    TABLE ACCESS   | WORKERS     |     7 |   161 |     1   (0)| 00:00:01 |
|*  4 |     INDEX UNIQUE  | WORKERS_PK  |     1 |       |     1   (0)| 00:00:01 |
|*  5 |    TABLE ACCESS   | DEPARTMENTS |     2 |    22 |     1   (0)| 00:00:01 |
----------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   3 - filter("DEPARTMENT_NAME"='Sales')
   4 - access("W"."DEPARTMENT_ID"="D"."DEPARTMENT_ID")
   5 - filter("D"."DEPARTMENT_NAME"='Sales')

Note
-----
   - inline SQL tuning starts here

Statistics
-----------------------------------------------------------
          0  recursive calls
          0  db block gets
         18  consistent gets
          0  physical reads
          0  redo size
        556  bytes sent via SQL*Net to client
        546  bytes received via SQL*Net from client
          2  SQL*Net roundtrips to/from client
          1  sorts (memory)
          0  sorts (disk)
          1  rows processed

可以看到,执行计划使用了NESTED LOOPS和HASH GROUP BY操作,从而使查询更快地运行。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Oracle中基于hint的3种执行计划控制方法详细介绍 - Python技术站

(0)
上一篇 2023年5月21日
下一篇 2023年5月21日

相关文章

  • dns是什么意思?dns怎么设置(手动设置/软件设置)

    DNS(Domain Name System)是指域名系统,它是网络传输的基础,它负责将人类可以理解的域名解析为计算机可理解的IP地址,使得计算机之间可以进行通讯。常用的DNS域名解析服务有阿里云、腾讯云等。 DNS设置可以手动设置和使用软件进行设置,以下是具体步骤: 手动设置DNS Windows系统 打开控制面板 选择“网络和共享中心”(或者“网络和 I…

    database 2023年5月19日
    00
  • Redis如何在项目中合理使用经验分享

    下面是Redis在项目中合理使用的攻略,主要包括以下几个方面: 1. Redis在项目中的应用场景 Redis是一种高性能的NoSql数据库,常被用于解决一些数据读取和缓存的问题,例如: 高并发数据读取功能,例如使用Redis缓存热门文章、商品等数据内容,减轻MySQL等数据库的读取压力,提高网站的访问速度和性能; 缓存系统功能,例如使用Redis作为ses…

    database 2023年5月22日
    00
  • Linux系统(X64)安装Oracle11g完整安装图文教程另附基本操作

    Linux系统(X64)安装Oracle11g完整安装图文教程 简介 本文将给各位读者提供详细说明,关于在Linux系统(X64)上安装Oracle11g的完整安装图文教程。旨在为读者提供一份详细的安装攻略。本攻略内容包括Oracle11g的基本操作,以及在Linux系统下Oracle11g的配置等。本文将从以下几个方面对Oracle11g进行详细讲解: 环…

    database 2023年5月22日
    00
  • MySQL创建触发器(CREATE TRIGGER)方法详解

    MySQL中创建触发器的方法 在MySQL中,可以使用CREATE TRIGGER语句来创建触发器,其基本语法如下: CREATE TRIGGER trigger_name trigger_time trigger_event ON table_name FOR EACH ROW BEGIN — trigger body END; 其中,各个参数的含义如下…

    MySQL 2023年3月10日
    00
  • MySQL的索引你了解吗

    当访问MySQL中的表时,如果没有索引,每次查询时都需要全表扫描,这将导致查询速度变慢。索引可以帮助MySQL更快地定位到数据,减少查询时间。 索引的基础知识 索引是什么? 在MySQL中,数据表的索引类似于图书馆的书目索引。索引会存储着字段值和与之关联的行指针,以便于找到数据库表中的数据。 索引的类型有哪些? MySQL中支持多种不同类型的索引,包括B树索…

    database 2023年5月22日
    00
  • oracle丢失temp表空间的处理方法

    Oracle丢失TEMP表空间的处理方法 问题描述 在使用Oracle数据库时,如果由于某些原因导致TEMP表空间不可用,可能会导致一些SQL无法正常执行。例如,在执行某个需要使用TEMP表空间的大型查询时,会提示如下错误信息: ORA-01565: 妥善回滚数据文件‘/oracle/oradata/orcl/temp01.dbf’(0) ORA-01110…

    database 2023年5月18日
    00
  • PHP简单系统数据添加以及数据删除模块源文件下载

    下面就来详细讲解“PHP简单系统数据添加以及数据删除模块源文件下载”的完整攻略。 1. 下载源码 首先,你需要下载源码。可以在网站或论坛上搜索PHP简单系统数据添加以及数据删除模块的源码并下载,或者自己手动编写代码。 2. 添加数据模块 2.1. 数据库连接 在添加数据之前,需要先连接数据库。可以在源码中找到以下代码: $servername = &quot…

    database 2023年5月21日
    00
  • Derby 和 IBM Db2的区别

    Derby 和 IBM Db2都是关系型数据库管理系统(RDBMS),但它们有不同的特点和适用场景。 Derby Derby是一个基于Java的RDBMS,有很多特点: Derby是一个开源软件,可以免费获取。 Derby比较小巧,容易使用和部署,适合中小型应用。 Derby支持Java应用程序及JDBC。它的内置数据库引擎模块是承担基本的事务处理、崩溃恢复…

    database 2023年3月27日
    00
合作推广
合作推广
分享本页
返回顶部