简体   繁体   English

MySQL通过联接和位置进行优化排序

[英]MySQL order by optimization with joins and wheres

I have this query: 我有这个查询:

SELECT SQL_NO_CACHE  DISTINCT `photos`.* 
FROM `photos` 
INNER JOIN `locations` ON `photos`.`location_id` = `locations`.`id` 
LEFT OUTER JOIN `albums_photos` ON `photos`.`id` = `albums_photos`.`photo_id` 
LEFT OUTER JOIN `facets` ON `photos`.`id` = `facets`.`photo_id` 
LEFT OUTER JOIN `source_tags` ON `facets`.`source_id` = `source_tags`.`id` 
LEFT OUTER JOIN `source_comments` ON `facets`.`source_id` = `source_comments`.`id` 
WHERE (`photos`.`date_taken` <= '2017-08-24') 
AND (photos.status != 1 or photos.status is NULL) 
ORDER BY `photos`.`date_taken` DESC 
LIMIT 75 
OFFSET 0

It takes which takes 6-7 sec to run. 运行需要6-7秒。 When I take out the Order by clause: 当我取出Order by子句时:

SELECT SQL_NO_CACHE  DISTINCT `photos`.* 
FROM `photos` 
INNER JOIN `locations` ON `photos`.`location_id` = `locations`.`id` 
LEFT OUTER JOIN `albums_photos` ON `photos`.`id` = `albums_photos`.`photo_id` 
LEFT OUTER JOIN `facets` ON `photos`.`id` = `facets`.`photo_id` 
LEFT OUTER JOIN `source_tags` ON `facets`.`source_id` = `source_tags`.`id` 
LEFT OUTER JOIN `source_comments` ON `facets`.`source_id` = `source_comments`.`id` 
WHERE (`photos`.`date_taken` <= '2017-08-24') 
AND (photos.status != 1 or photos.status is NULL) 
LIMIT 75 
OFFSET 0

It takes 0.025 sec to run. 运行需要0.025秒。 So clearly something is not optimized. 因此很明显,某些事情没有得到优化。 I have these indices on photos 我在照片上有这些索引

Table, Non_unique, Key_name, Seq_in_index, Column_name, Collation, Cardinality, Sub_part, Packed, Null, Index_type, Comment, Index_comment
photos, 0, PRIMARY, 1, id, A, 21069, , , , BTREE, , 
photos, 1, index_photos_on_location_id, 1, location_id, A, 468, , , YES, BTREE, , 
photos, 1, index_photos_on_date_taken, 1, date_taken, A, 21069, , , YES, BTREE, , 
photos, 1, index_photos_on_status, 1, status, A, 2, , , YES, BTREE, , 
photos, 1, index_photos_on_phash, 1, phash, A, 21069, , , YES, BTREE, , 

Photos is set up as per: 照片设置如下:

Field, Type, Null, Key, Default, Extra
id, bigint(20), NO, PRI, , auto_increment
date_taken, datetime, YES, MUL, , 
created_at, datetime, NO, , , 
updated_at, datetime, NO, , , 
file_extension, varchar(255), YES, , , 
file_size, int(11), YES, , , 
location_id, bigint(20), YES, MUL, , 
make, varchar(255), YES, , , 
model, varchar(255), YES, , , 
original_height, int(11), YES, , , 
original_width, int(11), YES, , , 
longitude, decimal(16,10), YES, , , 
latitude, decimal(16,10), YES, , , 
status, int(11), YES, MUL, 0, 
phash, varchar(255), YES, MUL, , 
org_id, int(11), YES, , , 
lg_id, int(11), YES, , , 
md_id, int(11), YES, , , 
tm_id, int(11), YES, , , 

what can I do. 我能做什么。 Should I do the ordering in my app (rails or JS)? 我应该在我的应用程序(rails或JS)中进行订购吗?

-- EDIT -- -编辑-

I should add that when I take out all the joins but leave in the order by the time drops to below a sec. 我应该补充一点,当我删除所有联接但按顺序离开时(时间降到一秒以下)。 Makes me think I need an index across the joined columns and date_taken?? 让我觉得我需要一个跨连接列和date_taken的索引?

SELECT SQL_NO_CACHE  DISTINCT `photos`.* 
FROM `photos` 
WHERE (`photos`.`date_taken` <= '2017-08-24') 
AND (photos.status != 1 or photos.status is NULL) 
#AND (`photos`.`date_taken` is not null)
ORDER BY `photos`.`date_taken` DESC 
LIMIT 75 
OFFSET 0;

if the tables contains a pk (eg: an id auto_increment) the distinct photos.* is unuseful 如果表格中包含pk(例如:id为auto_increment),则distinct photos.*是无用的
each row id different from the others 每行ID与其他行不同

remove unuseful () in where condition 在条件中删除无用的()

and remember that the limit is applied after al the rows are retrieved and ordered by (for this try removing limit and offset for test) 并记住,在对所有行进行检索并按以下顺序排序后才应用限制(为此,尝试删除限制和偏移量进行测试)

SELECT SQL_NO_CACHE   `photos`.* 
FROM `photos` 
INNER JOIN `locations` ON `photos`.`location_id` = `locations`.`id` 
LEFT JOIN `albums_photos` ON `photos`.`id` = `albums_photos`.`photo_id` 
LEFT JOIN `facets` ON `photos`.`id` = `facets`.`photo_id` 
LEFT JOIN `source_tags` ON `facets`.`source_id` = `source_tags`.`id` 
LEFT JOIN `source_comments` ON `facets`.`source_id` = `source_comments`.`id` 
WHERE `photos`.`date_taken` <= '2017-08-24'
AND  (photos.status != 1 or photos.status is NULL) 
ORDER BY `photos`.`date_taken` DESC 
LIMIT 75 
OFFSET 0

be sure you have proper index on all the join columun and foreign key and over all a proper index on photos.date_taken and photos.status 确保在所有联接列和外键上都具有正确的索引,并且在photos.date_takenphotos.status上都具有正确的索引

you could use also a composite index (photos.date_taken ,photos.status) 您还可以使用复合索引(photos.date_taken ,photos.status)

Try it like this.Faced a similar issue and fixed it like this. 像这样尝试。面对类似的问题,并像这样解决。

SELECT * FROM(
SELECT SQL_NO_CACHE  DISTINCT `photos`.* 
FROM `photos` 
INNER JOIN `locations` ON `photos`.`location_id` = `locations`.`id` 
LEFT OUTER JOIN `albums_photos` ON `photos`.`id` = `albums_photos`.`photo_id` 
LEFT OUTER JOIN `facets` ON `photos`.`id` = `facets`.`photo_id` 
LEFT OUTER JOIN `source_tags` ON `facets`.`source_id` = `source_tags`.`id` 
LEFT OUTER JOIN `source_comments` ON `facets`.`source_id` = `source_comments`.`id` 
WHERE (`photos`.`date_taken` <= '2017-08-24') 
AND (photos.status != 1 or photos.status is NULL)
)ORDER BY `photos`.`date_taken` DESC 
LIMIT 75 
OFFSET 0

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

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