MYSQL:连接表的性能低下
我有这3个表,但当我加入ref_practice_invoice_payment时,查询大约需要5秒钟++ 查询如下: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
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 <> '%'
)