Optimize MySQL query to avoid “Using where; Using temporary; Using filesort”

前端 未结 2 1829
春和景丽
春和景丽 2021-02-02 04:09

I built a custom forum for my site using MySQL. The listing page is essentially a table with the following columns: Topic, Last Updated, and

2条回答
  •  悲&欢浪女
    2021-02-02 04:45

    SELECT  id, name, last_reply, replies
    FROM    (
            SELECT  topic_id, MAX(date) AS last_reply, COUNT(*) AS replies
            FROM    wp_pod_tbl_forum
            GROUP BY
                    topic_id
            ) r
    JOIN    wp_pod_tbl_forum t
    ON      t.topic_id = 0
            AND t.id = r.topic_id
    UNION ALL
    SELECT  id, name, date, 0
    FROM    wp_pod_tbl_forum t
    WHERE   NOT EXISTS
            (
            SELECT  NULL
            FROM    wp_pod_tbl_forum r
            WHERE   r.topic_id = t.id
            )
            AND t.topic_id = 0
    ORDER BY
           date DESC
    LIMIT 0, 20
    

    If your table is MyISAM or id is not a PRIMARY KEY, you need to create a composite ondex on (topic_id, id).

    If your table is InnoDB and id is a PRIMARY KEY, an index just on (topic_id) will do (id will be implicitly added to the index).

    Update

    This query will most probably be even more efficient, provided that you have indexes on (topic_id, id) and (date, id):

    See this article in my blog for performance details:

    • Selecting last forum posts

    This query completes in 30 ms on a 100,000 rows sample data:

    SELECT  id, name, last_reply,
            (
            SELECT  COUNT(*)
            FROM    wp_pod_tbl_forum fc
            WHERE   fc.topic_id = fl.topic_id
            ) AS replies
    FROM    (
            SELECT  topic_id, date AS last_reply
            FROM    wp_pod_tbl_forum fo
            WHERE   id = (
                    SELECT  id
                    FROM    wp_pod_tbl_forum fp
                    WHERE   fp.topic_id = fo.topic_id
                    ORDER BY
                            fp.date DESC, fp.id DESC
                    LIMIT 1
                    )
                    AND fo.topic_id <> 0
            ORDER BY
                    fo.date DESC, fo.id DESC
            LIMIT 20
            ) fl
    JOIN    wp_pod_tbl_forum ft
    ON      ft.id = fl.topic_id
    UNION ALL
    SELECT  id, name, date, 0
    FROM    wp_pod_tbl_forum t
    WHERE   NOT EXISTS
            (
            SELECT  NULL
            FROM    wp_pod_tbl_forum r
            WHERE   r.topic_id = t.id
            )
            AND t.topic_id = 0
    ORDER BY
           last_reply DESC, id DESC
    LIMIT  20
    

    Both indexes are required for this query to be efficient.

    If your table is InnoDB and id is a PRIMARY KEY, then you can omit id from the indexes above.

提交回复
热议问题