【问题标题】:How to improve performance of nested SELECT statement in MySQL如何提高 MySQL 中嵌套 SELECT 语句的性能
【发布时间】:2012-06-19 19:02:32
【问题描述】:

我有以下性能很差的 SQL 语句:

SELECT  
frmInstLastModifiedDate AS last_modified 
, frmInstID AS proj_id 
, frmInstIsApproved 
, frmInstStatus AS proj_sts 
, (CASE 
    WHEN frmInstCreator = 294  THEN 'M' 
    WHEN status = 'f'  THEN 'F' 
    WHEN (frmInstID IN (SELECT shr.frmInstID from tbl_frm_share as shr WHERE shr.shrMember = 294 AND shr.shrType = 'LIKE'  AND shr.frmID = inst.frmID)) THEN 'L' 
    WHEN (frmInstID IN (SELECT shr.frmInstID from tbl_frm_share as shr WHERE shr.shrMember = 294 AND shr.shrType = 'SHARE' AND shr.frmID = inst.frmID)) THEN 'S' 
    ELSE 'O' END) as proj_grp 
, (SELECT lkpCode FROM tbl_frm_lookup WHERE lkpID = (SELECT ansValue FROM tbl_itm_answer WHERE frmInstID = proj_id AND itmID = (select itmID from tbl_frm_item where itmName = 'prjStatus' AND frmID = inst.frmID))) as prjStatus 
, (SELECT lkpCode FROM tbl_frm_lookup WHERE lkpID = (SELECT ansValue FROM tbl_itm_answer WHERE frmInstID = proj_id AND itmID = (select itmID from tbl_frm_item where itmName = 'ProjectType' AND frmID = inst.frmID))) as ProjectType 
, (SELECT itmID FROM tbl_itm_answer where itmID in (828,829,830,831) and frmInstID = proj_id AND SUBSTRING(ansValue,1,2) = 'on') as primIRWMObj 
, (SELECT lkpCode FROM tbl_frm_lookup WHERE lkpID = (SELECT ansValue FROM tbl_itm_answer WHERE frmInstID = proj_id AND itmID = (select itmID from tbl_frm_item where itmName = 'PrjPSubReg'))) as ProjectSubReg 
, frmInstCreator AS proj_creatorID 
, frmInstCode AS proj_code 
    FROM tbl_frm_instance inst 
WHERE status not like 'd'   
HAVING (proj_sts like 'c' AND ('PROJECT PROPONENT' = 'ADMIN' or proj_creatorID = 294 )) 
    or (proj_sts like 'a') 
    or (proj_sts like 't' AND proj_creatorID = 294)  
    OR (proj_grp = 'S')  
ORDER BY frmInstCreateDate DESC ;

语句是根据用户选择的选项动态创建的。我知道嵌套的 select 语句(如下所示)是问题所在,但我不知道如何替换它

    (SELECT lkpCode FROM tbl_frm_lookup WHERE lkpID = (SELECT ansValue FROM tbl_itm_answer WHERE frmInstID = proj_id AND itmID = (select itmID from tbl_frm_item where itmName = 'prjStatus' AND frmID = inst.frmID))) as prjStatus 

任何帮助将不胜感激。

【问题讨论】:

  • 在没有解释的情况下很难对 SQL 进行性能调优。如果您发布说明计划,我们可以为您提供更好的帮助。

标签: mysql


【解决方案1】:

不要使用nested selects,它最慢,而且数据库写得很脏。最好的方法是使用JOIN,尽可能使用JOIN

如果您想创建具有良好性能的IS(这是您的工作,您的名字),那么您必须始终决定最有效、最快速、最安全的方法,那就是JOIN

我建议你在任何地方都使用JOIN

我建议您阅读Understanding the Query Execution Plan

注意:有时您必须认为“像数据库”而不是“像过程”。

【讨论】:

    【解决方案2】:

    试试这个::

    我能做的最少::

    SELECT  
    frmInstLastModifiedDate AS last_modified 
    , frmInstID AS proj_id 
    , frmInstIsApproved 
    , frmInstStatus AS proj_sts 
    , (CASE 
        WHEN frmInstCreator = 294  THEN 'M' 
        WHEN status = 'f'  THEN 'F' 
        WHEN (frmInstID IN (SELECT shr.frmInstID from tbl_frm_share as shr WHERE shr.shrMember = 294 AND shr.shrType = 'LIKE'  AND shr.frmID = inst.frmID)) THEN 'L' 
        WHEN (frmInstID IN (SELECT shr.frmInstID from tbl_frm_share as shr WHERE shr.shrMember = 294 AND shr.shrType = 'SHARE' AND shr.frmID = inst.frmID)) THEN 'S' 
        ELSE 'O' END) as proj_grp 
    , 
    (SELECT lkpCode 
    FROM tbl_frm_lookup tfl
    inner join tbl_itm_answer tia on (tfl.lkpID= tia.ansValue)
    inner join tbl_frm_item tfi on (tia.itmID= tfi.itmID)
     WHERE frmInstID = proj_id and itmName = 'prjStatus' AND frmID = inst.frmID) as prjStatus 
    , frmInstCreator AS proj_creatorID 
    , frmInstCode AS proj_code
    

    【讨论】:

    • 此更改使代码速度提高了 5 倍。我还为在 where 子句中使用的键创建了索引。这也很有帮助。谢谢大家
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-11-03
    • 2023-04-03
    • 2018-09-06
    • 2016-08-25
    • 2020-03-15
    • 1970-01-01
    相关资源
    最近更新 更多