如何让这个MySQL查询更快?

时间:2012-08-11 13:12:56

标签: php mysql performance

我有一个MySQL查询,有时需要1秒以上才能执行。查询如下:

SELECT `id`,`totaldistance` FROM `alltrackers` WHERE `deviceid`='FT_99000083426364' AND (`gpsdatetime` BETWEEN 1341100800 AND 1342483200) ORDER BY `id` DESC LIMIT 1

此查询在循环中运行,以检索该月某些日期的行等。这会导致页面加载时间超过25秒......

表结构如下:

CREATE TABLE IF NOT EXISTS `alltrackers` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `deviceid` varchar(50) NOT NULL,
  `lat` double NOT NULL,
  `long` double NOT NULL,
  `gpsdatetime` int(11) NOT NULL,
  `version` int(11) DEFAULT NULL,
  `totaldistance` int(11) NOT NULL DEFAULT '0',
  `distanceprocessed` tinyint(1) NOT NULL DEFAULT '0',
  PRIMARY KEY (`id`),
  UNIQUE KEY `id_deviceid` (`id`,`deviceid`),
  UNIQUE KEY `deviceid_id` (`deviceid`,`id`),
  KEY `deviceid` (`deviceid`),
  KEY `deviceid_gpsdatetime` (`deviceid`,`gpsdatetime`),
  KEY `gpsdatetime_deviceid` (`gpsdatetime`,`deviceid`),
  KEY `gpsdatetime` (`gpsdatetime`),
  KEY `id_deviceid_gpsdatetime` (`id`,`deviceid`,`gpsdatetime`)
) ENGINE=MyISAM  DEFAULT CHARSET=utf8 AUTO_INCREMENT=677242 ;

我添加了各种索引组合(请告诉我要删除哪些),以便尝试让MySQL使用索引进行查询,但无济于事。

这是EXPLAIN输出:

id  select_type  table  type  possible_keys  key  key_len  ref  rows  Extra  
1 SIMPLE alltrackers index deviceid_id,deviceid,deviceid_gpsdatetime,gpsdatet... PRIMARY 4 NULL 677238 Using where 

我使用ORDER BY ASC / DESC LIMIT 1的原因是因为我需要查询的第一行和最后一行。如果没有LIMIT 1运行查询并使用PHP来检索第一行和最后一行,它会更快吗?

非常感谢你的帮助!

2 个答案:

答案 0 :(得分:0)

我能想到的一些事情让我无法想象:

1。)我不是任何一个mySQL / DBA大师,但索引似乎有点矫枉过正。通常,我会确保查询或连接的列被编入索引;所以你想要一个用于deviceid和gpsdatetime。每个查询1秒钟并不可怕,因此您的回报可能会受到限制。

2.)尝试消除循环。如果你要回到数据库25次;你只需打开/关闭连接等就会产生开销。一次访问数据库可能会更快,然后使用PHP处理结果以获取所需的最终数据。

答案 1 :(得分:0)

我不能说出你的确切情况,但我发现查询所有行并忽略除了第一行之外的所有行都比限制语句更快(尽管这是使用SQL Server)。它很容易 - 删除你的限制1条款并试一试。然后,您可以使用PHP来读取第一个和最后一个,从而减少MySQL实例的负载(即运行单个查询而不是2个)。

顺便说一句,为什么你有两个具有相同列的唯一键 - id_deviceid和deviceid_id?删除所有索引,然后重新添加它们,你真的希望快速DB的索引尽可能少。