简体   繁体   English

如何使此MySQL查询更快?

[英]How can I make this MySQL Query faster?

I have a MySQL query that sometimes takes over 1 second to execute. 我有一个MySQL查询,有时需要1秒钟以上的时间来执行。 The query is as follows: 查询如下:

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

This query is run in a loop to retrieve rows on certain days of the month and such. 该查询循环运行以检索每月某天等的行。 This causes the page to take over 25 seconds to load sometimes... 这有时导致页面加载需要25秒以上的时间...

The table structure is as follows: 表结构如下:

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 ;

I have added all kinds of index combinations (please tell me which to remove) in order to try and get MySQL to use indices for the query, but to no avail. 我添加了各种索引组合(请告诉我要删除的索引组合),以尝试使MySQL在查询中使用索引,但无济于事。

Here is the EXPLAIN output: 这是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 

The reason I'm using ORDER BY ASC/DESC LIMIT 1 is because I need the first and last rows of the query. 我使用ORDER BY ASC / DESC LIMIT 1的原因是因为我需要查询的第一行和最后一行。 Would it be faster to just run the query without LIMIT 1 and use PHP to retrieve the first and last rows? 仅运行不带LIMIT 1的查询并使用PHP检索第一行和最后一行会更快吗?

Many thanks for your help! 非常感谢您的帮助!

Couple things I can think of off the top of my head: 我想到的几件事:

1.) I'm not a mySQL/DBA guru by any stretch, but the index there seems like a bit of overkill. 1.)无论如何我都不是mySQL / DBA专家,但是那里的索引似乎有点过分了。 Typically I'll make sure that columns that are either queried on or joined on are indexed; 通常,我将确保对要查询或连接的列进行索引; so you'd want one for deviceid and gpsdatetime. 因此,您需要一个用于deviceid和gpsdatetime。 1 second per query isn't horrendous, so your returns here might be limited. 每个查询1秒并不可怕,因此您在这里的返回可能会受到限制。

2.) Try to eliminate the looping. 2.)尝试消除循环。 If you're going back to the database 25 times; 如果您要返回数据库25次; you're going to incur overhead simply opening/closing connections and such. 您将仅通过打开/关闭连接等来产生开销。 It might be faster to go to the database once, and then process the results using PHP to get the final data you need. 一次进入数据库,然后使用PHP处理结果以获得所需的最终数据可能会更快。

I can't say for your exact case, but I have found that querying all rows and ignoring all but the first is faster than a limit statement (this was using SQL Server though). 我不能说出您的确切情况,但是我发现查询所有行并忽略除第一个之外的所有行都比limit语句快(尽管这是使用SQL Server)。 Its easy to do - remove your limit 1 clause and give it a try. 这很容易-删除您的limit 1子句并尝试一下。 You can then use the PHP to read the first and last thus reducing the load on the MySQL instance (ie running a single query rather than 2). 然后,您可以使用PHP读取第一个和最后一个,从而减少MySQL实例的负载(即,运行单个查询而不是2)。

Incidentally, why do you have 2 unique keys with the same columns in them - id_deviceid and deviceid_id? 顺便说一句,为什么您有两个具有相同列的唯一键-id_deviceid和deviceid_id? Remove all the indexes and then add them back in again, you really want as few indexes as possible for fast DBs. 删除所有索引,然后再次添加它们,对于快速数据库,您确实确实希望尽可能少的索引。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM