有3个表,persontbl1,persontbl2(每个7500行)和日程表(~3000个活动日程表,即schedule.status = 0)。人员表包含与一对一关系相同的人的数据,两者之间的INNER连接不到一秒钟。并且时间表包含有关被访问人员的数据,而不是所有人都有时间表中的时间表。使用左连接查询需要大约45秒,这会导致各种问题。
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
以下是查询说明:
日程表结构:
计划表索引:
如果需要任何进一步的信息,请告诉我。
感谢。
编辑:添加了完全限定的表名及其列。
答案 0 :(得分:1)
你应该只替换这一行:
AND (DATE(SCHEDULE.call_datetime) <= CURDATE())
到这一个:
AND SCHEDULE.call_datetime <= '2015-04-18 00:00:00'
所以mysql不会为每条记录调用2个函数,但会使用静态常量'2015-04-18 00:00:00'
。
如果您的查询是:
,那么您可以尝试提高性能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
编辑1 所以你说没有LEFT JOIN
部分它足够快,所以你可以试试:
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
答案 1 :(得分:0)
我猜AGR_CONTACT
来自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;
此查询的最佳索引是:persontbl2(agr_contact)
,persontbl1(_TOP_LEVEL_AURI, _uri)
和schedule(survey_id, status, call_datime)
。
不建议在日期时间周围使用date()
。通常,这会排除索引的使用。但是,在这种情况下,您有一个left join
,所以它没有什么区别。该列无论如何都不用于过滤。 schedule
上的索引仅用于涵盖on
子句。