簡體   English   中英

如何優化這個mysql查詢(max,replace,left join)?

[英]HOW to optimize this mysql query (max,replace,left join)?


我知道每個人都討厭提出問題,但我需要你的幫助。 所以 - 這就是代碼。 它必須獲取用戶的信息

 select
 c.id,
 c.firstName,
 c.lastName,
 ...
 dt.code as docCode,
 dt.name as docName,
 replace(replace(replace(replace(replace(cc.contact, ' ',''), '(',''), ')', ''), '-', ''), '+', '') as homePhone,
 replace(replace(replace(replace(replace(cc1.contact, ' ',''), '(',''), ')', ''), '-', ''), '+', '') as cellPhone
      from Client c
        left join ClientPolicy p on p.id=(select max(pp.id) 
                                            from ClientPolicy pp 
                                            where 
                                            pp.client_id = c.id 
                                            and pp.deleted = 0)
        left join rbPolicyType pt on pt.id = p.policyType_id
        left join ClientDocument d on d.id =(SELECT MAX(dd.id) 
                                            FROM ClientDocument dd 
                                            WHERE 
                                            dd.client_id = c.id 
                                            and dd.deleted = 0)
        left join rbDocumentType dt on dt.id = d.documentType_id and dt.code IN ('1')
        left join ClientContact cc ON cc.id = (select MAX(ccc.id) 
                                                FROM ClientContact ccc 
                                                where 
                                                ccc.client_id = c.id 
                                                and ccc.deleted = 0 
                                                and ccc.contactType_id = 1)
        left join ClientContact cc1 ON cc1.id = (SELECT MAX(ccc1.id) 
                                                FROM ClientContact ccc1 
                                                WHERE  
                                                ccc1.client_id = c.id 
                                                and ccc1.deleted = 0 
                                                and ccc1.contactType_id = 3)
  where
 c.deleted = 0
 and c.firstName like '%'
 and c.patrName like '%'
 and c.lastName like '%'
 and replace(replace(replace(replace(replace(cc.contact, ' ',''), '(',''), ')', ''), '-', ''), '+', '') like '%521%'
 and replace(replace(replace(replace(replace(cc1.contact, ' ',''), '(',''), ')', ''), '-', ''), '+', '') like '%8905%'

每個%表示用戶將在那里插入一些數據,例如like '%8905%

關於INDEX
我添加了下面的索引,所以這樣,我肯定無濟於事

  INDEX client_insurer (client_id, insurer_id),      
  INDEX policyType_id (policyType_id),
  INDEX Serial_Num (serial, number),

關於replace(replace...
我相信regexp會給我減少1秒鍾並添加它
如何從MySQL查詢中的字符串中提取數值?
溶劑化不會減少時間(實際上增加了5秒)

我不知道(mb粘貼條件從where join ?)如何讓它更快。 請幫我。

好吧,你沒有添加explain ,沒有關於你的數據的信息,沒有表結構,沒有關於(有用的)索引的信息。 沒有這個,優化只是一個有根據的猜測。

但無論如何我會嘗試。

我會嘗試一系列子查詢,因為你必須通過所有數據,因為喜歡。

select
 c.id,
 c.firstName,
 c.lastName,
 ...
 dt.code as docCode,
 dt.name as docName,
 cphone1 as as homePhone,
 cphone3 as cellPhone
from

( select *,
  replace(replace(replace(replace(replace(cc.contact, ' ',''), '(',''), ')', ''), '-', ''), '+', '') as cphone1,
  replace(replace(replace(replace(replace(cc1.contact, ' ',''), '(',''), ')', ''), '-', ''), '+', '') as cphone3
  from 
  (select c.id,
    (select max(pp.id) from ClientPolicy pp 
     where pp.client_id = c.id and pp.deleted = 0) as pmax,
    (select max(dd.id) FROM ClientDocument dd 
     WHERE dd.client_id = c.id and dd.deleted = 0) as dmax,
    (select MAX(ccc.id) FROM ClientContact ccc 
     where ccc.client_id = c.id and ccc.deleted = 0 
     and ccc.contactType_id = 1) as cmax1,
    (SELECT MAX(ccc1.id) FROM ClientContact ccc1 
     WHERE ccc1.client_id = c.id and ccc1.deleted = 0 
     and ccc1.contactType_id = 3) as cmax3
    from Client c        
    where c.deleted = 0
     and c.firstName like '%'
     and c.patrName like '%'
     and c.lastName like '%'
  ) as clientbase
  join ClientContact cc on cc.id = clientbase.cmax1
  join ClientContact cc1 on cc1.id = clientbase.cmax3
) as clientnamed
join client c on c.id = clientnamed.id
left join ClientPolicy p on p.id=clientnamed.pmax
left join rbPolicyType pt on pt.id = p.policyType_id
left join ClientDocument d on d.id = clientnamed.dmax
left join rbDocumentType dt on dt.id = d.documentType_id and dt.code = 1
where cphone1 like '%521%' and cphone3 like '%8905%';

如果您的搜索參數'%521%'或'%8905%'是可選的(例如並非總是給出),則必須使用left join ClientContact cc (對於cc1相同),但是沒有cphone1 like '%521%'在你的where (對於cphone3 like '%8905%'相同),因為它將再次充當join (而你的like '%'實際上也應該不在那里。)

如果您能夠在新列中以干凈的方式使用phonenumbers(例如,通過觸發器更新),您可能會得到改進。

現在索引:

您必須將id作為主鍵。

為Client(id,已刪除),ClientPolicy(id,已刪除)和ClientDocument(id,已刪除)創建索引。

您應該在ClientContact上嘗試索引(id,deleted,contact_type)或(id,contact_type,deleted) - 具體取決於您的數據:如果您有大量刪除的條目,則第一個應該更好,否則秒。

如果這些索引具有可衡量的效果取決於您的數據,但由於您沒有告訴我們有關您的數據的任何信息,請嘗試它(有很多索引會減慢您的插入/更新速度,所以不要垃圾郵件索引;但是再一次,你沒有告訴我們有關數據的任何信息,所以你必須自己試試。)

對於任何后續操作,您必須至少添加以下內容

  • explain看看mysql究竟在做什么
  • explain子查詢select c.id, (select max(pp.id) from ClientPolicy pp ... c.lastName like '%'不包含周圍的代碼
  • 獲取整個代碼和上述子查詢的結果所需的時間

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM