【问题标题】:Why does SQL query visit all rows and is very slow为什么SQL查询访问所有行并且很慢
【发布时间】:2017-11-06 02:50:59
【问题描述】:

“读数”表包含今天每 40 秒采集的读数。该查询返回 180 秒周期的平均值。 'time_stamp' 已编入索引。下面的查询返回合理数量的行(几百),但访问所有行并且表越大越慢。 WHERE 子句似乎并没有将其限制在今天的行中。

EXPLAIN SELECT DATE_FORMAT(time_stamp, '%Y-%m-%dT%T+00:00') , AVG(temp_c) FROM reading WHERE DATE(time_stamp) = CURDATE() GROUP BY round(UNIX_TIMESTAMP(time_stamp) / 180)

表架构: CREATE TABLE reading ( id bigint(20) NOT NULL AUTO_INCREMENT, time_stamp timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, temp_c float NOT NULL, pressure_hpa float NOT NULL, wind_speed_kt int(11) NOT NULL, wind_dir_degree int(11) NOT NULL, rain_mm float NOT NULL, rain_day_mm float NOT NULL, wind_gust_kt int(11) NOT NULL, humidity float DEFAULT NULL, PRIMARY KEY (id), KEY time_stamp (time_stamp), KEY time_stamp_idx (time_stamp) ) ENGINE=InnoDB AUTO_INCREMENT=1747097 DEFAULT CHARSET=latin1;

【问题讨论】:

  • WHERE 在 GROUP BY 之前。您可以通过删除 WHERE(或者可能通过 AVG 值)来验证这一点:)
  • 此外,查询似乎选择了当天的所有记录,因此在下午可能会明显变慢。
  • 您能告诉我round(UNIX_TIMESTAMP(time_stamp) / 180) 是做什么的吗?如果将UNIX_TIMESTAMP 函数应用于time_stamp 字段,则不使用索引。
  • @harshavmb round(UNIX_TIMESTAMP(time_stamp) / 180) 使时间段缩短 180 秒。
  • @quanglewangle 你能发布表格架构和一些示例数据吗?

标签: mysql performance indexing


【解决方案1】:
EXPLAIN SELECT 
    DATE_FORMAT(time_stamp, '%Y-%m-%dT%T+00:00') ,
    AVG(temp_c) 
FROM reading
WHERE DATE(time_stamp) = CURDATE() 
GROUP BY round(UNIX_TIMESTAMP(time_stamp) / 180) 

执行上述查询时,MySQL 优化器对索引扫描不感兴趣(可能是因为成本因素),而是启动全表扫描,问题似乎是因为WHERE DATE(time_stamp) = CURDATE()

将 where 子句更改为 time_stamp >= CURDATE() 后,我发现使用了索引并且获取的行数减少了,避免了全扫描。

因此,您的最终查询将是:

EXPLAIN SELECT 
    DATE_FORMAT(time_stamp, '%Y-%m-%dT%T+00:00') ,
    AVG(temp_c) 
FROM reading
WHERE time_stamp >= CURDATE() 
GROUP BY round(UNIX_TIMESTAMP(time_stamp) / 180);

我怀疑date(time_stamp) 的索引效率不高。 here 讨论了类似的主题(请参阅 ypercube 的回答)。

上述查询可以通过选择round(UNIX_TIMESTAMP(time_stamp) / 180) 的替代品来进一步改进,因为UNIX_TIMESTAMP(timestamp) 不使用索引。但是,我不会再尝试了。

希望这会有所帮助!

【讨论】:

  • 这会使其运行得更快:INDEX(time_stamp, temp_c)(“覆盖”索引)。
猜你喜欢
  • 1970-01-01
  • 2022-12-13
  • 1970-01-01
  • 1970-01-01
  • 2014-01-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-10-24
相关资源
最近更新 更多