需要优化SQL查询 - 需要花费大量时间来执行

时间:2017-04-11 15:39:45

标签: mysql sql optimization query-optimization

我们有一个以下查询,大约需要6-8秒才能执行。 总记录数:522954

(SELECT 
        * 
      FROM
        tbl_insights_copy
      WHERE insightscat = 21 
        AND submitedon >= UNIX_TIMESTAMP(DATE_SUB(NOW(), INTERVAL 30 DAY)) 
      ORDER BY submitedon DESC 
      LIMIT 5) 
      UNION
      (SELECT 
        * 
      FROM
        tbl_insights_copy 
      WHERE insightscat = 22 
        AND submitedon >= UNIX_TIMESTAMP(DATE_SUB(NOW(), INTERVAL 30 DAY)) 
      ORDER BY submitedon DESC 
      LIMIT 5) 
      UNION
      (SELECT 
        * 
      FROM
        tbl_insights_copy 
      WHERE insightscat = 23 
        AND submitedon >= UNIX_TIMESTAMP(DATE_SUB(NOW(), INTERVAL 30 DAY)) 
      ORDER BY submitedon DESC 
      LIMIT 5) 
      UNION
      (SELECT 
        * 
      FROM
        tbl_insights_copy 
      WHERE insightscat = 24 
        AND submitedon >= UNIX_TIMESTAMP(DATE_SUB(NOW(), INTERVAL 30 DAY)) 
      ORDER BY submitedon DESC 
      LIMIT 5)

有人可以帮助优化此查询以减少执行时间。 提前谢谢。

4 个答案:

答案 0 :(得分:1)

你在一个选择和另一个选择之间唯一改变的是列insightscat的过滤值。我不确定这是你想要的但是......

您可以尝试IN指令。例如:

SELECT 
        * 
FROM
        tbl_insights_copy 
      WHERE insightscat in (20,21,22,23,24)
        AND submitedon >= UNIX_TIMESTAMP(DATE_SUB(NOW(), INTERVAL 30 DAY)) 
      ORDER BY submitedon DESC 

答案 1 :(得分:0)

对于此查询:

reallyComplicatedFunction

您需要SELECT ic.* FROM tbl_insights_copy ic WHERE insightscat = 21 AND submitedon >= UNIX_TIMESTAMP(DATE_SUB(NOW(), INTERVAL 30 DAY)) ORDER BY submitedon DESC LIMIT 5 上的索引。

这适用于所有子查询。这可能是MySQL的最佳方法。

答案 2 :(得分:0)

    SELECT t1.*
   FROM (SELECT t.* ,ROW_NUMBER() OVER (ORDER BY insightscat) AS Row
       FROM 
       (select * from        
        tbl_insights_copy 
         WHERE insightscat in (20,21,22,23,24)
        AND submitedon >= UNIX_TIMESTAMP(DATE_SUB(NOW(), INTERVAL 30 DAY)) 
        ORDER BY submitedon DESC ) as t ) t1
   WHERE Row <= 5 

答案 3 :(得分:0)

如果没有SHOW CREATE TABLE,我将不得不猜测你没有最佳的

INDEX(insightscat, submitedon)

由于SELECTs不同,请使用UNION ALL代替默认UNION DISTINCT。这样可以避免在20行上进行不必要的(但很快)的重复传递。

如果你想要20行

如果是这样,我上面的建议可能是最好的。

如果您想要6行

如果您只需要来自任何的最新5个洞察猫,那么有3种可能性。

计划A

Developer90在评论中说了什么。

计划B

( SELECT ... ORDER BY ORDER BY submitedon DESC LIMIT 5)
UNION ALL
( SELECT ... ORDER BY ORDER BY submitedon DESC LIMIT 5)
UNION ALL
( SELECT ... ORDER BY ORDER BY submitedon DESC LIMIT 5)
UNION ALL
( SELECT ... ORDER BY ORDER BY submitedon DESC LIMIT 5)
ORDER BY ORDER BY submitedon DESC LIMIT 5;

我的索引每个SELECT都非常快。然后,UNION的20行再次排序并应用LIMIT 5。再次,非常快。

使用Developer90建议的IN,可能会也可能不会有效地使用我的索引。你用的是哪个版本?

计划C

此选项已命中或未命中。也就是说,它的性能在很大程度上取决于数据的分布是否会非常快或非常慢:Developer90 + INDEX(submitedon)(不包括insightscat)。