3

我有一个存储“主题”的数据库,每个主题都与一大堆图像相关联(=这些主题的屏幕截图)。现在我想显示最新的 10 个主题,对于每个主题,我只想从数据库中获取一张图片(ID 最低的一张)。

目前我的查询看起来像这样(我正在使用子查询):

SELECT DISTINCT 
  t.theme_id, t.theme_name, theme_date_last_modification, image_id, image_type

FROM 
  themes t, theme_images i

WHERE 
  i.theme_id = t.theme_id
  AND t.theme_status = 3
  AND t.theme_date_added < now( )
  AND i.image_id = (
    SELECT MIN( image_id )
    FROM theme_images ii
    WHERE ii.theme_id = t.theme_id 
  )

GROUP BY 
  t.theme_id

ORDER BY 
  t.theme_date_last_modification DESC

LIMIT 10

它可以工作,但是查询很慢。当我使用 EXPLAIN 时,我可以看到有一个“依赖子查询”。是否可以将此依赖子查询转换为某种可以由mysql更快处理的连接?

PS:我的实际查询要复杂得多,并且使用了更多的表。我已经尝试尽可能简化它,以便您可以专注于性能问题的实际原因。

编辑:这是解释的输出:

id  select_type         table   type    possible_keys              key       key_len   ref                 rows  Extra   
1   PRIMARY             t       index   PRIMARY,themes             themes    212       NULL                5846  Using where; Using index; Using temporary; Using filesort
1   PRIMARY             i       eq_ref  PRIMARY,theme_id,image_id  PRIMARY   4         func                1     Using where
2   DEPENDENT SUBQUERY  ii      ref     theme_id                   theme_id  4         themes.t.theme_id   6   
4

2 回答 2

4

先试试这个查询 -

SELECT
  t.*, ti1.*
FROM
  themes t
JOIN theme_images ti1
  ON ti1.theme_id = t.theme_id
JOIN (SELECT theme_id, MIN(image_id) image_id FROM theme_images GROUP BY theme_id) ti2
  ON ti1.theme_id = ti2.theme_id AND ti1.image_id = ti2.image_id
ORDER BY 
  t.theme_date_last_modification DESC
LIMIT 10

另一种解决方案 -

SELECT
  t.*, ti.*
FROM
  themes t
JOIN (SELECT * FROM theme_images ORDER BY image_id) ti
  ON ti.theme_id = t.theme_id
GROUP BY
  theme_id 
ORDER BY 
  t.theme_date_last_modification DESC
LIMIT
  10

然后添加您的 WHERE 过滤器。

于 2013-09-12T11:18:08.900 回答
1

一种方法是先LIMIT放在themes桌子上,JOIN然后images

SELECT
    t.theme_id, t.theme_name, t.theme_date_last_modification, 
    ti.image_id, ti.image_type
FROM
      ( SELECT theme_id, theme_name, theme_date_last_modification
        FROM themes t
        WHERE theme_status = 3
          AND theme_date_added < now( )
        ORDER BY 
          theme_date_last_modification DESC
        LIMIT 10 
      ) AS t
    JOIN                     -- LEFT JOIN if you want themes without an image 
        theme_images AS ti   -- to be shown
          ON ti.theme_id = t.theme_id
         AND ti.image_id =
             ( SELECT ii.image_id
               FROM theme_images AS ii
               WHERE ii.theme_id = t.theme_id
               ORDER BY ii.image_id
               LIMIT 1
             ) 

ORDER BY 
    t.theme_date_last_modification DESC ;

限制子查询上的索引themes (theme_status, theme_date_last_modification, theme_id, theme_date_added)应该是有效的。

我想你也有一个(唯一的)索引theme_images (theme_id, image_id)

于 2013-09-12T11:14:05.963 回答