我遇到运行此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)
)
EDIT2
答案 0 :(得分:2)
由于您希望每天获得结果,因此需要使用函数date()
从日期时间列中提取日期。这使得索引无用。
您可以将reading_date
列拆分为reading_date
和reading_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
答案 1 :(得分: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的建议将列拆分为date
和{ {1}}列。
答案 2 :(得分: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更改为非null。空值和索引不是很合适。