使用多个条件联接加快MySql查询时间
共有3个表,persontbl1、persontbl2,每个表中有7500行和约3000个活动计划,即schedule.status=0。Person表包含与一对一关系相同的人的数据,两个表之间的内部联接需要不到一秒钟的时间。时间表表包含了关于被采访人员的数据,并非所有人员都有时间表。使用Left-join查询立即需要大约45秒,这会导致各种问题使用多个条件联接加快MySql查询时间,mysql,sql,left-join,inner-join,Mysql,Sql,Left Join,Inner Join,共有3个表,persontbl1、persontbl2,每个表中有7500行和约3000个活动计划,即schedule.status=0。Person表包含与一对一关系相同的人的数据,两个表之间的内部联接需要不到一秒钟的时间。时间表表包含了关于被采访人员的数据,并非所有人员都有时间表。使用Left-join查询立即需要大约45秒,这会导致各种问题 SELECT persontbl1._CREATION_DATE, persontbl2._TOP_LEVEL_AURI, perso
SELECT persontbl1._CREATION_DATE, persontbl2._TOP_LEVEL_AURI,
persontbl2.RESP_CNIC, persontbl2.RESP_CNIC_NAME,
persontbl1.MOB_NUMBER1, persontbl1.MOB_NUMBER2,
schedule.id, schedule.call_datetime, schedule.enum_id,
schedule.enum_change, schedule.status
FROM persontbl1
INNER JOIN persontbl2 ON (persontbl2._TOP_LEVEL_AURI = persontbl1._URI)
AND (AGR_CONTACT=1)
LEFT JOIN SCHEDULE ON (schedule.survey_id = persontbl1._URI)
AND (SCHEDULE.status=0)
AND (DATE(SCHEDULE.call_datetime) <= CURDATE())
ORDER BY schedule.call_datetime IS NULL DESC, persontbl1._CREATION_DATE ASC
以下是查询的解释:
明细表结构:
明细表索引:
如果需要更多信息,请告诉我
谢谢
编辑:添加了完全限定的表名及其列。我猜AGR\u联系人来自p1。这是您要优化的查询:
SELECT p1._CREATION_DATE, _TOP_LEVEL_AURI, RESP_CNIC, RESP_CNIC_NAME,
MOB_NUMBER1, MOB_NUMBER2,
s.id, s.call_datetime, s.enum_id, s.enum_change, s.status
FROM persontbl1 p1 INNER JOIN
persontbl2 p2
ON (p2._TOP_LEVEL_AURI = p1._URI) AND (p1.AGR_CONTACT = 1) LEFT JOIN
SCHEDULE s
ON (s.survey_id = p1._URI) AND
(s.status = 0) AND
(DATE(s.call_datetime) <= CURDATE())
ORDER BY s.call_datetime IS NULL DESC, p1._CREATION_DATE ASC;
此查询的最佳索引是:persontbl2agr\u联系人、persontbl1\u顶级\u AURI、\u uri和schedulesurvey\u id、status、call\u datime
不建议使用日期时间前后的日期。一般来说,这排除了索引的使用。但是,在本例中,您有一个左连接,因此它没有什么区别。该列无论如何都不用于筛选。附表索引仅用于涵盖on条款。您只需替换此行:
AND (DATE(SCHEDULE.call_datetime) <= CURDATE())
编辑1,所以你说没有左连接部分,速度足够快,所以你可以尝试:
SELECT persontbl1._CREATION_DATE, persontbl2._TOP_LEVEL_AURI,
persontbl2.RESP_CNIC, persontbl2.RESP_CNIC_NAME,
persontbl1.MOB_NUMBER1, persontbl1.MOB_NUMBER2,
s.id, s.call_datetime, s.enum_id,
s.enum_change, s.status
FROM persontbl1
INNER JOIN persontbl2 ON (persontbl2._TOP_LEVEL_AURI = persontbl1._URI)
AND (AGR_CONTACT=1)
LEFT JOIN
(SELECT *
FROM SCHEDULE
WHERE status=0
AND call_datetime <= '2015-02-01 00:00:00'
) s
ON s.survey_id = persontbl1._URI
ORDER BY s.call_datetime IS NULL DESC, persontbl1._CREATION_DATE ASC
你的问题是什么?还要添加表定义。你应该用表别名限定所有列名,这样我们就知道列的来源了。@GordonLinoff表名被添加了。@Dorvalla查询优化,因为我是MySQL的初学者,所以我真的很想在这件事上有一些专家意见。Gordon,AGR_触点来自第一个表p1。我相应地修改了您的查询,并检查了索引,它仍然需要40秒,大约2-3秒,性能更好,提供了正确的日期时间。例如,今天的“2015-04-19 00:00:00”查询需要42秒,这没有任何区别:@Ayub,您能提供时间表结构吗?你有调用时的索引吗?datetime ans状态?它说“每个派生表都必须有自己的别名”,我也在用结构更新这个问题…oops。。。修复了…在“2015-02-01 00:00:00”结尾时的拼写错误,现在在“字段列表”中显示未知列“s.id”,是否要尝试使用teamviewer?
SELECT persontbl1._CREATION_DATE, persontbl2._TOP_LEVEL_AURI,
persontbl2.RESP_CNIC, persontbl2.RESP_CNIC_NAME,
persontbl1.MOB_NUMBER1, persontbl1.MOB_NUMBER2,
schedule.id, schedule.call_datetime, schedule.enum_id,
schedule.enum_change, schedule.status
FROM persontbl1
INNER JOIN persontbl2 ON (persontbl2._TOP_LEVEL_AURI = persontbl1._URI)
AND (AGR_CONTACT=1)
LEFT JOIN SCHEDULE ON (schedule.survey_id = persontbl1._URI)
AND (SCHEDULE.status=0)
AND (SCHEDULE.call_datetime <= '2015-02-01 00:00:00')
ORDER BY schedule.call_datetime IS NULL DESC, persontbl1._CREATION_DATE ASC
SELECT persontbl1._CREATION_DATE, persontbl2._TOP_LEVEL_AURI,
persontbl2.RESP_CNIC, persontbl2.RESP_CNIC_NAME,
persontbl1.MOB_NUMBER1, persontbl1.MOB_NUMBER2,
s.id, s.call_datetime, s.enum_id,
s.enum_change, s.status
FROM persontbl1
INNER JOIN persontbl2 ON (persontbl2._TOP_LEVEL_AURI = persontbl1._URI)
AND (AGR_CONTACT=1)
LEFT JOIN
(SELECT *
FROM SCHEDULE
WHERE status=0
AND call_datetime <= '2015-02-01 00:00:00'
) s
ON s.survey_id = persontbl1._URI
ORDER BY s.call_datetime IS NULL DESC, persontbl1._CREATION_DATE ASC