我有一个需要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 |
--------------------------------------------------------------
我添加了表格说明并解释了我的查询计划。
答案 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)
表格中至少应该包含以下两个索引:
仍然可以用覆盖索引加速:
答案 3 :(得分:0)
如果您希望驱动优化程序使用索引,
将/*+ all_rows */
替换为/*+ first_rows */