5

表中有 400,000 条记录

表格形成

id(int,pk)
title varchar(255)
body(text)

查询 1

select **title** from qa_question order by id desc limit 300000, 15;

运行时间15

查询 2

select **body** from qa_question order by id desc limit 300000, 15;

运行时间1.8

我想知道为什么

4

3 回答 3

2

很简单,先执行ORDER BY然后只有LIMIT起作用。如果您在如此多的记录上按偶数id排序 ,则意味着大量数据正在移动(varchar 和 text)。如果您不在那里订购,那么您的查询会很快,因为数据不会像那样移动。数据越多,对磁盘的 I/O 请求就会越多。

在下面的评论中回答问题。

差异可能是由于 OP 可能正在使用 MyISAM 存储引擎,而 TEXT 没有为此存储在行内。VARCHAR 是。见这里。该文件系统存储可能是行内存储而不是行内存储的排序时间差异。另请阅读这个很好的解释

也可以看看这个帖子

于 2013-01-21T08:25:37.063 回答
1

让我们仔细看看您的查询有ORDER BY id DESC LIMIT 300000, 15.

MySQL 服务器必须做什么才能执行它?首先,它必须根据主索引id以降序获取每条记录。请注意,这必须发生 300k 次。一旦达到 300,000 个计数,服务器才可以开始输出结果行,并且只有 15 个。如果您使用的不是 300k 初始偏移量,而是更小的值,则此查询会运行得更快。

为什么 query1 与 query2 相差 10 倍?这是因为TEXTMySQL中的列链接到父表(未存储在其中)并且检索它们需要额外的查找,但VARCHAR存储在表中。在您的情况下,TEXT列获胜,因为您实际上不需要拉body列,直到您达到第 300,000 行(服务器仅拉body TEXT取对另一个不可见表中的列的相对较小的引用)。但是在title列的情况下,服务器别无选择,只能拉满title列,即使它在 100 字节的范围内,这就是它慢 10 倍的原因。

很难说清楚。这可能是因为第一个查询运行缓慢,但将所有表数据缓存在 RAM 中,所以第二个可以运行得更快。在得出任何结论之前,您应该至少重复所有查询 3 次。

我对你的建议是找到一种方法来LIMIT 300000, 15替换

WHERE id BETWEEN 300000 AND 300014

或等效的,如果可以的话。在这种情况下,服务器将能够利用主索引,而且速度会快如闪电。

于 2013-01-21T08:38:30.370 回答
0

这是因为varchar在执行查询之前分配内存,即它使用静态内存分配。因此,即使标题短于 255 个字符,它也会保留 255 个字符的内存。

在这种情况下,您可以使用VARCHAR CHARACTER SET utf8,它是 nvarchar 的别名,它是动态的并根据标题的长度使用内存量。

由于您有 400,000 条记录,这相当多,这会在使用 varchar 时导致更长的运行时间。所以,我的建议是使用VARCHAR CHARACTER SET utf8并避免使用 varchar。

于 2013-01-21T08:36:45.173 回答