简体   繁体   English

改进Oracle中的连接查询

[英]Improve join query in Oracle

I have a query which takes 17 seconds to execute. 我有一个需要17秒才能执行的查询。 I have applied indexes on FIPS, STR_DT, END_DT but still it's taking time. 我已经在FIPS,STR_DT,END_DT上应用了索引,但仍然需要时间。 Any suggestions on how I can improve the performance? 关于如何提高性能的任何建议?

My query: 我的查询:

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        

Explain Plan: 解释计划:

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

I have added description of tables and explain plan for my query. 我添加了表的描述并解释了我的查询计划。

On the face of it, and without information on the configuration of the sequence you're using, the number of rows in each table, and the total number of rows projected from the query, it's possible that the execution plan you have is the most efficient one for returning all rows. 从表面上看,如果没有关于您正在使用的序列的配置,每个表中的行数以及从查询中投射的总行数的信息,您的执行计划可能是最多的有效的一个返回所有行。

The optimiser clearly thinks that the indexes will not benefit performance, and this is often more likely when you optimise for all rows, not first rows. 优化器显然认为索引不会对性能有所帮助,当您优化所有行而不是第一行时,这通常更有可能。 Index-based access is single block and one row at a time, so can be inherently slower than multiblock full scans on a per-block basis. 基于索引的访问是单个块,一次一行,因此可以比每个块的多块完全扫描更慢。

The hash join that Oracle is using is an extremely efficient way of joining data sets. Oracle正在使用的散列连接是一种非常有效的连接数据集的方法。 Unless the hashed table is so large that it spills to disk, the total cost is only slightly more than full scans of the two tables. 除非散列表太大以至于溢出到磁盘,否则总成本仅略高于两个表的完全扫描。 We need more detailed statistics on the execution to be able to tell if the hashed table is spilling to disk, and if it is the solution may just be modified memory management, not indexes. 我们需要有关执行的更详细统计信息,以便能够判断散列表是否溢出到磁盘,如果是解决方案可能只是修改内存管理,而不是索引。

What might also hold up your SQL execution is calling that sequence, if the sequence's cache value is very low and the number of records is high. 如果序列的缓存值非常低且记录数量很高,那么可能还会阻止SQL执行的是调用该序列。 More info required on that -- if you need to generate a sequential identifier for each row then you could use ROWNUM. 需要更多信息 - 如果您需要为每一行生成顺序标识符,那么您可以使用ROWNUM。

This is basically your query: 这基本上是您的查询:

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;

You want a composite index on (FIPS, STR_DT, END_DT) , perhaps on both tables: 您希望在两个表上都有(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);

Actually, only one is probably necessary but having both gives the optimizer more choices for improving the query. 实际上,只有一个可能是必要的,但两者都为优化器提供了更多选择来改进查询。

You should have at least these two indexes on the table: 你应该在表上至少有这两个索引:

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

which can still be sped up with covering indexes instead: 相反,它仍然可以加速覆盖索引:

  • CTY_REC(FIPS, STR_DT, END_DT, REC_ID) CTY_REC(FIPS,STR_DT,END_DT,REC_ID)
  • FIPS_CONS(FIPS, STR_DT, END_DT, VALUE, VID) FIPS_CONS(FIPS,STR_DT,END_DT,VALUE,VID)

If you wish to drive the optimizer to use the indexes, 如果您希望驱动优化器使用索引,
replace /*+ all_rows */ with /*+ first_rows */ /*+ all_rows */替换为/*+ first_rows */

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM