MYSQL:连接表的性能低下

MYSQL:连接表的性能低下,mysql,performance,join,explain,Mysql,Performance,Join,Explain,我有这3个表,但当我加入ref_practice_invoice_payment时,查询大约需要5秒钟++ 查询如下: SELECT * FROM practice_invoice_detail PID LEFT JOIN ref_practice_invoice_payment RPIP ON RPIP.timestamp = PID.timestamp AND RPIP.practice_id = PID.practice_id AND RPIP.r

我有这3个表,但当我加入ref_practice_invoice_payment时,查询大约需要5秒钟++

查询如下:

SELECT * 
  FROM practice_invoice_detail PID 
  LEFT 
  JOIN ref_practice_invoice_payment RPIP 
    ON RPIP.timestamp = PID.timestamp 
   AND RPIP.practice_id = PID.practice_id
   AND RPIP.refunded <> 1 
   AND RPIP.other_bill = 0 
  JOIN practice_invoice_header PIH 
    ON PIH.timestamp = PID.timestamp 
   AND PIH.practice_id = PID.practice_id 
   AND PIH.is_active = 1
WHERE PIH.source = 'E' 
   AND PID.practice_id = 28618 
   AND (
         (RPIP.pay_cal_id >= 201805130 AND RPIP.pay_cal_id <= 201805200) 
       OR (PIH.cal_id >= 201805130 AND PIH.cal_id <= 201805200 AND PIH.total_invoice = 0 AND PID.item_comission_type <> '%')
           )
下面是对上述问题的解释

1   SIMPLE  PIH ref PRIMARY,source,practice_id,timestamp,is_active,practice_id_3,cal_id,practice_id_5,practice_id_6,practice_id_2,practice_id_4,practice_id_7,practice_id_8,total_invoice   practice_id_6   4   const   40228   Using index condition   
1   SIMPLE  PID ref timestamp,practice_id,timestamp_2,practice_id_2,practice_id_3,item_comission_type,timestamp_3,timestamp_4   timestamp   12  k6064619_lokadok.PIH.timestamp,const    1       
1   SIMPLE  RPIP    ref timestamp,practice_id,timestamp_2,refunded,other_bill,timestamp_3   timestamp   8   k6064619_lokadok.PIH.timestamp  1   Using where 
连接查询很简单,但是查询花费的时间有点太长。然而,数据相当多,但我认为还是不错的。大约20万行

进一步调查结果: 奇怪的是,如果我删除这个部分,查询速度会在1秒以下

(RPIP.pay_cal_id >= 201805130 AND RPIP.pay_cal_id <= 201805200) 

上述查询可以写成:

SELECT * FROM 
(SELECT * FROM practice_invoice_detail WHERE practice_id = 28618 ) as PID 

LEFT JOIN 
(SELECT * FROM ref_practice_invoice_payment WHERE practice_id = 28618 AND refunded <> 1 AND other_bill = 0 ) as RPIP 
ON RPIP.timestamp = PID.timestamp 

JOIN 
(SELECT * FROM practice_invoice_header WHERE practice_id = 28618 AND is_active = 1 AND source = 'E' ) as PIH 
ON PIH.timestamp = PID.timestamp 

WHERE 
( (RPIP.pay_cal_id >= 201805130 AND RPIP.pay_cal_id <= 201805200) 
OR (PIH.cal_id >= 201805130 AND PIH.cal_id <= 201805200 AND PIH.total_invoice = 0 AND PID.item_comission_type <> '%') ) ;    
请尝试在practice\u id、退款、其他账单和practice\u id、是否活动、来源和放映后解释结果上添加索引。

部分帮助:

PIH:  INDEX(timestamp, source, is_active, total_invoice, cal_id)
PID:  INDEX(practice_id, item commission_type)
RPIP: INDEX(practice_id, timestamp, other_bill, pay_cal_id)

RPIP.pay_cal_id>=201805130和RPIP.pay_cal_id第1步:仅选择您实际想要返回的列。此外,我觉得名为paid的列不太可能有浮点数据类型。此外,我找不到实践_id6您还可以为连接字段添加索引:RPIP.timestamp、PID.timestamp、PIH。timestamp@IgrewupwithSlackware,我相信我已经索引了我尝试过的每个表上的所有时间戳,但是查询仍然花费了大约相同的时间6++秒。根据show explain,没有使用新的索引?我添加了上面的解释,仍然花费了很长的时间,但我注意到存在索引合并。我将首先修复索引,然后再次查看多个派生表会显著降低查询速度。最好是修正原来的公式,视情况而定。它可能会强制查询优化器使用一些索引。在这种情况下,它没有任何帮助。最后,尝试使用您的建议进行测试,结果成功了。或者确实使索引变得无用。谢谢
SELECT * FROM 
(SELECT * FROM practice_invoice_detail WHERE practice_id = 28618 ) as PID 

LEFT JOIN 
(SELECT * FROM ref_practice_invoice_payment WHERE practice_id = 28618 AND refunded <> 1 AND other_bill = 0 ) as RPIP 
ON RPIP.timestamp = PID.timestamp 

JOIN 
(SELECT * FROM practice_invoice_header WHERE practice_id = 28618 AND is_active = 1 AND source = 'E' ) as PIH 
ON PIH.timestamp = PID.timestamp 

WHERE 
( (RPIP.pay_cal_id >= 201805130 AND RPIP.pay_cal_id <= 201805200) 
OR (PIH.cal_id >= 201805130 AND PIH.cal_id <= 201805200 AND PIH.total_invoice = 0 AND PID.item_comission_type <> '%') ) ;    
PIH:  INDEX(timestamp, source, is_active, total_invoice, cal_id)
PID:  INDEX(practice_id, item commission_type)
RPIP: INDEX(practice_id, timestamp, other_bill, pay_cal_id)
( SELECT ...
     FROM ...
     WHERE PIH.source = 'E'
      AND  PID.practice_id = 28618
      AND  RPIP.pay_cal_id >= 201805130
      AND  RPIP.pay_cal_id <  201805200
) UNION
( SELECT ...
     FROM ...
     WHERE PIH.source = 'E'
      AND  PID.practice_id = 28618
      AND  PIH.cal_id >= 201805130
      AND  PIH.cal_id <  201805200
      AND  PIH.total_invoice = 0
      AND  PID.item_comission_type <> '%'
)