连接中的非索引列

时间:2012-11-28 08:38:11

标签: sql oracle indexing database-performance

SQL> desc emp_1;

Name     Type         Nullable Default Comments 
-------- ------------ -------- ------- -------- 
EMP_ID   NUMBER                                 
EMP_NAME VARCHAR2(20) Y                         
DEPTNO   NUMBER(10)   Y

SQL> desc dept

Name      Type         Nullable Default Comments 
--------- ------------ -------- ------- -------- 
DEPT_ID   NUMBER       Y                         
DEPT_NAME VARCHAR2(20) Y 

SQL> CREATE INDEX abc_idex ON emp_1(deptno);

Index created

从emp_1中选择/ * + index(emp_1 abc_idex)* / emp_name     INNER JOIN dept ON emp_1.deptno = dept.dept_id

Explain Plan :- 
SELECT STATEMENT, GOAL = ALL_ROWS           271 100000  800000
 MERGE JOIN         271 100000  800000
  TABLE ACCESS BY INDEX ROWID   EXAMINBI    EMP_1   267 100000  500000
   INDEX FULL SCAN  EXAMINBI    ABC_IDEX    131 100000  
  SORT JOIN         4   4   12
   TABLE ACCESS FULL    EXAMINBI    DEPT    3   4   12

从emp_1中选择/ * + index(emp_1 abc_idex)* / emp_name INNER JOIN dept ON emp_1.deptno = dept.dept_id 和emp_1.emp_name = dept.dept_name

Explain Plan:- 
SELECT STATEMENT, GOAL = ALL_ROWS           272 1   11
 HASH JOIN          272 1   11
  TABLE ACCESS FULL EXAMINBI    DEPT    3   4   24
  TABLE ACCESS BY INDEX ROWID   EXAMINBI    EMP_1   267 100000  500000
   INDEX FULL SCAN  EXAMINBI    ABC_IDEX    131 100000  

我在你的帮助下清除我的索引概念。我的理解是oracle将跳过我的索引提示,因为它需要其他列也没有索引(emp_name)但在第二种情况下仍然通过索引扫描emp_1表。我的问题在这种情况下会有所帮助,我使用另一列进行不使用索引的连接(在我们的示例中为emp_name)?在这种情况下我们应该使用索引提示吗? *注意: - 我知道这是emp_name,dept_name不是逻辑连接,但仅仅是为了测试目的,我创建了相同的。*

3 个答案:

答案 0 :(得分:1)

  

我想知道在加入你时是否建议使用索引提示   正在使用同一个表中的非索引列。它有帮助吗?

在大多数情况下

在正常情况下,您根本就不使用提示。正如你在这里看到的,你已经使用了一个提示,Oracle已经遵循它并做了一些愚蠢的事情。您只在非常有限的情况下使用提示,通常只有在您了解Oracle无法自行解决的数据性质时才会使用。通常我使用的唯一提示是基数提示,因为Oracle有时可能无法正确计算基数。

不要假设您需要经常使用提示。你没有。即使提示现在有效,但当数据的性质发生变化时,它可能会停止工作。

答案 1 :(得分:0)

在你的案例中使用索引可能会减慢整个语句的速度。这是因为您正在查询整个表DEPT和EMP_1。由于提示,Oracle必须查询完整表和索引。你真的想要这个吗?

在这种简单的情况下,我不喜欢使用提示。优化器的功能非常好。

如果您对特定部门使用陈述,那么结果会更好

select emp_name
  from emp_1 INNER JOIN dept ON emp_1.deptno = dept.dept_id
  where dept.dname = 'any department'

答案 2 :(得分:0)

所以:

select /*+ cardinality(0)*/ emp_name 
from emp_1 
   INNER JOIN dept ON emp_1.deptno = dept.dept_id