【问题标题】:How can I make this MySQL Query faster?如何使这个 MySQL 查询更快?
【发布时间】:2012-08-11 13:12:56
【问题描述】:

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

非常感谢您的帮助!

【问题讨论】:

  • 重复索引没有帮助。您可以向 MySQL 询问use a specific index。您可以尝试一个想法:为时间段创建一个(临时?)表,加入该表而不是硬编码范围SELECT device_id, MAX(id) WHERE <time condition> GROUP BY device_id,然后将其连接回原始表以获得对应于每个idtotaldistance .这也可能允许您在单个查询中获取多个时段的数据。

标签: php mysql performance


【解决方案1】:

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

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

【讨论】:

  • 谢谢。我删除了限制并使用 mysql_seek_row 命令读取第一个和最后一个结果。 LIMIT 导致查询运行缓慢并忽略索引...
【解决方案2】:

我能想到的几件事:

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

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

【讨论】:

    猜你喜欢
    • 2022-01-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-11-02
    • 1970-01-01
    • 2012-12-01
    • 1970-01-01
    相关资源
    最近更新 更多