我需要运行一个需要24秒的SQL查询。我尝试在两个日期时间列START_DATE和END_DATE创建索引,但我的连接在600秒后被中断。有没有办法写一个更快的查询?
SELECT tbl1.*,
tbl2.NAME
FROM ( SELECT * FROM table1
WHERE LOC_ID IN (%s)
AND START_DATE != END_DATE
AND START_DATE <= '2002-01-31'
AND END_DATE >= '2002-01-01') tbl1
LEFT JOIN
table2 as tbl2
ON tbl1.ID = tbl2.ID
编辑: 我尝试将where子句移到外面,将持续时间增加到120秒。
我将查询更改为建议但仍然需要24秒,我只获得了几毫秒
答案 0 :(得分:1)
我相信以下内容与您当前的逻辑同义,并且不会破坏在您的日期使用索引的能力:
SELECT tbl1.*,
tbl2.NAME
FROM table1 tbl1
LEFT JOIN table2 as tbl2
ON tbl1.ID = tbl2.ID
WHERE tbl1.LOC_ID IN (%s)
AND tbl1.START_DATE <> tbl1.END_DATE
AND tbl1.START_DATE <= '2002-01-31'
AND tbl1.END_DATE >= '2002-01-01';
即使没有索引,我怀疑这个,或者它的子查询形式会更快,因为CPU不必在表中的每条记录上拆分两个字段的dateparts来执行比较。
答案 1 :(得分:0)
SELECT *,
( SELECT NAME
FROM table2
WHERE ID = table1.id
) AS NAME
FROM table1
WHERE LOC_ID IN (%s)
AND START_DATE != END_DATE
AND START_DATE <= '2002-01-31'
AND END_DATE >= '2002-01-01';
使用这些索引:
INDEX(START_DATE),
INDEX(END_DATE),
INDEX(LOC_ID, START_DATE),
INDEX(LOC_ID, END_DATE)
您拥有的日期范围基本上无法优化;具有多个索引可为优化程序提供选择;它将根据数据的分布从中挑选。也就是说,更改相关月份可能会导致使用不同的索引。
以LOC_ID
开头的索引是(1)正在使用的单个LOC的优化,或者(2)LOC比任何一个日期都更好地进行过滤。
如果关系为1:many,子查询将失败;我猜它是1:1。为什么有table2?通常(并非总是)以1:1的关系建立两个表是不明智的。
除非您确实需要所有列,否则请勿使用SELECT *
。
请提供EXPLAIN SELECT ...
,SHOW CREATE TABLE
以及表格中有多少行。
什么版本的MySQL? (较新版本将更好地执行此查询。)