如何加快或改善此查询?

时间:2019-10-17 01:17:28

标签: mysql

我有一个具有以下结构的表:


id    widget_id    value    date_recorded
-----------------------------------------------
1         1          10     2019-10-12 12:00:15
2         2          15     2019-10-12 12:00:15
3         3          20     2019-10-12 12:00:15
4         4          50     2019-10-12 12:00:15 
5         1          12     2019-10-15 00:05:15
6         2          19     2019-10-15 00:05:15
7         3          25     2019-10-15 00:05:15
8         4          75     2019-10-15 00:05:15

该表大约有500,000条记录,因为我们需要保留小部件值的历史数据。大约有三百种不同的唯一窗口小部件ID,每个ID的记录数量相同,因此每个ID的记录数不到1700条。

大多数时候,我们只需要获取给定ID或所有ID的最新值,但我发现查询所花的时间比预期的长,尤其是在遍历所有需要的ID时。

我尝试了以下两个查询:

第一个需要花费三百到五百个MS。总计超过三百条记录。

SELECT 
  widget_id,
  value,
  date_recorded
  FROM widget_values
  WHERE  widget_id = 1
  ORDER BY date_recorded DESC
  LIMIT 1

这需要500毫秒或更长时间

SELECT 
  widget_id,
  value,
  date_recorded
  FROM widget_values
  WHERE widget_id = 1
  AND date_recorded = (
      SELECT 
      MAX(date_recorded)
      FROM widget_values
      WHERE widget_id = 1
      )

我想知道以下情况:

  1. 有什么方法可以更快地执行这些操作,或者在一个查询中获取所有唯一ID的最新值?
  2. 由于该数据集每几个月将增加一倍,是否有更好的策略将相关ID的最新值存储在单独的表中,因此获取它们的操作不太繁琐?因此,我将有一个表存储历史值,而另一个表仅包含300个最新值。这听起来像是某种设计违规,但也似乎是一个解决日益严重的问题的公平解决方案。

| widget_values | CREATE TABLE `widget_values` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `widget_id` int(11) DEFAULT NULL,
  `value` int(11) NOT NULL,
  `date_recorded` datetime NOT NULL,
  PRIMARY KEY (`id`),
  KEY `widget_id` (`widget_id`),
  KEY `value` (`value`),
  KEY `date_recorded` (`date_recorded`),
  CONSTRAINT `widget_amounts_one` FOREIGN KEY (`widget_id`) REFERENCES `widget_codes` (`widget_id`) ON DELETE SET NULL ON UPDATE CASCADE
) ENGINE=InnoDB 

3 个答案:

答案 0 :(得分:1)

date_recorded列是什么意思?如果仅是数据的创建时间,则可以使用列id进行排序:


SELECT 
  widget_id,
  value,
  date_recorded
  FROM widget_values
  WHERE  widget_id = 1
  ORDER BY id DESC
  LIMIT 1

这将命中主键索引。

答案 1 :(得分:0)

( widget_id , date_recorded )上的多列索引将为您提供帮助。

拥有多个索引的主要缺点是,每次插入,更新,删除都要付出代价。

要优化对表的访问时,必须针对该表验证每个不同的查询,并查看索引是否正确。

一种可能的优化是删除列id,并将widget_id , date_recorded变成primary key。因此,您将只有一个索引。如果其他表需要引用单个行,则此优化就没有意义,因为您将使用更多字节来存储引用widget_id , date_recorded

答案 2 :(得分:0)

除了在表上有索引外,您还可以尝试在下面的查询中提高性能-

SELECT 
  widget_id,
  value,
  date_recorded
FROM widget_values
WHERE widget_id = 1
ORDER BY date_recorded DESC
LIMIT 1;
相关问题