select查询中的重复列可以更快地执行查询

时间:2017-11-21 12:38:55

标签: mysql database-performance

从MySQL 5.6中获取一些奇怪的行为。以下查询应该从连接中选择一些简单数据。哪个工作正常。

SELECT 
  f.followID, 
  l.object_id,
  l.created_at,
  ROUND(UNIX_TIMESTAMP(l.created_at)/(3600)) window
FROM fb_follow f LEFT JOIN fb_likes l ON f.followID = l.user_id
WHERE f.profileID = 1
  AND l.created_at > '20171119' LIMIT 1000;

当我错误地包含l.created_at行的副本时,会发生奇怪的事情。

SELECT 
  f.followID, 
  l.object_id,
  l.created_at,
  l.created_at,
  ROUND(UNIX_TIMESTAMP(l.created_at)/(3600)) window
FROM fb_follow f LEFT JOIN fb_likes l ON f.followID = l.user_id
WHERE f.profileID = 1
  AND l.created_at > '20171119' LIMIT 1000;

查询执行时间从~600ms到~350ms(对于f.profileID的不同值重复。查询时间较短的原因是什么?我的期望是,由于数据量较少,它至少会花费更少的时间回来?

1 个答案:

答案 0 :(得分:1)

两个缓存

SELECT更改为SELECT SQL_NO_CACHE,无法使用"查询缓存"。

通常在使用查询缓存时,查询时间为1毫秒或更短。 350ms表示它不是QC。

另一个主要缓存是InnoDB的buffer_pool。 (你 使用InnoDB,对吗?)当你第一次运行查询时,可能需要点击磁盘来获取索引和/或数据块。第二次,那些块可能仍然缓存在buffer_pool(在RAM中),因此查询会更快。

差异通常是10倍。但是有很多例外。 600 vs 350不适合这种模式,但这是不确定的。

所以,当时间做两件事时:

  1. SELECT SQL_NO_CACHE ...
  2. 运行查询两次,然后使用第二次计时。
  3. <强> EXPLAIN

    请为每个变体运行EXPLAIN SELECT ...。如果存在任何差异(我怀疑),这可能会给出新的洞察力,为什么&#34;重复一行改变了时间&#34;。

    <强> JOIN

    当您不需要时,请不要使用LEFT。它让读者感到困惑。由于您明确过滤了f.profileID = 1,因此会忽略LEFT(并且可以将其删除)。

    ORDER BY

    LIMIT没有ORDER BY通常是愚蠢的。你想要哪1000行?添加ORDER BY会使决策明确。是的,它可能会减慢查询速度。

    有用的索引

    为了获得更好的表现:

    `f` needs INDEX(followID, profileID)   -- in this order
    `u` needs INDEX(created_at)