SQL左连接需要太长时间

时间:2018-02-14 19:52:48

标签: mysql performance datetime

我需要运行一个需要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秒,我只获得了几毫秒

2 个答案:

答案 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? (较新版本将更好地执行此查询。)