不使用 min() max() 获取选择的第一条和最后一条记录

32S*_*oth 2 mysql query-performance

我的能量计每分钟将(累计)消耗写入 db。为了获得我今天的消费,我使用:

SELECT
  (MAX(energy_kwh) - MIN(energy_kwh)) AS kwh_today
FROM logging.main_meter
WHERE DATE_FORMAT(strtime, '%Y-%m-%d') = CURDATE();
Run Code Online (Sandbox Code Playgroud)

问题是: max() 和 min() 似乎大大减慢了查询速度。我在列中添加了一个键,energy_kwh但没有帮助。我敢打赌有更好的方法来获得计算的第一个和最后一个记录。

表格(实际上要大得多,约 130 列,所以我将其缩小到相关部分):

CREATE TABLE 'main_meter` 
( 
  id int(11) NOT NULL AUTO_INCREMENT, 
  timestamp int(11) DEFAULT NULL, 
  strtime datetime DEFAULT NULL, 
  energy_kwh double unsigned DEFAULT '0', 
) ENGINE=InnoDB AUTO_INCREMENT=1717655 DEFAULT CHARSET=latin1;
Run Code Online (Sandbox Code Playgroud)

32S*_*oth 9

事实证明,MIN()/MAX()降低查询速度的不是函数,而是

WHERE DATE_FORMAT(strtime, '%Y-%m-%d') = CURDATE()
Run Code Online (Sandbox Code Playgroud)

陈述。由于该表有一个带有 unix-timestap 的列,因此使用它可以大大加快它的速度:

WHERE TIMESTAMP > UNIX_TIMESTAMP(CURDATE())
Run Code Online (Sandbox Code Playgroud)

查询时间从 ~3.6s 下降到 ~0.02s。我称之为很好的改进。

  • 您已经正确地将 `strtime` 识别为问题,应该将其编入索引。但是,`WHERE DATE_FORMAT(strtime, '%Y-%m-%d') = CURDATE()` 和`WHERE TIMESTAMP > UNIX_TIMESTAMP(CURDATE())` 并不相同。第一个检查 `strtime` 是否在当前日期。第二个检查`tiimestamp` 是否在*当前日期之后*。真正的问题是使用`date_format` 意味着它不能使用索引。 (2认同)