0

我有一个 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 使用索引进行查询,但无济于事。

这是解释输出:

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 检索第一行和最后一行会更快吗?

非常感谢您的帮助!

4

2 回答 2

0

我能想到的几件事:

1.) 无论如何我都不是 mySQL/DBA 大师,但那里的索引似乎有点矫枉过正。通常,我会确保对查询或连接的列进行索引;所以你想要一个用于 deviceid 和 gpsdatetime。每次查询 1 秒并不可怕,因此您在这里的回报可能会受到限制。

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

于 2012-08-11T13:24:49.433 回答
0

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

顺便说一句,为什么你有 2 个具有相同列的唯一键 - id_deviceid 和 deviceid_id?删除所有索引,然后重新添加它们,对于快速数据库,您确实希望尽可能少的索引。

于 2012-08-11T13:25:06.757 回答