1

我在运行此 SQL 时遇到问题:

在此处输入图像描述

我认为这是一个index problem但我不知道,因为我没有制作这个数据库,我只是一个简单的程序员。

问题是,该表有 64260 条记录,因此查询在执行时变得疯狂,我不得不停止 mysql 并再次运行,因为计算机被冻结了。

谢谢。

编辑:表架构

CREATE TABLE IF NOT EXISTS `value_magnitudes` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `value` float DEFAULT NULL,
  `magnitude_id` int(11) DEFAULT NULL,
  `sdi_belongs_id` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
  `reading_date` datetime DEFAULT NULL,
  `created_at` datetime DEFAULT NULL,
  `updated_at` datetime DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB  DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci AUTO_INCREMENT=1118402 ;

询问

select * from value_magnitudes
where id in 
(
    SELECT min(id)
    FROM value_magnitudes
    WHERE magnitude_id = 234
    and date(reading_date) >= '2013-04-01'
    group by date(reading_date)
)

编辑2

在此处输入图像描述

4

3 回答 3

2

由于您想获得每天的结果,您需要使用函数从日期时间列中提取日期date()。这使得索引毫无用处。

您可以将reading_date列拆分为reading_datereading_time。然后您可以在没有函数的情况下运行查询,并且索引将起作用。

此外,您可以将查询更改为join

select * 
from value_magnitudes v
inner join 
(
    SELECT min(id) as id
    FROM value_magnitudes
    WHERE magnitude_id = 234
    and reading_date >= '2013-04-01'
    group by reading_date
) x on x.id = v.id
于 2013-05-10T11:30:54.840 回答
2

首先,在 上添加一个索引(magnitude_id, reading_date)

ALTER TABLE
  ADD INDEX magnitude_id__reading_date__IX       -- just a name for the index
    (magnitude_id, reading_date) ;

然后尝试这种变化:

SELECT vm.* 
FROM value_magnitudes AS vm
  JOIN 
  ( SELECT MIN(id) AS id
    FROM value_magnitudes
    WHERE magnitude_id = 234
      AND reading_date >= '2013-04-01'         -- changed so index is used
    GROUP BY DATE(reading_date)
  ) AS vi
    ON vi.id = vm.id ;

仍然需要将该GROUP BY DATE(reading_date)函数应用于所有选定的(通过索引)行并且无法改进,除非您遵循@jurgen 的建议并将列拆分为datetime列。

于 2013-05-10T11:42:09.443 回答
1

对于初学者,我会将您的查询更改为:

select * from value_magnitudes where id = (
  select min(id) from value_magnitudes
  where magnitude_id = 234
  and DATE(reading_date) >= '2013-04-01' 
)

当子查询只返回一条记录时,您不需要使用 IN 子句。

然后,我会确保你在magnitude_id 和reading_date 上有一个索引(可能是一个两字段索引),因为这就是你在子查询中查询的内容。如果没有该索引,您每次都在扫描表。

此外,如果可能,将magnitude_id 和reading_date 更改为非空。空值和索引不是很合适。

于 2013-05-10T11:24:30.430 回答