PHP 板慢 mysql
Slow mysql of a PHP Board
我有多个 table 个 php 板。
我需要一个有效的查询,select 所有类别、所有主题、最后 post 个主题,以及 posted 用户。对于我的查询,运行 需要 5-8 秒。
我使用 last_post_id 字段对主题 table 进行了优化,但我需要一个更好的解决方案。
结构
forum_categories ~ 15 lines
id|name|...
forum_topics ~ 150 lines
id|name|category_id|...
forum_posts ~ 1.000.000 lines
id|body|topic_id|user_id|...
users ~ 30.000 lines
id|username|...
category 1
- topic 1
- last post1 | user1
- topic 2
- last post2 | user2
...
category 2
- topic 3
- last post3 | user3
...
...
上次查询(这是我朋友的帮助,但也太慢了。)
SELECT c.NAME AS category,
t.NAME AS topic,
p.body AS post,
p.username AS username
FROM forum_categories AS c
JOIN forum_topics AS t
ON t.category_id = c.id
JOIN (SELECT *
FROM (SELECT p.body,
p.topic_id,
u.username
FROM forum_posts AS p
JOIN users AS u
ON u.id = p.user_id
ORDER BY p.id DESC) AS t
GROUP BY topic_id) AS p
ON t.id = p.topic_id
解释查询
查询统计
Headers分别是:排序、状态、时间|状态,所有时间, pct。时间,电话,时间
我认为 "last post of topics" 是您查询的关键点。这就是为什么您在大多数内部查询中使用 ORDER BY
但这会产生两个子查询。
更新版本
CREATE TEMPORARY TABLE last_post_per_topic_t ENGINE = MEMORY
SELECT topic_id, MAX(id) AS id -----+
FROM forum_posts --> find last post id per topic
GROUP BY topic_id; -----------------+
ALTER TABLE last_post_per_topic_t ADD INDEX (id, topic_id);
SELECT *
FROM forum_categories AS c INNER JOIN forum_topics t ON c.id = t.category_id
INNER JOIN forum_posts p ON p.topic_id = t.id
INNER JOIN last_post_per_topic_t ON last_post_per_topic_t.topic_id = t.id
AND last_post_per_topic_t.id = p.id;
INNER JOIN users u ON p.user_id = u.id;
第一个版本
SELECT *
FROM forum_categories AS c INNER JOIN forum_topics t ON c.id = t.category_id
INNER JOIN forum_posts p ON p.topic_id = t.id
INNER JOIN (
SELECT topic_id, MAX(id) AS id -----+
FROM forum_posts --- find last post_id per topic
GROUP BY topic_id ---------------+
) last_post_per_topic_t ON last_post_per_topic_t.topic_id = t.id
AND last_post_per_topic_t.id = p.id;
我有多个 table 个 php 板。
我需要一个有效的查询,select 所有类别、所有主题、最后 post 个主题,以及 posted 用户。对于我的查询,运行 需要 5-8 秒。 我使用 last_post_id 字段对主题 table 进行了优化,但我需要一个更好的解决方案。
结构
forum_categories ~ 15 lines
id|name|...
forum_topics ~ 150 lines
id|name|category_id|...
forum_posts ~ 1.000.000 lines
id|body|topic_id|user_id|...
users ~ 30.000 lines
id|username|...
category 1
- topic 1
- last post1 | user1
- topic 2
- last post2 | user2
...
category 2
- topic 3
- last post3 | user3
...
...
上次查询(这是我朋友的帮助,但也太慢了。)
SELECT c.NAME AS category,
t.NAME AS topic,
p.body AS post,
p.username AS username
FROM forum_categories AS c
JOIN forum_topics AS t
ON t.category_id = c.id
JOIN (SELECT *
FROM (SELECT p.body,
p.topic_id,
u.username
FROM forum_posts AS p
JOIN users AS u
ON u.id = p.user_id
ORDER BY p.id DESC) AS t
GROUP BY topic_id) AS p
ON t.id = p.topic_id
解释查询
查询统计
Headers分别是:排序、状态、时间|状态,所有时间, pct。时间,电话,时间
我认为 "last post of topics" 是您查询的关键点。这就是为什么您在大多数内部查询中使用 ORDER BY
但这会产生两个子查询。
更新版本
CREATE TEMPORARY TABLE last_post_per_topic_t ENGINE = MEMORY
SELECT topic_id, MAX(id) AS id -----+
FROM forum_posts --> find last post id per topic
GROUP BY topic_id; -----------------+
ALTER TABLE last_post_per_topic_t ADD INDEX (id, topic_id);
SELECT *
FROM forum_categories AS c INNER JOIN forum_topics t ON c.id = t.category_id
INNER JOIN forum_posts p ON p.topic_id = t.id
INNER JOIN last_post_per_topic_t ON last_post_per_topic_t.topic_id = t.id
AND last_post_per_topic_t.id = p.id;
INNER JOIN users u ON p.user_id = u.id;
第一个版本
SELECT *
FROM forum_categories AS c INNER JOIN forum_topics t ON c.id = t.category_id
INNER JOIN forum_posts p ON p.topic_id = t.id
INNER JOIN (
SELECT topic_id, MAX(id) AS id -----+
FROM forum_posts --- find last post_id per topic
GROUP BY topic_id ---------------+
) last_post_per_topic_t ON last_post_per_topic_t.topic_id = t.id
AND last_post_per_topic_t.id = p.id;