2012-03-30 67 views
0

如下表結構這怎麼MySQL查詢優化

images     data 
------------------ ---------------------------------- 
| id | filename | | fromImageId | toImageId | result | 
------------------ ---------------------------------- 

我有以下SELECT獲得所有images.filename沒有在data一個條目(或者fromImageIdtoImageId

SELECT image.id, image.filename 
FROM images image 
WHERE NOT EXISTS(
    SELECT fromImageId, toImageId 
    FROM data results 
    WHERE fromImageId = image.id 
     OR toImageId = image.id 
) ORDER BY image.id 

由於data表格非常大(500,000+),因此此查詢花費很長時間來計算(大約10-15秒)。

我很確定這裏有很多優化工作要做,但是我無法理解我可以做什麼來優化查詢。

PS:images.idPRIMARY KEY兩者fromImageIdtoImageIdimages.id

+0

您對fromImageId和toImageId列有索引嗎? – Hiro2k 2012-03-30 14:34:43

+0

我總是對SQL中'OR'子句的效率持懷疑態度。也許嘗試重寫這兩個查詢,一個forImage和一個toImage,然後相交結果? – KernelM 2012-03-30 14:38:10

回答

2

確保您的「Data」表具有AT LEAST兩個索引...一個是FROM圖像ID,另一個是To Image ID。然後,比邁克爾略有不同的是提出

select STRAIGHT_JOIN 
     i.ID, 
     i.FileName 
    from 
     Images i 
     LEFT JOIN Data d1 
      on i.ID = d1.FromImageID 
     LEFT JOIN Data d2 
      on i.ID = d2.ToImageID 
    where 
      d1.FromImageID is null 
     AND d2.ToImageID is null 

隨着兩個單獨的索引,此查詢與您的圖像文件開始,有兩個版本的數據表的...通過無論是從或分別加入得到內襯式圖像值在同一時間。所以現在,它應該只是通過吹捧,只有那些「數據」表都不匹配的條目。

+0

這真了不起。其他每個查詢花費大約10-15秒,這個最大值僅爲20ms。驚人! – 2012-03-31 11:26:58

+0

只有一個問題要正確理解; STRAIGHT_JOIN是做什麼的?是否有必要,如果是的話,爲什麼? – 2012-03-31 11:32:35

+0

@florianpeschka,請參閱我的其他鏈接澄清... http://stackoverflow.com/questions/9936532/mysql-query-performance-help-many-of-the-same-table-being-joined/9952793#9952793 – DRapp 2012-04-01 01:40:27

4
SELECT 
    images.id, 
    filename 
FROM 
    images 
LEFT JOIN `data` ON images.id = fromImageId 
OR images.id = toImageId 
WHERE 
    fromImageId IS NULL AND toImageId IS NULL 

FOREIGN KEY S和保證指標都在fromImageIdtoImageId

+0

'data'沒有'id'-字段 – 2012-03-30 21:09:39

+0

所以沒有。我改變了我的答案以反映這一點。我不知道'* ImageId'是否可以是'NULL',所以我必須確保它們都是'NULL'(因爲它們不能都是NULL並加入到'images'中。表(假設'images.id'不能是'NULL'))。 – MichaelRushton 2012-03-31 05:39:32

0

NOT IN可能是更好的選擇。沒有測試它,但請嘗試以下

SELECT image.id, image.filename 
FROM images image 
WHERE image.id NOT IN(
    SELECT IFNULL(fromImageId, toImageId) 
    FROM data results 
    WHERE fromImageId = image.id 
     OR toImageId = image.id 
) ORDER BY image.id 
0

的另一種方式,我能想到形成該查詢的是:

SELECT image.id, image.filename 
FROM images image 
WHERE image.id NOT IN(
    SELECT fromImageId, toImageId 
    FROM data results 
) ORDER BY image.id 

真的不知道有關「優化」會做,但也許你應該考慮製作一個存儲過程