我在mysql中有以下查询:
SELECT t.ID
FROM forum_categories c, forum_threads t
INNER JOIN forum_posts p ON p.ID = t.Last_post
WHERE t.ForumID=36 OR (c.Parent=36 AND t.ForumID=c.ID)
ORDER BY t.Last_post DESC LIMIT 1
表forum_threads
看起来像这样:
ID ---标题--- ForumID - Last_post(最后论坛帖子的ID)
表格forum_posts
是这样的:
ID ---内容 - 作者
最后表格forum_categories
是这样的:
ID - 姓名---父母(另一个forum_categoriey)
(均为简化)
表forum_posts
包含当前约200,000行和表forum_threads
~5,000行
有时这些查询大约需要1-2秒 我已经将“Last_post”编入索引,但它没有帮助 “复制到tmp表”持续时间占该查询整个执行时间的约99%
我还增加了tmp_table_size
和sort_buffer_size
,但它仍然没有区别。
有什么想法吗?
答案 0 :(得分:1)
当你有
的东西时,查询应该会好得多select t.id
from forum_threads t
inner join forum_posts p ON p.ID = t.Last_post
inner join forum_categories c on t.ForumID=c.ID
WHERE t.ForumID=36 OR c.Parent=36
ORDER BY t.Last_post
DESC LIMIT 1
现在,对于一小组数据,它看起来非常好,查询时间非常好。
接下来,如何针对大量数据进行改进,答案是INDEX。
发生了2次加入
还有一个where子句
因此,您需要正确索引表以避免全表扫描。
您可以运行以下命令以查看表中的当前索引
show indexes from forum_threads;
show indexes from forum_posts ;
show indexes from forum_categories ;
以上命令将显示与表关联的索引。现在考虑一下这个事实,即没有索引,所以我们需要将索引作为
alter table forum_threads add index Last_post_idx (`Last_post`);
alter table forum_posts add index ID_idx (`ID`);
alter table forum_categories add index ID_idx (`ID`);
最后
alter table forum_threads add index ForumID_idx (`ForumID`);
alter table forum_categories add index Parent_idx (`Parent`);
现在我们在表上有索引,查询应该更快。
注意:2个表之间的连接键应具有相同的数据类型和大小,以便索引起作用。例如
inner join forum_posts p ON p.ID = t.Last_post
ID和Last_post应该在表中具有相同的数据类型和大小。
现在我们仍然对它使用OR条件的查询存在问题,即使使用正确的索引,查询也会在某些情况下尝试扫描整个表。
WHERE t.ForumID=36 OR c.Parent=36
那么如何摆脱这种情况,有时UNION在这种情况下效果更好。这意味着您运行带有条件的一个查询
WHERE t.ForumID=36
后跟UNION相同的查询,其中where where条件为
WHERE c.Parent=36
但优化需要更深入地了解表以及将在这些表上执行的可能查询。
上面的解释只是一个想法,我们如何能够提高查询的性能,并且实时有很多可能性,这些可以在具有完整的表结构和将要应用于它们的可能查询的同时进行处理。