改进Oracle

时间:2016-11-23 15:53:59

标签: sql oracle

我有一个需要17秒才能执行的查询。我已经在FIPS,STR_DT,END_DT上应用了索引,但仍然需要时间。关于如何提高绩效的任何建议?

我的查询:

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                      |
--------------------------------------------------------------

我添加了表格说明并解释了我的查询计划。

4 个答案:

答案 0 :(得分: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);

实际上,只有一个可能是必要的,但两者都为优化器提供了更多选择来改进查询。

答案 2 :(得分: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,VALUE,VID)

答案 3 :(得分:0)

如果您希望驱动优化程序使用索引,
/*+ all_rows */替换为/*+ first_rows */