如何优化这个mysql查询(max、replace、left join)?

如何优化这个mysql查询(max、replace、left join)?,mysql,optimization,Mysql,Optimization,我知道每个人都不喜欢提问题,但我需要你的帮助。 这就是代码。它必须为用户获取信息 select c.id, c.firstName, c.lastName, ... dt.code as docCode, dt.name as docName, replace(replace(replace(replace(replace(cc.contact, ' ',''), '(',''), ')', ''), '-', ''), '+', '') as homePhone, repla

我知道每个人都不喜欢提问题,但我需要你的帮助。 这就是代码。它必须为用户获取信息

 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%'
每%表示用户将在其中插入一些数据,例如“%8905%

关于索引 我添加了如下所示的索引,所以这样做肯定不会有帮助

  INDEX client_insurer (client_id, insurer_id),      
  INDEX policyType_id (policyType_id),
  INDEX Serial_Num (serial, number),
关于替换。。。 我确信regexp只会给我少1秒钟的时间,并添加这个 溶剂化并没有减少时间,实际上多了5秒

我没有理想的粘贴条件从哪里加入?如何使它更快。请帮帮我。

好吧,你没有添加解释,没有关于数据的信息,没有表结构,没有关于有用索引的信息。如果没有这一点,优化只是一个有根据的猜测

不过我还是会试试的

我会尝试一系列的子查询,因为您必须检查所有的数据,因为喜欢

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%”是可选的(例如,并非总是给定),则必须对cc1使用left join ClientContact cc same,但在where same中不要使用类似“%521%”的cphone1,因为类似“%8905%”的cphone3,它将再次充当联接。您的类“%”实际上也不应该在其中

如果您能够以干净的方式将电话号码保存在新列中(例如,通过触发器更新),您可能会得到改进

现在转到索引:

您必须将id作为主键

为客户端id、已删除、ClientPolicy id、已删除和ClientDocument id、已删除创建索引

您应该尝试索引id、已删除、联系人类型或id、联系人类型、在ClientContact上删除-具体取决于您的数据:如果您有很多已删除的条目,第一个条目应该工作得更好,否则第二个条目会更好

如果这些索引会产生可测量的影响,这取决于您的数据,但由于您没有告诉我们有关您的数据的任何信息,请尝试使用大量索引会降低插入/更新的速度,因此不要垃圾邮件索引;但是,你没有告诉我们关于数据的任何信息,所以你必须自己尝试一下

对于任何后续操作,您必须至少添加以下内容

解释一下mysql到底在做什么 解释为子查询选择c.id,从ClientPolicy pp中选择maxpp.id。。。c、 类似“%”的lastName,不包含周围代码 获取整个代码和上述子查询的结果所需的时间 您没有添加解释,没有关于数据的信息,没有表结构,没有关于有用索引的信息。如果没有这一点,优化只是一个有根据的猜测

不过我还是会试试的

我会尝试一系列的子查询,因为您必须检查所有的数据,因为喜欢

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%”是可选的(例如,并非总是给定),则必须对cc1使用left join ClientContact cc same,但在where same中不要使用类似“%521%”的cphone1,因为类似“%8905%”的cphone3,它将再次充当联接。您的类“%”实际上也不应该在其中

如果您能够以干净的方式将电话号码保存在新列中(例如,通过触发器更新),您可能会得到改进

现在转到索引:

您必须将id作为主键

为客户端id、已删除、ClientPolicy id、已删除和ClientDocument id、已删除创建索引

您应该尝试索引id、已删除、联系人类型或id、联系人类型、在ClientContact上删除-具体取决于您的数据:如果您有很多已删除的条目,第一个条目应该工作得更好,否则第二个条目会更好

如果这些索引会产生可测量的影响,这取决于您的数据,但由于您没有告诉我们有关您的数据的任何信息,请尝试使用大量索引会降低插入/更新的速度,因此不要垃圾邮件索引;但是,你没有告诉我们关于数据的任何信息,所以你必须自己尝试一下

对于任何后续操作,您必须至少添加以下内容

解释一下mysql到底在做什么 解释为子查询选择c.id,从ClientPolicy pp中选择maxpp.id。。。c、 类似“%”的lastName,不包含周围代码 获取整个代码和上述子查询的结果所需的时间
好的,谢谢你,我昨天读了你的评论,没有时间回答。我会添加你需要的所有信息。此外,我的团队领导强烈批准了您的索引,如id、删除。非常感谢,谢谢,我昨天看了你的评论,没有时间回答。我会添加你需要的所有信息。此外,我的团队领导强烈批准了您的索引,如id、删除。PS:非常感谢