0
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

I have this SQL query. And I have a question is it good or not? Maybe I can improve it?

In this part

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

I load a preview of image, then in select:

    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

This mean if it have a preview of image, then use it otherwise use original image

EXPLAIN:

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

2 回答 2

1

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

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
于 2013-07-13T11:28:41.017 回答
1

Make sure that the attachments table has a key on parent (or possibly better a key covering bother parent and width). Suspect this is the major issue.

I suspect that the moderate and delete columns on the news table won't narrow things down enough to make an index on them useful.

I also presume that there are many more source records than there are news records, hence MySQL has chosen to take sources and join news to that rather than the other way round.

于 2013-07-13T13:24:53.583 回答