我使用MySQL为我的网站构建了一个自定义论坛。列表页面基本上是一个包含以下列的表格:主题,上次更新和#回复。
数据库表格包含以下列:
id
name
body
date
topic_id
email
主题的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;
此表中总共有2,100项,查询通常需要6秒钟。我在“topic_id”列中添加了一个INDEX,但这没有多大帮助。有没有办法加速这个查询而不进行重大重组?
编辑:尚未完成工作。我似乎无法让下面的例子正常工作。
答案 0 :(得分:7)
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
如果您的表格为MyISAM
或id
不是PRIMARY KEY
,则需要在(topic_id, id)
上创建复合索引。
如果您的表格为InnoDB
且id
为PRIMARY KEY
,则(topic_id)
上的索引将会id
隐式添加到索引中)。
<强>更新强>
如果您在(topic_id, id)
和(date, id)
上有索引,则此查询的效率可能会更高:
请参阅我的博客中有关效果详情的文章:
此查询在30 ms
行样本数据的100,000
中完成:
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
此查询需要两个索引才能有效。
如果您的表格为InnoDB
且 id
为PRIMARY KEY
,则您可以忽略上述indexes
中的ID。
答案 1 :(得分:1)
您可能希望将其分解为一组子查询(作为内部查询)。我需要架构真正发挥,但如果你
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;
可能有助于加快速度,甚至可能不是最好的答案(错误可能存在)。
有很多方法可以做到这一点,但是当SQL调优是在执行操作之前尽可能地减少每个集合时最重要的事情。