优化IN子句

时间:2011-07-26 07:30:11

标签: sql oracle oracle10g query-optimization sql-optimization

我正在使用Oracle 10g。这是我的查询

select * from Entries 
where RefKey in (select RefKey 
                 from Entries 
                 where KeyStat = 1) 
and RefKey = Key;

这里RefKey,Key和KeyStat都被编入索引。该表在另一列上分区,此列未在此处使用。 在此查询中,我选择当前活动的主密钥(如果RefKey =密钥然后是主密钥)(KeyStat = 1)。以下是使用SQLTools 1.21 RC3的此查询的执行计划。

----------------------------------------------------------------------------------------------------------------------
| Id  | Operation                           | Name           | Rows  | Bytes | Cost (%CPU)| Time     | Pstart| Pstop |
----------------------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT                    |                |     1 |   270 |   218K  (1)| 00:43:37 |       |       |
|   1 |  NESTED LOOPS SEMI                  |                |     1 |   270 |   218K  (1)| 00:43:37 |       |       |
|   2 |   PARTITION RANGE ALL               |                |     1 |   262 |   218K  (1)| 00:43:37 |     1 |    12 |
|*  3 |    TABLE ACCESS FULL                | ENTRIES        |     1 |   262 |   218K  (1)| 00:43:37 |     1 |    12 |
|*  4 |   TABLE ACCESS BY GLOBAL INDEX ROWID| ENTRIES        |    10M|    77M|     3   (0)| 00:00:01 | ROWID | ROWID |
|*  5 |    INDEX RANGE SCAN                 | IND_ENTR_REFKEY|     1 |       |     2   (0)| 00:00:01 |       |       |
----------------------------------------------------------------------------------------------------------------------

我担心ID = 3“表格访问已满”。如果此查询中使用的所有列都已编制索引,那么为什么oracle正在执行全表扫描。

如何优化?如果我在内部查询中放入一些值,它返回的速度会快得多。


解释为什么子查询是必要的:我选择的是具有至少一个活动密钥的整批。 Refkey不是唯一的;例如:

Key=1, RefKey=1, Stat=1 
Key=2, RefKey=1, Stat=0
Key=3, RefKey=2, Stat=1

3 个答案:

答案 0 :(得分:5)

  

“我担心ID = 3”表访问已满“。如果所有列   在此查询中使用的是索引,然后oracle为什么要完整   表扫描。“

优化器忽略了KEYSTAT上的索引。我猜这是因为KEYSTAT不是非常有选择性(相对较少的不同值)和/或因为这些值均匀分布在整个ENTRIES表范围内。如果查询几乎击中表中的每个块,则FULL TABLE SCAN是最佳路径。

通过过滤子查询获得的速度提高,可以验证此猜测。

正如其他人所建议的那样,重构您的语句以删除子查询将是提高性能的最佳方法。


  

“将有数百万条条目的KeyStat = 0,只有少数条目   1000s将有1,所以使用索引将是有益的。“

倾斜的数据分布通常是性能问题的根源。你知道,事实是,数据库不知道 KEYSTAT = 1比KEYSTAT = 0更具选择性。除非我们告诉它,这就是为什么在收集有关该索引的统计信息时可能需要考虑创建直方图的原因。 Find out more

请注意,直方图可能会导致问题并解决它们,尤其是对于使用绑定变量instaead of literals的查询。因此,在将它们投入生产之前,先在沙坑中进行基准测试。

答案 1 :(得分:4)

也许我错过了一些东西,但不应该产生相同的结果?

select *
from Entries e
where e.KeyStat = 1 
  and e.RefKey = e.Key

答案 2 :(得分:1)

相关问题