在RPI /优化查询上运行MySQL

时间:2017-09-09 14:56:06

标签: mysql sql raspberry-pi

我有一个运行MySQL 5.5.57的raspberry PI 3 - 这是在RPI上运行的唯一服务。 我的应用程序进行了一个关键查询(如下所示),需要5-7秒才能在MySQL服务器上执行。

我已经做了很多工作来优化索引和FK,但它确实没有多大帮助。当我做一个解释时,我发现它是使用临时文件和文件,我不太懂。

  • 在RPI上运行mysql时是否应该进行任何配置调整。我对各种缓冲区了解不多......
  • 我还应该做些什么来优化查询?

该表有大约30,000行并且正在增长......

这是查询:

SELECT  SQL_NO_CACHE  distinct `photos`.* 
FROM `photos` 
LEFT OUTER JOIN `facets` ON `photos`.`id` = `facets`.`photo_id` 
WHERE (`photos`.`date_taken` <= '2017-08-24') 
AND (photos.status != 1 or photos.status is NULL) 
ORDER BY photos.date_taken DESC LIMIT 500 OFFSET 500;

这是表格设置:

CREATE TABLE `photos` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `date_taken` datetime DEFAULT NULL,
  `created_at` datetime NOT NULL,
  `updated_at` datetime NOT NULL,
  `file_extension` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
  `file_size` int(11) DEFAULT NULL,
  `location_id` bigint(20) DEFAULT NULL,
  `make` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
  `model` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
  `original_height` int(11) DEFAULT NULL,
  `original_width` int(11) DEFAULT NULL,
  `longitude` decimal(16,10) DEFAULT NULL,
  `latitude` decimal(16,10) DEFAULT NULL,
  `status` int(11) DEFAULT ''0'',
  `phash` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
  `org_id` int(11) DEFAULT NULL,
  `lg_id` int(11) DEFAULT NULL,
  `md_id` int(11) DEFAULT NULL,
  `tm_id` int(11) DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY `index_photos_on_location_id` (`location_id`),
  KEY `index_photos_on_date_taken` (`date_taken`),
  KEY `index_photos_on_status` (`status`),
  KEY `index_photos_on_phash` (`phash`),
  CONSTRAINT `fk_rails_47f4e5f105` FOREIGN KEY (`location_id`) REFERENCES `locations` (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=25672 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci

当我对查询做一个解释时,这就是我得到的:

+----+-------------+--------+-------+---------------------------------------------------+----------------------------+---------+-------------------+-------+----------------------------------------------+
| id | select_type | table  | type  | possible_keys                                     | key                        | key_len | ref               | rows  | Extra                                        |
+----+-------------+--------+-------+---------------------------------------------------+----------------------------+---------+-------------------+-------+----------------------------------------------+
|  1 | SIMPLE      | photos | range | index_photos_on_date_taken,index_photos_on_status | index_photos_on_date_taken | 9       | NULL              | 13147 | Using where; Using temporary; Using filesort |
|  1 | SIMPLE      | facets | ref   | index_facets_on_photo_id                          | index_facets_on_photo_id   | 9       | pt_prod.photos.id |     1 | Using index; Distinct                        |
+----+-------------+--------+-------+---------------------------------------------------+----------------------------+---------+-------------------+-------+----------------------------------------------+

查询有时会扩展为:

SELECT  DISTINCT `photos`.* 
FROM `photos`  
LEFT OUTER JOIN `facets` ON `photos`.`id` = `facets`.`photo_id` 
LEFT OUTER JOIN `tags` ON `facets`.`source_id` = `tags`.`id` 
LEFT OUTER JOIN `comments` ON `facets`.`source_id` = `comments`.`id` 
WHERE `photos`.`date_taken` >= '2017-01-25' 
AND `photos`.`date_taken` <= '2018-01-10' 
AND `locations`.`country_id` = 16 
AND `locations`.`city_id` = 21 
OR `facets`.`source_id` = 9 AND `facets`.`type` = 'AlbumFacet'
OR `facets`.`source_id` = 9  AND `facets`.`type` = 'TagFacet'

1 个答案:

答案 0 :(得分:2)

这是对问题的原始版本的回答。

您的查询仅使用第一个表中的列。我会把它写成:

SELECT  SQL_NO_CACHE `photos`.* 
FROM `photos` p
LEFT OUTER JOIN `facets` ON `photos`.`id` = `facets`.`photo_id` 
WHERE (p.`date_taken` <= '2017-08-24') AND (NOT p.status <=> 1) AND
      EXISTS (SELECT 1 FROM facets f WHERE pid = f.photo_id)
ORDER BY p.date_taken DESC
LIMIT 500 OFFSET 500;

删除SELECT DISTINCT应该有点胜利。您还应该在facets(photo_id)上有一个索引。

(date_taken, status)上的索引可能有所帮助。但是,目前还不清楚你的条件是多么有选择性,因此照片索引可能没什么用处。