0

下面的查询需要超过 1 分钟,如何提高性能。两个表都在进行全扫描。如何避免?

查询计划:

SELECT STATEMENT  ALL_ROWSCost: 62  Bytes: 14,355  Cardinality: 45          
    3 HASH JOIN  Cost: 62  Bytes: 14,355  Cardinality: 45   
        1 TABLE ACCESS FULL TABLE SYSADM.POSITIONS Cost: 9  Bytes: 520  Cardinality: 4  
        2 TABLE ACCESS FULL TABLE SYSADM.PORTCONSUMPTION Cost: 52  Bytes: 797,202  Cardinality: 4,218  



SELECT     
     a.Consumption    AS Consumption     ,
     a.Cost      AS Cost      ,
     a.CreatedBy     AS CreatedBy     ,
     a.CreatedDate    AS CreatedDate     ,
     a.UpdatedBy     AS UpdatedBy     ,
     a.UpdatedDate    AS UpdatedDate   

   FROM PortConsumption a   

   JOIN Positions b
   ON  a.PortRotationId = b.Id

   WHERE  b.VoyageId ='82A042031E1B4C38A9832A6678A695A4';

职位(* 115970条记录) *

Id - Primary key (indexed)
VoyageId - indexed

端口消耗(* 1291000条记录) *

Id - Primary key (indexed)
PortRotationId - indexed

执行后

dbms_stats.gather_table_stats ('SYSADM', 'POSITIONS');
dbms_stats.gather_table_stats ('SYSADM', 'PORTCONSUMPTION');

完全扫描没有发生,但性能仍然相同,需要 50 秒。

计划

SELECT STATEMENT  ALL_ROWSCost: 20  Bytes: 16,536  Cardinality: 52                  
    6 NESTED LOOPS              
        4 NESTED LOOPS  Cost: 20  Bytes: 16,536  Cardinality: 52        
            2 TABLE ACCESS BY INDEX ROWID TABLE SYSADM.POSITIONS Cost: 5  Bytes: 520  Cardinality: 4    
                1 INDEX RANGE SCAN INDEX SYSADM.INX_POSITIONS_VOYAGEID Cost: 3  Cardinality: 4  
            3 INDEX RANGE SCAN INDEX SYSADM.INX_PORTCONS_PORTROTID Cost: 2  Cardinality: 12     
        5 TABLE ACCESS BY INDEX ROWID TABLE SYSADM.PORTCONSUMPTION Cost: 4  Bytes: 2,256  Cardinality: 12   
4

1 回答 1

1

您需要收集表的统计信息,因为 Oracle 目前认为 POSITIONS 有 4 行而不是 115970,而 PORTCONSUMPTION 有 4218 行而不是 120 万行,因此对两者进行全面扫描是回答查询的最佳方式。

此代码将使用默认设置收集 2 个表的统计信息:

begin
    dbms_stats.gather_table_stats ('SYSADM', POSITIONS');
    dbms_stats.gather_table_stats ('SYSADM', PORTCONSUMPTION ');
end;

有关如何收集统计信息的更多详细信息,请参阅DBMS_STATS 文档。

于 2012-08-29T11:14:00.173 回答