oracle为什么选择INDEX FULL SCAN,然后选择ACCESS BY INDEX ROWID与FULL TABLE SCAN?

问题描述 投票:1回答:2

为什么oracle为什么选择INDEX FULL SCAN,然后选择ACCESS BY INDEX ROWID,而不是只进行一个步骤的全表扫描,并且做同样的事情并且可能更快?

Oracle为什么选择

|   2 |   TABLE ACCESS BY INDEX ROWID
|   3 |    INDEX FULL SCAN    

超过

|  2 |  TABLE ACCESS FULL| 

为了进一步说明,这是查询和完整的执行计划

SELECT EMP_NO, ENAME, SALARY, dname 
FROM EMP E, DEPT D
WHERE E.DEPT_NO=D.DEPT_NO;



Execution Plan
----------------------------------------------------------
Plan hash value: 2125045483

----------------------------------------------------------------------------------------
| Id  | Operation                    | Name    | Rows  | Bytes | Cost (%CPU)| Time     |
----------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT             |         |   879 | 35160 |     8  (13)| 00:00:01 |
|   1 |  MERGE JOIN                  |         |   879 | 35160 |     8  (13)| 00:00:01 |
|   2 |   TABLE ACCESS BY INDEX ROWID| DEPT    |     7 |    91 |     2   (0)| 00:00:01 |
|   3 |    INDEX FULL SCAN           | DEPT_PK |     7 |       |     1   (0)| 00:00:01 |
|*  4 |   SORT JOIN                  |         |   879 | 23733 |     6  (17)| 00:00:01 |
|   5 |    TABLE ACCESS FULL         | EMP     |   879 | 23733 |     5   (0)| 00:00:01 |
----------------------------------------------------------------------------------------
oracle sql-execution-plan
2个回答
0
投票

您会注意到优化器does在EMP表上选择了FULL TABLE SCAN。然后,它使用键EMP.DEPT_NO在DEPT上查找适当的值,因为在这种情况下,执行879次查找显然比在DEPT上执行FULL TABLE SCAN进行查找更快(至少在优化程序看来),而执行879 * 7个比较。

为了有趣,您可以通过查看USER_TABLES或DBA_TABLES视图来查看最近如何收集这些表的统计信息:

SELECT TABLE_NAME, LAST_ANALYZED
  FROM USER_TABLES
  WHERE TABLE_NAME IN ('EMP', 'DEPT')

如果愿意,您可以使用以下方法在这些表上收集新的统计信息:>

BEGIN
  DBMS_STATS.GATHER_TABLE_STATISTICS(OWNNAME => 'your_schema_name',
                                     TABNAME => 'EMP',
                                     CASCADE => TRUE);

  DBMS_STATS.GATHER_TABLE_STATISTICS(OWNNAME => 'your_schema_name',
                                     TABNAME => 'DEPT',
                                     CASCADE => TRUE);
END;

0
投票

通常,表全扫描必须读取到表的高水位线(即,几乎每个表所分配的块都已被表使用)。如果从表中删除了很多内容,则表中可能有10,000个块,其中大部分是空的,必须将其读取。

© www.soinside.com 2019 - 2024. All rights reserved.