优化我的长mysql查询

时间:2013-07-13 10:49:01

标签: mysql sql

SELECT
    n.id,
    n.title,
    n.text,
    n.date,
    IFNULL(ap.name, a.name) AS name,
    IFNULL(ap.path, a.path) AS path,
    IFNULL(ap.extension, a.extension) AS extension,
    IFNULL(ap.width, a.width) AS width,
    IFNULL(ap.height, a.height) AS height,
    IFNULL(ap.server, a.server) AS server,
    s.id AS source_id,
    s.name AS source_name
FROM news n
LEFT JOIN news_attachments na ON n.id = na.news_id AND na.cover = 1
LEFT JOIN attachments a ON na.attachments_id = a.id
LEFT JOIN attachments ap ON a.id = ap.parent AND ap.width = 136
JOIN sources s ON n.sources_id = s.id
WHERE n.moderate = 1 AND n.delete = 0
GROUP BY n.id
ORDER BY n.date DESC
LIMIT 25

我有这个SQL查询。我有一个问题是好还是不好?也许我可以改进它?

在这部分

LEFT JOIN attachments a ON na.attachments_id = a.id
LEFT JOIN attachments ap ON a.id = ap.parent AND ap.width = 136

我加载图像预览,然后选择:

    IFNULL(ap.name, a.name) AS name,
    IFNULL(ap.path, a.path) AS path,
    IFNULL(ap.extension, a.extension) AS extension,
    IFNULL(ap.width, a.width) AS width,
    IFNULL(ap.height, a.height) AS height,
    IFNULL(ap.server, a.server) AS server

这意味着如果它有图像预览,则使用它,否则使用原始图像

说明:

+----+-------------+-------+--------+-------------------------------------------+----------------------+---------+--------------------------+------+---------------------------------+
| id | select_type | table | type   | possible_keys                             | key                  | key_len | ref                      | rows | Extra                           |
+----+-------------+-------+--------+-------------------------------------------+----------------------+---------+--------------------------+------+---------------------------------+
|  1 | SIMPLE      | s     | ALL    | PRIMARY,id                                | NULL                 | NULL    | NULL                     |    4 | Using temporary; Using filesort |
|  1 | SIMPLE      | n     | ref    | fk_news_sources1_idx                      | fk_news_sources1_idx | 4       | base.s.id              |   93 | Using where                     |
|  1 | SIMPLE      | na    | ref    | PRIMARY,fk_news_has_attachments_news1_idx | PRIMARY              | 4       | base.n.id              |    1 |                                 |
|  1 | SIMPLE      | a     | eq_ref | PRIMARY,id                                | PRIMARY              | 4       | base.na.attachments_id |    1 |                                 |
|  1 | SIMPLE      | ap    | ALL    | NULL                                      | NULL                 | NULL    | NULL                     | 3720 |                                 |
+----+-------------+-------+--------+-------------------------------------------+----------------------+---------+--------------------------+------+---------------------------------+

2 个答案:

答案 0 :(得分:1)

假设所有news条记录都有sources,请尝试在moderatedeletedate(按此顺序)添加新闻索引,然后尝试以下查询:

SELECT
    n.id,
    n.title,
    n.text,
    n.date,
    IFNULL(ap.name, a.name) AS name,
    IFNULL(ap.path, a.path) AS path,
    IFNULL(ap.extension, a.extension) AS extension,
    IFNULL(ap.width, a.width) AS width,
    IFNULL(ap.height, a.height) AS height,
    IFNULL(ap.server, a.server) AS server,
    s.id AS source_id,
    s.name AS source_name
FROM (select *
      from news
      WHERE moderate = 1 AND delete = 0
      ORDER BY date DESC
      LIMIT 25) n
LEFT JOIN news_attachments na ON n.id = na.news_id AND na.cover = 1
LEFT JOIN attachments a ON na.attachments_id = a.id
LEFT JOIN attachments ap ON a.id = ap.parent AND ap.width = 136
JOIN sources s ON n.sources_id = s.id
GROUP BY n.id

答案 1 :(得分:1)

确保附件表在父级上有一个键(或者更好的是一个覆盖父级和宽度的键)。怀疑这是主要问题。

我怀疑新闻表中的中等和删除列不会缩小范围,以使其上的索引有用。

我还假设有更多的源记录而不是新闻记录,因此MySQL选择了获取资源并加入新闻,而不是相反。