[Oracle]-[索引][HINT][执行计划]-带HINT的索引执行计划

谭老师的《Oracle 10g
性能分析与优化思路》第六章hint部分介绍:
举例:
create table t(id int);
create index t_idx on t(id);

SQL> select /*+ index(t t_idx) */ count(*) from t;

Execution Plan

----------------------------------------------------------

Plan hash value: 4075463224

-------------------------------------------------------------------

| Id  | Operation          | Name | Rows  | Cost (%CPU)| Time     |

-------------------------------------------------------------------

|   0 | SELECT STATEMENT   |      |     1 |     2   (0)| 00:00:01 |

|   1 |  SORT AGGREGATE    |      |     1 |            |          |

|   2 |   TABLE ACCESS FULL| T  |     3 |     2   (0)| 00:00:01 |

-------------------------------------------------------------------

Note

-----

   - dynamic sampling used for this statement

这里忽略了HINT,解释是:因为我们要对表的记录求总数,我们创建的索引并没有指定索引字段T不能为空,所以如果CBO选择在索引上做COUNT,当索引字段上有空值时,COUNT的结果必然不准确。

SQL> select /*+ index(t, t_idx) */ count(id) from t;

Execution Plan

----------------------------------------------------------

Plan hash value: 4235589928

----------------------------------------------------------------------------

| Id  | Operation        | Name    | Rows  | Bytes | Cost (%CPU)| Time     |

----------------------------------------------------------------------------

|   0 | SELECT STATEMENT |         |     1 |    13 |     1   (0)| 00:00:01 |

|   1 |  SORT AGGREGATE  |         |     1 |    13 |            |          |

|   2 |   INDEX FULL SCAN| T_IDX |     3 |    39 |     1   (0)| 00:00:01 |

----------------------------------------------------------------------------

Note

-----

   - dynamic sampling used for this statement

这里用到了HINT,解释是:因为我们只是对X字段做COUNT,id字段是索引字段,这个动作相当于COUNT索引上的所有id的键值,这个结果和对表上id字段做COUNT是一样的。

这点我觉得不是很准确。

如果是唯一性索引,则count(*)==count(索引字段)。

如果不是非唯一索引,则列中NULL值不会存入索引,因此count(*)>=count(索引字段)。

再做个实验:

CREATE TABLE TBL_SMALL
(ID   NUMBER,
NAME VARCHAR2(5)
);
SQL> create index t_s_idx on tbl_small(id);

create table tbl_big as select rownum id, object_name name from dba_objects where rownum<1000;
SQL> create index t_b_idx on tbl_big(id);
insert into tbl_big values('', '');

>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
SQL> select * from tbl_small;
        ID NAME
---------- -----
         2 b

         1 a

SQL> select count(*) from tbl_small;
  COUNT(*)
----------
         3

SQL> select count(id) from tbl_small;
COUNT(ID)
----------
         2

SQL> select count(*) from tbl_big;
  COUNT(*)
----------
      1000

SQL> select count(id) from tbl_big;
COUNT(ID)
----------
       999

SQL> set autot trace exp
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
TBL_SMALL表:

SQL> select count(*) from tbl_small;
Execution Plan
----------------------------------------------------------
Plan hash value: 1452584873

------------------------------------------------------------------------
| Id  | Operation          | Name      | Rows  | Cost (%CPU)| Time     |
------------------------------------------------------------------------
|   0 | SELECT STATEMENT   |           |     1 |     2   (0)| 00:00:01 |
|   1 |  SORT AGGREGATE    |           |     1 |            |          |
|   2 |   TABLE ACCESS FULL| TBL_SMALL |     3 |     2   (0)| 00:00:01 |
------------------------------------------------------------------------

Note
-----
   - dynamic sampling used for this statement

SQL> select count(id) from tbl_small;
Execution Plan
----------------------------------------------------------
Plan hash value: 1539159417

----------------------------------------------------------------------------
| Id  | Operation        | Name    | Rows  | Bytes | Cost (%CPU)| Time     |
----------------------------------------------------------------------------
|   0 | SELECT STATEMENT |         |     1 |    13 |     1   (0)| 00:00:01 |
|   1 |  SORT AGGREGATE  |         |     1 |    13 |            |          |
|   2 |   INDEX FULL SCAN| T_S_IDX |     3 |    39 |     1   (0)| 00:00:01 |
----------------------------------------------------------------------------

Note
-----
   - dynamic sampling used for this statement

SQL> select /*+ index(tbl_small, t_s_idx) */ count(*) from tbl_small;
Execution Plan
----------------------------------------------------------
Plan hash value: 1452584873

------------------------------------------------------------------------
| Id  | Operation          | Name      | Rows  | Cost (%CPU)| Time     |
------------------------------------------------------------------------
|   0 | SELECT STATEMENT   |           |     1 |     2   (0)| 00:00:01 |
|   1 |  SORT AGGREGATE    |           |     1 |            |          |
|   2 |   TABLE ACCESS FULL| TBL_SMALL |     3 |     2   (0)| 00:00:01 |
------------------------------------------------------------------------

Note
-----
   - dynamic sampling used for this statement

SQL> select /*+ index(tbl_small, t_s_idx) */ count(id) from tbl_small;
Execution Plan
----------------------------------------------------------
Plan hash value: 1539159417

----------------------------------------------------------------------------
| Id  | Operation        | Name    | Rows  | Bytes | Cost (%CPU)| Time     |
----------------------------------------------------------------------------
|   0 | SELECT STATEMENT |         |     1 |    13 |     1   (0)| 00:00:01 |
|   1 |  SORT AGGREGATE  |         |     1 |    13 |            |          |
|   2 |   INDEX FULL SCAN| T_S_IDX |     3 |    39 |     1   (0)| 00:00:01 |
----------------------------------------------------------------------------

Note
-----
   - dynamic sampling used for this statement

>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
TBL_BIG表:

SQL> select count(*) from tbl_big;
Execution Plan
----------------------------------------------------------
Plan hash value: 475686685

----------------------------------------------------------------------
| Id  | Operation          | Name    | Rows  | Cost (%CPU)| Time     |
----------------------------------------------------------------------
|   0 | SELECT STATEMENT   |         |     1 |     3   (0)| 00:00:01 |
|   1 |  SORT AGGREGATE    |         |     1 |            |          |
|   2 |   TABLE ACCESS FULL| TBL_BIG |  1000 |     3   (0)| 00:00:01 |
----------------------------------------------------------------------

Note
-----
   - dynamic sampling used for this statement

SQL> select count(id) from tbl_big;
Execution Plan
----------------------------------------------------------
Plan hash value: 2252048431

--------------------------------------------------------------------------------
| Id  | Operation             | Name    | Rows  | Bytes | Cost (%CPU)| Time
--------------------------------------------------------------------------------
|   0 | SELECT STATEMENT      |         |     1 |    13 |     3   (0)| 00:00:01
|   1 |  SORT AGGREGATE       |         |     1 |    13 |            |
|   2 |   INDEX FAST FULL SCAN| T_B_IDX |  1000 | 13000 |     3   (0)| 00:00:01
|
--------------------------------------------------------------------------------

Note
-----
   - dynamic sampling used for this statement

SQL> select /*+ index(tbl_big, t_b_idx) */ count(*) from tbl_big;
Execution Plan
----------------------------------------------------------
Plan hash value: 475686685

----------------------------------------------------------------------
| Id  | Operation          | Name    | Rows  | Cost (%CPU)| Time     |
----------------------------------------------------------------------
|   0 | SELECT STATEMENT   |         |     1 |     3   (0)| 00:00:01 |
|   1 |  SORT AGGREGATE    |         |     1 |            |          |
|   2 |   TABLE ACCESS FULL| TBL_BIG |  1000 |     3   (0)| 00:00:01 |
----------------------------------------------------------------------

Note
-----
   - dynamic sampling used for this statement

SQL> select /*+ index(tbl_big, t_b_idx) */ count(id) from tbl_big;
Execution Plan
----------------------------------------------------------
Plan hash value: 1004523789

----------------------------------------------------------------------------
| Id  | Operation        | Name    | Rows  | Bytes | Cost (%CPU)| Time     |
----------------------------------------------------------------------------
|   0 | SELECT STATEMENT |         |     1 |    13 |     5   (0)| 00:00:01 |
|   1 |  SORT AGGREGATE  |         |     1 |    13 |            |          |
|   2 |   INDEX FULL SCAN| T_B_IDX |  1000 | 13000 |     5   (0)| 00:00:01 |
----------------------------------------------------------------------------

Note
-----
   - dynamic sampling used for this statement

不同的点:
小表对id字段count,无论是否使用hint,都是INDEX FULL SCAN。
大表对id字段count,不带hint,是INDEX FAST FULL SCAN,对id字段count带hint,是INDEX FULL SCAN。(这里我感觉不带hint,CBO还能选择FFS的方式可能更优,但如果带了hint,则强制使用并不最优的FS)。

也可以参考我的帖子上其它的回复:

http://www.itpub.net/thread-1794313-1-1.html

时间: 2024-07-30 10:50:38

[Oracle]-[索引][HINT][执行计划]-带HINT的索引执行计划的相关文章

Oracle 12c 新SQL提示(hint)

Oracle 12c 新SQL提示(hint) Oracle 12c中引入了许多新特性,其中部分是和SQL相关的特性.而一些新的SQL提示也随着这些新特性被引入. enable_parallel_dml Syntax: enable_parallel_dml Description: Enable parallel dml. Same effect as "alter session enable parallel dml" SQL?? HelloDBA.com> create 

Oracle技术:基于自定义函数的Function-Based索引创建

在oralce中给自建函数创建索引,结果不成功. source:Create Index IDX_T_SP_TWOTYPESTAT_0_f On T_SP_TWOTYPESTAT_0(f_dateadd(yearmonth,12,2)); err:the function is not deterministic. 我们看一下这是为什么? 随便一个测试可以再现这个问题,我门创建一个函数(本范例函数用于进行16进制向10进制转换): 此时创建索引,获得如下错误信息: 更多精彩内容:http://w

Oracle 反向键索引的原理和用途(减少索引热点块)

Oracle 反向键索引的原理和用途(减少索引热点块) 我们知道Oracle会自动为表的主键列建立索引,这个默认的索引是普通的B-Tree索引.对于主键值是按顺序(递增或递减)加入的情况,默认的B-Tree索引并不理想.这是因为如果索引列的值具有严格顺序时,随着数据行的插入,索引树的层级增长很快.搜索索引发生的I/O读写次数和索引树的层级数成正比,也就是说,一棵具有5个层级的B -Tree索引,在最终读取到索引数据时最多可能发生多达5次I/O操作.因而,减少索引的层级数是索引性能调整的一个重要方

Oracle CBO优化模式中的5种索引访问方法浅析_oracle

本文主要讨论以下几种索引访问方法: 1.索引唯一扫描(INDEX UNIQUE SCAN) 2.索引范围扫描(INDEX RANGE SCAN) 3.索引全扫描(INDEX FULL SCAN) 4.索引跳跃扫描(INDEX SKIP SCAN) 5.索引快速全扫描(INDEX FAST FULL SCAN) 索引唯一扫描(INDEX UNIQUE SCAN) 通过这种索引访问数据的特点是对于某个特定的值只返回一行数据,通常如果在查询谓语中使用UNIQE和PRIMARY KEY索引的列作为条件的

linux oracle rac expdp导出数据库,在节点1执行导出但是数据文件保存在了节点2上

问题描述 linux oracle rac expdp导出数据库,在节点1执行导出但是数据文件保存在了节点2上 linux oracle rac expdp导出数据库,在节点1(机器1)执行导出,数据文件保存在了节点2(机器2)上,怎么指定导出到哪个节点(哪台机器)的目录下?或者让两个节点的目录下都有导出的数据文件.

MySQL索引与性能(3) 覆盖索引

覆盖索引是指索引的叶子节点已包含所有要查询的列,因此不需要访问表数据,能极大地提高性能.覆盖索引对 InnoDB的聚簇索引表特别有用,因为可以避免InnoDB二级索引的二次查询.MySQL里只有B树索引能做覆盖索引,因为必 须要存储索引列的值,而哈希索引.空间索引.全文索引不可以. 当发起一个覆盖索引的查询时,在explain的Extra列可以看到Using Index,下面看一个例子,在表users有一个多列 索引(login_id,status),执行计划如下 root@test 01:30

【译】SQL Server索引进阶第八篇:唯一索引

原文:[译]SQL Server索引进阶第八篇:唯一索引     索引设计是数据库设计中比较重要的一个环节,对数据库的性能其中至关重要的作用,但是索引的设计却又不是那么容易的事情,性能也不是那么轻易就获取到的,很多的技术人员因为不恰当的创建索引,最后使得其效果适得其反,可以说"成也索引,败也索引".     本系列文章来自Stairway to SQL Server Indexes,翻译和整理后发布在agilesharp和博客园,希望对广大的技术朋友在如何使用索引上有所帮助.   唯一

使用索引的误区之四:空值对索引的影响

索引 使用索引的误区之四:空值对索引的影响我们首先做一些测试数据: SQL> create table t(x int, y int);   Table created   请注意,这里我对表t做了一个唯一(联合)索引: SQL> create unique index t_idx on t(x,y);   Index created   SQL> insert into t values(1,1);   1 row inserted   SQL> insert into t va

SQL Server 索引和表体系结构(包含列索引)

原文:SQL Server 索引和表体系结构(包含列索引) 包含列索引 概述 包含列索引也是非聚集索引,索引结构跟聚集索引结构是一样,有一点不同的地方就是包含列索引的非键列只存储在叶子节点:包含列索引的列分为键列和非键列,所谓的非键列就是INCLUDE中包含的列,至少需要有一个键列,且键列和非键列不允许重复,非键列最多允许1023列(也就是表的最多列-1),由于索引键列(不包括非键)必须遵守现有索引大小的限制(最大键列数为 16,总索引键大小为 900 字节)的要求所以引进了包含列索引. 正文