此查询:
EXPLAIN SELECT ppi_loan.customerID,
loan_number,
CONCAT(forename, ' ', surname) AS agent,
name,
broker,
(SELECT timestamp
FROM ppi_sar_status
WHERE history = 0
AND (status = 10 || status = 13)
AND ppi_sar_status.loanID = ppi_loan.loanID) AS ppi_unsure_date,
fosSent,
letterSent,
(SELECT timestamp
FROM ppi_ques_status
WHERE status = 1
AND ppi_ques_status.loanID = ppi_loan.loanID
ORDER BY timestamp DESC LIMIT 1) AS sent_date,
ppi_ques_status.timestamp
FROM ppi_loan
LEFT JOIN ppi_assignments ON ppi_assignments.customerID = ppi_loan.customerID
LEFT JOIN italk.users ON italk.users.id = agentID
LEFT JOIN ppi_ques_status ON ppi_ques_status.loanID = ppi_loan.loanID
JOIN ppi_lenders ON ppi_lenders.id = ppi_loan.lender
JOIN ppi_status ON ppi_status.customerID = ppi_loan.customerID
JOIN ppi_statuses ON ppi_statuses.status = ppi_status.status
AND ppi_ques_status.status = 1
AND ppi_ques_status.history = 0
AND (cc_type = '' || (cc_type != '' AND cc_accepted = 'no'))
AND ppi_loan.deleted = 'no'
AND ppi_loan.customerID != 10
GROUP BY ppi_loan.customerID, loan_number
非常慢,以下是EXPLAIN查询的所有结果
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY ppi_ques_status ref loanID,status,history status 3 const 91086 Using where; Using temporary; Using filesort
1 PRIMARY ppi_loan eq_ref PRIMARY,customerID PRIMARY 8 ppimm.ppi_ques_status.loanID 1 Using where
1 PRIMARY ppi_lenders eq_ref PRIMARY PRIMARY 4 ppimm.ppi_loan.lender 1 Using where
1 PRIMARY ppi_assignments eq_ref customerID customerID 8 ppimm.ppi_loan.customerID 1
1 PRIMARY users eq_ref PRIMARY PRIMARY 8 ppimm.ppi_assignments.agentID 1
1 PRIMARY ppi_status ref status,customerID customerID 8 ppimm.ppi_loan.customerID 6
1 PRIMARY ppi_statuses eq_ref PRIMARY PRIMARY 4 ppimm.ppi_status.status 1 Using where; Using index
3 DEPENDENT SUBQUERY ppi_ques_status ref loanID,status loanID 8 func 1 Using where; Using filesort
2 DEPENDENT SUBQUERY ppi_sar_status ref loanID,status,history loanID 8 func 2 Using where
为什么要扫描这么多行以及为什么“使用临时;使用filesort”? 我无法删除任何子查询,因为我需要他们生成的所有结果
答案 0 :(得分:0)
正如评论中已经提到的,查询速度慢的主要原因是您似乎只有单列索引,而您需要多列索引来覆盖连接,过滤器和组。 / p>
此外,您的查询还有其他两个问题:
即使您仅在2个字段上group by
,其他几个字段也列在select
列表中,而不受聚合函数的约束,例如min()
。 MySQL允许在某些sql模式设置下运行此类查询,但它们仍然违反sql标准,可能会产生意想不到的副作用,除非你真的知道自己在做什么。
您在ppi_loan
表格中的left join
表格中有where
左表格的过滤条件。由于左连接的性质,这些记录不会从结果集中消除,但MySQL不会在它们上加入任何值。这些标准应移至group by
条款。
我要创建的索引:
ppi_sar_status:关于loanID,状态,历史记录字段的多列索引 - 我会考虑将其移至连接部分,因为此表不存在
ppi_ques_status:loanID,status,timestamp字段的多列索引 - 这将支持子查询和连接。请记住,子查询在解释中也有文件排序。
ppi_loan:至少是customerID上的多列索引,loan_number字段支持exists()
子句,因此至少避免使用filesort。您可以考虑根据它们对此索引的选择性在连接条件中添加其他字段。
我也不确定为什么你在连接中有最后2个状态表,因为你没有从中检索任何值。如果您使用这些表来消除某些记录,请考虑使用exists()
子查询而不是连接。在连接中,MySQL需要从所有连接的表中获取数据,而在Foreground
子查询中,它只检查结果集中是否存在至少1条记录而不从基础表中检索任何实际数据。