优化查询(索引、解释)Mysql

优化查询(索引、解释)Mysql,mysql,datetime,indexing,query-optimization,in-clause,Mysql,Datetime,Indexing,Query Optimization,In Clause,根据stackoverflow上另一位开发人员的建议,我已经更新了我的查询,如下所示,但我仍然需要进一步优化它。是否有人可以指导我如何最好地将索引应用于查询 请参阅下面的查询: SELECT a.id, a.user_unique_id, a.loan_location, a.ippis, a.tel_no, a.organisation, a.branch, a.loan_agree, a.loan_type, a.appr, a

根据stackoverflow上另一位开发人员的建议,我已经更新了我的查询,如下所示,但我仍然需要进一步优化它。是否有人可以指导我如何最好地将索引应用于查询

请参阅下面的查询:

SELECT a.id, a.user_unique_id, a.loan_location, 
          a.ippis, a.tel_no,
          a.organisation, a.branch, a.loan_agree, 
          a.loan_type, a.appr, a.sold, 
          a.loan_status, a.top_up, a.current_loan, 
          a.date_created, a.date_updated, c.loan_id, c.user_unique_id AS tu_user_unique_id, 
          c.ippis AS tu_ippis, c.top_up_approved, 
           c.loan_type AS tu_loan_type, c.dse, c.status, c.current_loan AS tu_current_loan, 
          c.record_category, c.date_created AS tu_date_created, 
          c.date_updated AS tu_date_updated 
FROM loan_applications_tbl a
LEFT JOIN topup_or_reapplication_tbl c
    ON a.ippis=c.ippis   
WHERE ((c.status IN ('pending', 'corrected', 'Rejected', 'Processing', 'Captured', 'Reviewed', 'top up') 
       AND MONTH(CURRENT_DATE) IN (MONTH(c.date_created), MONTH(c.date_updated) 
       AND YEAR(CURRENT_DATE) IN (YEAR(c.date_created), YEAR(c.date_updated)) 
       AND   c.current_loan='1' )) 
OR ( a.loan_status IN ('pending', 'corrected', 'Rejected', 'Processing', 'Captured', 'Reviewed', 'top up')
     AND MONTH(CURRENT_DATE) IN (MONTH(a.date_created), MONTH(a.date_updated)) )
     AND YEAR(CURRENT_DATE) IN (YEAR(a.date_created), YEAR(a.date_updated)) 
     AND (a.current_loan='1' 
          OR (a.current_loan='0' 
              AND a.loan_status IN('Approved','Closed')))))
执行时间:53秒

记录数目:11000

使用mysql EXPLAIN给出以下屏幕截图:(如何最大限度地利用“可能的密钥”列中的信息

我已更新了以下附加信息:

我在c和a之间使用OR的原因如下:

  • a
    是具有66列的父表,如果
    a
    上的新条目具有匹配的/现有的
    ippi
    a
    上的唯一字段),则会填充贷款条目
    a
    中的某些列将用新条目中的数据更新/覆盖,而条目中的其余数据将作为新行插入
    c
    IPPI
    在表
    c
    中不是唯一的)。这是为了保留所有后续贷款请求的历史记录,同时不给冗余空间

  • 在检索记录时,我需要使用big
    子句来检查
    a
    c
    表中每个贷款记录的所有实例,其中
    状态、日期和当前贷款
    列与我的where子句中的参数匹配

  • a
    中始终有完整的记录,但
    c
    中并不总是有记录,除非对同一唯一ID有更多的贷款请求。
    a
    包含如“通过唯一ID”等“谁是账户人”,以及第一笔贷款的附加/补充状态详细信息,随后,在第一笔贷款“c”之后,将是具有相同唯一ID的实际贷款申请的附加/补充状态详细信息

  • 如果在3月12日创建了“A”,并在3月16日创建了新的“c”记录,“A”记录也会得到最后一次更新的时间戳,标记为3月16日,因为它有一个对它有一定影响的子附件,而新的
    c
    记录有自己创建和更新的时间戳。在进行更改或有
    c
    记录之前,
    a
    记录的更新字段将为空/空在对
    c
    记录进行一些更改之前,
    c
    记录的字段将为空/空


  • 我希望这是可以理解的

    我一直忘记这个词,因为我很少提到它,但无论如何,您的索引不能通过使用月()和年()进行优化因为它们是基础数据上的函数。通过应用日期范围,它们可以。因此,您可以保留您的月/年,例如在2021年1月创建并在2021年3月更新,但另外,添加
    "c.date\u created>=当前日期和当前日期,where子句中的
    正在以一种可怕的方式破坏性能。有几件事可以让查询运行得更快,但是
    必须要去做。@matigo非常感谢你的帮助。你介意帮我用一个可能替代的伪代码吗?你的query在你第一个月()的测试中有一个错误的位置,应该是你单身的第二个月(c.date_updated)。然后,在您的或条件之前删除一个。@DRapp感谢您的帮助highlight@matigo仍然期待着来自世界各地的帮助you@Peter,请参阅我的修订答案,以获得更多详细的澄清和评论。@Peter,2更多,请参阅修订单词是@Peter,修订为包装(创建或更新)和其他内容query@Peter,请参阅底部的修订,并重新阅读有关howFarBack上下文的整个SQL。
    
    WHERE > beginning of this month and LESS than beginning of next month
    
    loan_applications_tbl ( date_created, date_updated, loan_status, current_loan, ippis )
    topup_or_reapplication_tbl ( ippis, status, current_loan, date_created, date_updated )
    
    SELECT 
            a.id, 
            a.user_unique_id, 
            a.loan_location, 
            a.ippis, 
            a.tel_no,
            a.organisation, 
            a.branch, 
            a.loan_agree, 
            a.loan_type, 
            a.appr, 
            a.sold, 
            a.loan_status, 
            a.top_up, 
            a.current_loan, 
            a.date_created, 
            a.date_updated, 
            c.loan_id, 
            c.user_unique_id tu_user_unique_id, 
            c.ippis tu_ippis, 
            c.top_up_approved,
            c.loan_type tu_loan_type, 
            c.dse, 
            c.status, 
            c.current_loan tu_current_loan,
            c.record_category, 
            c.date_created tu_date_created,
            c.date_updated tu_date_updated 
        FROM 
            -- this creates inline mySQL variables I can use for the WHERE condition
            -- by doing comma after with no explicit join, it is a single row
            -- and thus no Cartesian result, just @variables available now
            ( select 
                    -- first truncating any TIME portion by casting to DATE()
                    @myToday := date(curdate()),
                    @howFarBack := date_sub( @myToday, interval 6 month ),
                    -- now subtract day of month -1 to get first of THIS month
                    @beginOfMonth := date_sub( @myToday, interval dayOfMonth( @myToday ) -1 day ),
                    -- and now, add 1 month for beginning of next
                    @beginNextMonth := date_add( @beginOfMonth, interval 1 month ) ) SqlVars,
    
            loan_applications_tbl a
        
                LEFT JOIN topup_or_reapplication_tbl c
                    ON  a.ippis = c.ippis   
                    AND c.current_loan='1'
                    AND c.status IN ('pending', 'corrected', 'Rejected', 
                                    'Processing', 'Captured', 'Reviewed', 'top up') 
                    AND 
                    (
                            (@beginOfMonth <= c.date_created 
                        AND c.date_created < @beginNextMonth)
            
                    OR
                            (@beginOfMonth <= a.date_updated 
                        AND a.date_updated < @beginNextMonth )
                    )
    
        WHERE
                -- forces only activity for the single month in question
                -- since the "a" table knows of any "updates" to the "C",
                -- its updated basis will keep overall restriction to any accounts
    
                -- updated within this month in question only
                -- testing specifically for created OR updated within the
                -- current month in question
    
            a.date_created >= @howFarBack
            AND
                (
                        (@beginOfMonth <= a.date_created 
                    AND a.date_created < @beginNextMonth)
            
                OR
                        (@beginOfMonth <= a.date_updated 
                    AND a.date_updated < @beginNextMonth )
                )
            
            -- and NOW we can easily apply the OR without requiring
            -- to run against the ENTIRE set of BOTH tables.
            AND (
                        c.ippis IS NOT NULL
                    OR 
                        ( a.loan_status IN (  'pending', 'corrected', 'Rejected', 'Processing', 
                                'Captured', 'Reviewed', 'top up')
                        AND (   
                                a.current_loan = '1' 
                            OR  (   a.current_loan = '0' 
                                AND a.loan_status IN ('Approved', 'Closed')
                                )
                            )
                        )
                )