2012-03-30 55 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 

真的不知道有关“优化”会做,但也许你应该考虑制作一个存储过程