需要 Oracle 查询优化(经过的时间 = 2.37 秒)

Posted

技术标签:

【中文标题】需要 Oracle 查询优化(经过的时间 = 2.37 秒)【英文标题】:Oracle Query Optimization Required ( elapsed time = 2.37 sec ) 【发布时间】:2016-10-28 06:31:19 【问题描述】:

以下查询需要时间(2.37 秒)来执行。我在 FORWARD_INFO 和 G_PROFILE 表中分别有大约 5,00,00 条记录和 2,00,00 条记录。

我需要优化这个查询。它应该需要 ~.20 秒。你能建议一下吗?

使用 Oracle10g 数据库。

SELECT S_NUM, STATUS, TRANSLATION_NUM, ANN, NOTIFY_ANN, ID, NAME, 
  PROFILE_ID, ANN_ID, RES_PROFILE_ID, R_ANN, RES_ANN_ID 
FROM(
  SELECT CSC.S_NUM,CSC.STATUS, CSC.TRANSLATION_NUM, CSC.ANN, CSC.NOTIFY_ANN, CSC.ID, CGP.NAME, CGP.PROFILE_ID, CGP.ANN_ID, CGP.RES_PROFILE_ID, CGP.R_ANN, CGP.RES_ANN_ID, 
     RANK() OVER(ORDER BY LENGTH(CSC.S_NUM) DESC) RANKING 
  FROM 
    FORWARD_INFO CSC, G_PROFILE CGP 
  WHERE '0120913005' LIKE CSC.S_NUM||'%' AND 
         CGP.NAME LIKE 'ase' ||'%' AND 
         CSC.ACCOUNT_NUMBER=10 AND CSC.ID= CGP.ID AND 
         CSC.ACTIVE = 1 AND CGP.ACTIVE = 1) 
WHERE RANKING = 1 AND 
         ROWNUM = 1;

【问题讨论】:

如果没有表和索引的 DDL 以及对表中包含的数据和查询逻辑的基本了解,我认为任何人都无法提供帮助。 请edit您的问题为有问题的表(包括所有索引)和执行计划添加create table语句。 Formatted text 请no screen shots 【参考方案1】:

经过一点点重新格式化

SELECT S_NUM, STATUS, TRANSLATION_NUM, 
    ANN, NOTIFY_ANN, ID, NAME, 
    PROFILE_ID, ANN_ID, RES_PROFILE_ID , R_ANN,
    RES_ANN_ID 
FROM
    (SELECT CSC.S_NUM,CSC.STATUS, CSC.TRANSLATION_NUM, CSC.ANN, CSC.NOTIFY_ANN, CSC.ID, 
        CGP.NAME, CGP.PROFILE_ID, CGP.ANN_ID, CGP.RES_PROFILE_ID , CGP.R_ANN, CGP.RES_ANN_ID, 
        RANK() OVER (ORDER BY LENGTH(CSC.S_NUM) DESC) RANKING 
    FROM FORWARD_INFO CSC
        JOIN G_PROFILE CGP ON CSC.ID = CGP.ID 
    WHERE '0120913005' LIKE CSC.S_NUM||'%' 
        AND CGP.NAME LIKE 'ase' ||'%' 
        AND CSC.ACCOUNT_NUMBER = 10          
        AND CSC.ACTIVE = 1 
        AND CGP.ACTIVE = 1) 
WHERE RANKING = 1 
    AND ROWNUM = 1;

你看到了瓶颈:

'0120913005' LIKE CSC.S_NUM||'%' AND CGP.NAME LIKE 'ase' ||'%' 

您可以创建基于函数的索引。

CREATE INDEX NAME_LIKE_ASE ON G_PROFILE (SUBSTR(NAME, 1, 3));
CREATE INDEX S_NUM_LIKE ON G_PROFILE (S_NUM||'%');

你的 WHERE 条件是

'0120913005' LIKE CSC.S_NUM||'%' AND SUBSTR(NAME, 1, 3) = 'ase'

那么你应该在FORWARD_INFO.IDG_PROFILE.ID 上有索引。

【讨论】:

不应该在 FORWARD_INFO 而不是 G_PROFILE 上创建 S_NUM_LIKE 索引吗?此外,将谓词中的其他列也包含在 fbi 中可能会有所帮助 但总的来说,即使您的建议很好,我们仍然没有所有信息。最具选择性的标准是什么?上面已经有索引了?如果(例如)这两个索引根本没有选择性,而 OP 只想要大多数“非活动”记录上的少数“活动”记录怎么办?解决方案可能再次是 FBI ,但在活动列上。所以,如果 OP 希望我们帮助他实现 10 倍的性能提升,他真的应该给我们更多信息。【参考方案2】:

在哪里条款

WHERE '0120913005' LIKE 
  CSC.S_NUM||'%' AND CGP.NAME LIKE 'ase' ||'%' AND 
  CSC.ACCOUNT_NUMBER=10 AND CSC.ID= CGP.ID AND 
  CSC.ACTIVE = 1 AND CGP.ACTIVE = 1

像这样改变条件的顺序

WHERE CSC.ACTIVE = 1 AND CGP.ACTIVE = 1  AND 
  CSC.ACCOUNT_NUMBER=10 AND CSC.ID= CGP.ID  AND 
 '0120913005' LIKE 
  CSC.S_NUM||'%' AND CGP.NAME LIKE 'ase' ||'%'

字符串比较需要大量成本

【讨论】:

WHERE 条件的顺序不匹配。优化器可能会重新排列它们。 由于oracle是基于成本的优化,它会自行安排订单

以上是关于需要 Oracle 查询优化(经过的时间 = 2.37 秒)的主要内容,如果未能解决你的问题,请参考以下文章

oracle查询的查询优化

Oracle - 查询优化 - 查询运行时间长

如何针对 Oracle 优化此查询

oracle表查询优化

需要帮助来优化 ORACLE SQL 查询 [关闭]

oracle 优化时间查询