简体   繁体   中英

How can I make this MySQL Query faster?

I have a MySQL query that sometimes takes over 1 second to execute. 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...

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.

Here is the EXPLAIN output:

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. Would it be faster to just run the query without LIMIT 1 and use PHP to retrieve the first and last rows?

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. 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. 1 second per query isn't horrendous, so your returns here might be limited.

2.) Try to eliminate the looping. If you're going back to the database 25 times; 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.

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). Its easy to do - remove your limit 1 clause and give it a try. 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).

Incidentally, why do you have 2 unique keys with the same columns in them - id_deviceid and deviceid_id? Remove all the indexes and then add them back in again, you really want as few indexes as possible for fast DBs.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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