2017-08-30 46 views
1

我有這個疑問:mysql命令通過優化連接和哪來

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 

它需要這需要6-7秒來運行。當我拿出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 

運行需要0.025秒。所以顯然沒有優化。 我有照片,這些指標

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, , 

照片設置爲每個:

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, , , 

我能做些什麼。我應該在我的應用程序(rails或JS)中進行排序嗎?

- 編輯 -

我要補充的是,當我拿出所有的聯接,但離開的時候訂單下降到低於秒。讓我覺得我需要在連接的列和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; 
+0

你有多少行在表格進行適當的指數? .. photos.id是auto_increment?(每行有一個不同的id?) – scaisEdge

+0

添加了表定義。是的,它是auto_increment。我有21000行和增長... – martin

+0

有一篇文章解釋延遲行查找解釋。也許這可以幫助。 – Strawberry

回答

2

如果表包含PK(例如:一個id AUTO_INCREMENT)的distinct photos.*是無用
不同於其它各行ID

除去無用()在條件

和記該限制適用於在行被檢索並排序之後(對於此嘗試移除限制和測試偏移)

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 

確保你對所有連接columun和外鍵 並在所有適當的指數photos.date_takenphotos.status

你也可以使用一個綜合指數(photos.date_taken ,photos.status)

+0

這是獨特的條款......我補充說,因爲我因爲連接而得到重複。這是一個總體糟糕的解決方案 - 應該更多地與聯合工作。 – martin

+0

當你說在連接列上有正確的索引時,你的意思是有並在facets.photo_id上索引,對吧? – martin

+1

是的......但請記住where子句中涉及的索引..這主要是爲了減少在連接中使用的行集合。 – scaisEdge

0

像這樣試一下。發現了類似的問題並修復了它。

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 
+0

試過了...... 6.3秒 - 沒有變化。 – martin

+0

只是出於好奇。當你通過照片表的主鍵進行訂購時,它會比這更快地執行嗎? –

+0

不用它是一樣的 - 已經嘗試過...... :-) – martin