2016-11-23 78 views
3

我有一个需要17秒才能执行的查询。我已经在FIPS,STR_DT,END_DT上应用了索引,但仍然需要时间。关于如何改善表现的任何建议?改善Oracle中的联接查询

我的查询:

SELECT /*+ALL_ROWS*/ K_LF_SVA_VA.NEXTVAL VAL_REC_ID,  a.REC_ID, 
    b.VID, 
    1 VA_SEQ, 
    51 VA_VALUE_DATATYPE, 
    b.VALUE VAL_NUM, 
    SYSDATE CREATED_DATE, 
    SYSDATE UPDATED_DATE 
    FROM CTY_REC a JOIN FIPS_CONS b 
ON a.FIPS=b.FIPS AND a.STR_DT=b.STR_DT AND a.END_DT=b.END_DT; 


DESC CTY_REC; 

Name    Null Type   
------------------- ---- ------------- 
REC_ID     NUMBER(38)  
DATA_SOURCE_DATE   DATE   
STR_DT     DATE   
END_DT     DATE   
VID_RECSET_ID   NUMBER   
VID_VALSET_ID   NUMBER   
FIPS      VARCHAR2(255) 


DESC FIPS_CONS; 

Name   Null  Type   
------------- -------- ------------- 
STR_DT     DATE   
END_DT     DATE   
FIPS     VARCHAR2(255) 
VARIABLE    VARCHAR2(515) 
VALUE     NUMBER   
VID   NOT NULL NUMBER   

解释计划:

Plan hash value: 919279614 

-------------------------------------------------------------- 
| Id | Operation   | Name       | 
-------------------------------------------------------------- 
| 0 | SELECT STATEMENT |        | 
| 1 | SEQUENCE   | K_VAL       | 
| 2 | HASH JOIN   |        | 
| 3 | TABLE ACCESS FULL| CTY_REC      | 
| 4 | TABLE ACCESS FULL| FIPS_CONS      | 
-------------------------------------------------------------- 

我添加表的描述和我的查询说明计划。

+1

有多少行,表中替换/*+ all_rows */?从查询中投影了多少行?在另一个表中,哪些行的比例不匹配行?什么是序列的缓存值? –

+0

你能展示完整的执行计划吗?包括行估计和成本列(也许TmpSpc) –

回答

3

在它的面前,没有您所使用的顺序,排在每个表的数量,以及配置信息从查询中计算出的总行数,可能是您执行计划是返回所有行的效率最高的计划。

优化器清楚地认为索引不会使性能受益,并且在优化所有行而不是第一行时通常更有可能。基于索引的访问一次只能有一个单独的块和一个行,因此在每个块的基础上,它本质上可能比多块全面扫描慢。

Oracle正在使用的散列连接是连接数据集的极其有效的方式。除非散列表如此大以至于溢出到磁盘,否则总成本仅比两个表的完整扫描略高。我们需要更详细的执行统计信息,以便能够判断散列表是否溢出到磁盘,并且如果解决方案可能只是修改了内存管理,而不是索引。

如果序列的缓存值非常低且记录数很高,那么可能会阻塞您的SQL执行的操作是调用该序列。需要更多信息 - 如果你需要为每一行生成一个顺序标识符,那么你可以使用ROWNUM。

+1

我喜欢这个回答。你说得对,全表扫描本身不是很糟糕。它们有时是访问数据的最有效方式。而且,是的,散列连接是连接两个表格的一种很好的技术。 –

0

这基本上是你的查询:

SELECT . . . 
FROM CTY_REC a JOIN 
    FIPS_CONS b 
    ON a.FIPS = b.FIPS AND a.STR_DT = b.STR_DT AND a.END_DT = b.END_DT; 

你想在(FIPS, STR_DT, END_DT)一个综合指数,也许这两个表:

create index idx_cty_rec_3 on cty_rec(FIPS, STR_DT, END_DT); 
create index idx_fipx_con_3 on cty_rec(FIPS, STR_DT, END_DT); 

事实上,只有一个可能是必要的,但同时具有给出了优化更多的选择来改善查询。

+0

我已经有这些。 – dang

0

你至少应该有在桌子上这两个指标:

  • CTY_REC(FIPS,STR_DT,END_DT)
  • FIPS_CONS(FIPS,STR_DT,END_DT)

它仍然可以被加速与覆盖索引代替:

  • CTY_REC(FIPS,STR_DT,END_DT,·REC_ID)
  • FIPS_CONS(FIPS,STR_DT,END_DT,价值,VID)
+0

当您包含所需的rowid和空格时,这些索引可能会比表格大。 –

+0

@David Aldridge:是的,有时候索引会变大,但我不会认为这是不使用它们的原因。 –

0

如果你想开车到使用索引优化,
/*+ first_rows */