简体   繁体   English

优化MySQL查询以避免“使用位置;使用临时;使用filesort“

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

I built a custom forum for my site using MySQL. 我使用MySQL为我的网站建立了一个自定义论坛。 The listing page is essentially a table with the following columns: Topic , Last Updated , and # Replies . 列表页面本质上是一个包含以下列的表: 主题上次更新#Reslies

The DB table has the following columns: DB表包含以下列:

id
name
body
date
topic_id
email

A topic has the topic_id of "0", and replies have the topic_id of their parent topic. 主题的topic_id为“0”,并且回复具有其父主题的topic_id。

SELECT SQL_CALC_FOUND_ROWS
    t.id, t.name, MAX(COALESCE(r.date, t.date)) AS date, COUNT(r.id) AS replies
FROM
    wp_pod_tbl_forum t
LEFT OUTER JOIN
    wp_pod_tbl_forum r ON (r.topic_id = t.id)
WHERE
    t.topic_id = 0
GROUP BY
    t.id
ORDER BY
    date DESC LIMIT 0,20;

There are about 2,100 total items in this table, and queries usually take a whopping 6 seconds. 此表中共有约2,100项,查询通常需要6秒钟。 I added an INDEX to the "topic_id" column, but that didn't help much. 我在“topic_id”列中添加了一个INDEX,但这没有多大帮助。 Are there any ways of speeding up this query w/out doing significant restructuring? 有没有办法加速这个查询而不进行重大重组?

EDIT : not quite working yet. 编辑 :还没有完成工作。 I can't seem to get the examples below to work properly. 我似乎无法让下面的例子正常工作。

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) . 如果您的表是MyISAM或者id不是PRIMARY KEY ,则需要在(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). 如果你的表是InnoDB并且id是一个PRIMARY KEY ,那么只有on (topic_id)的索引会做( id将被隐式添加到索引中)。

Update 更新

This query will most probably be even more efficient, provided that you have indexes on (topic_id, id) and (date, id) : 只要你有(topic_id, id)(date, id)索引,这个查询很可能会更有效:

See this article in my blog for performance details: 有关性能详情,请参阅我的博客中的这篇文章

This query completes in 30 ms on a 100,000 rows sample data: 对于100,000行样本数据,此查询在30 ms完成:

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. 如果您的表是InnoDB idPRIMARY KEY ,那么您可以从上面的indexes省略id。

You may want to break it up into a set of subqueries (as inner queries). 您可能希望将其分解为一组子查询(作为内部查询)。 I'd need the schema to really play, but if you 我需要架构真正发挥,但如果你

SELECT t.id, t.name, MAX(COALESCE(r.date, t.date)) AS date, COUNT(r.id) AS replies  
FROM (
   SELECT (id, name, date)
   FROM wp_pod_tbl_forum
   WHERE topic_id = 0  
) as t 
LEFT OUTER JOIN
   wp_pod_tbl_forum r
WHERE
   r.topic_id = t.id
GROUP BY
    t.id
ORDER BY
    date DESC LIMIT 0,20;

that may help speed it up a little, it may not even be the best answer (errors may exist). 这可能有助于加快一点,甚至可能不是最佳答案(可能存在错误)。

There are tons of ways to do it, but the most important thing to do when SQL tuning is to reduce each set as much as possible before performing an operation. 有很多方法可以做到这一点,但是当SQL调优是在执行操作之前尽可能地减少每个集合时最重要的事情。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何在Extra中优化MYSQL: 使用临时; 使用文件排序 - How to Optimize MYSQL in Extra :-Using where; Using temporary; Using filesort 优化表以避免使用临时和使用filesort - Optimize table to avoid using temporary and using filesort 奇怪的MySQL查询计划:为什么这个查询使用临时&filesort? 如何优化呢? - Weird MySQL query plan: why is this query using temporary & filesort? How to optimize it? 优化“ GROUP BY”查询,消除“在哪里使用”; 使用临时; 使用文件排序” - Optimization of 'GROUP BY'-Query, eliminate 'Using where; Using temporary; Using filesort' 如何避免在 &quot;!=&quot; mysql 中使用 Filesort - How to avoid Using Filesort in "!=" mysql MySQL查询优化,大表,使用临时文件排序 - MySQL query optimisation, big table, using temporary filesort MYSQL优化用于临时; 使用filesort !!! - &gt;帮助 - MYSQL optimization for Using temporary; Using filesort!!! -> HELP 使用临时索引和文件排序 - Index using temporary and filesort MySQL db 正在使用“使用 where; 使用临时的; 按日期排序时使用文件排序 - MySQL db is using “Using where; Using temporary; Using filesort” when sorting by date 为什么MySql不使用我的索引以及如何避免使用“临时”; 使用文件排序”? - Why MySql doesn't use my index and how to avoid the “Using temporary; Using filesort”?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM