为啥 MySQL 查询在我第二次运行时更快?

Posted

技术标签:

【中文标题】为啥 MySQL 查询在我第二次运行时更快?【英文标题】:Why MySQL query is faster the second time I run it?为什么 MySQL 查询在我第二次运行时更快? 【发布时间】:2017-04-06 07:51:06 【问题描述】:

我刚刚观察到一个非常奇怪的问题,这实际上可能有助于我更好地理解我的数据库行为并更好地设计它。

首先,这是我们所说的 mysql 数据库。 User_ID 字段有索引。

这是我运行的代码:

query3 =("SELECT Content FROM Twit "
          "WHERE User_ID = %s "
          "limit 25 ")

for userid, c_word in user22_list:
    cursorSQL.execute(query3, (userid,))

由于某种原因,我不明白什么时候我为 200 个第一个用户运行它,然后停止它,每 10 个用户大约需要 1 秒,非常慢。

但是如果几分钟后我为第一个 1000 个用户运行它,它将在不到一秒的时间内达到 200 个,然后减速到 10 个用户/秒的速度,依此类推如果我在那之后运行它 5000(非常快到 1000,之后慢)。

问题:

能否将查询临时存储在某处(在我服务器的 RAM 中?)以解释其速度? 您有什么方法可以加快这个过程吗?

***** 编辑1: 根据要求:

SHOW CREATE TABLE Twit的输出

 Table    Create Table    
    Twit  CREATE TABLE `Twit` (
     `ID_num` bigint(45) NOT NULL,
     `Content` varchar(250) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
     `User_ID` bigint(24) NOT NULL,
     `Location` varchar(70) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
     `Date_create` datetime NOT NULL,
     `Retweet_count` int(7) NOT NULL,
     `isRetweet` tinyint(1) NOT NULL,
     `hasReetweet` tinyint(1) NOT NULL,
     `Original` bigint(45) DEFAULT NULL,
     `Url` varchar(150) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
     `Favorite_count` int(7) NOT NULL,
     PRIMARY KEY (`ID_num`),
     KEY `User_ID` (`User_ID`),
     KEY `Date_create` (`Date_create`),
     KEY `User_ID_2` (`User_ID`)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci

EXPLAIN SELECT Content From...的输出

id = 1 select_type = '简单' "table" = 'Twit' 分区 = null type = 'ref' possible_keys = 'User_ID,User_ID_2' "key" = 'User_ID' key_len = '8' ref = 'const' “行”= 298 过滤 = 100 Extra = '使用索引条件';

变量:

'innodb_buffer_pool_size', Value = '4294967296';

为了更清楚,我在 python 循环中调用 SELECT 请求。如果我已经为该用户运行了 SELECT 请求,则每次迭代都非常快,否则非常慢。是否擦除 RAM(服务器重启)都没有关系。

谢谢。

【问题讨论】:

Should I blame caching, yes!:) 该死,这就是我不想听到的!!!意味着没有优化可能吗?不过谢谢 其实这个看起来像一个内置的优化功能。大声笑。 查询并未准确存储,但数据库的执行计划已存储,第一次执行期间获取的部分(或全部)数据也已存储。这是设计使然 - 缓冲区缓存(在 RAM 中,由 db 进程使用)是用于提高大多数现代数据库整体性能的最重要元素之一。 缓存是原因 【参考方案1】:

有两个“缓存”可以解释时序“加速”。

InnoDB 使用其“缓冲池”来避免从磁盘重新加载内容。 如果“查询缓存”已打开,则第二次运行可能会“立即”返回,因为 QC 缓存了结果集。

“然后减速到 10 用户/秒的速度”——闻起来像数据尚未缓存。

不要在没有ORDER BY 的情况下使用LIMIT,除非您不在乎返回哪些行。

cursorSQL 是什么?不同的客户做事不同;了解您使用的语言可能很重要。

请提供SHOW CREATE TABLE TwitEXPLAIN SELECT ...,以便我们了解更多详情。

请解释“为第 1000 个用户运行它”是什么意思。那是1000个选择吗?一个选择 LIMIT 1000?还有什么?

你有多少内存? innodb_buffer_pool_size的值是多少?

【讨论】:

感谢您的回答。 - 我不清楚“缓存”是什么意思。它是仅缓存 RAM,还是也可以“硬缓存”。因为之前的观察结果适用于我之前是否运行过查询,或者如果我刚刚重新启动服务器(并清除了 RAM ......)。 - cursorSQL 来自我正在使用的 python-mysqlconnector。在 python 中调用 SQL 查询我更新了我的帖子以提供您问题的答案。再次感谢! 为了清楚起见,我在 python 循环中调用 SELECT 请求。如果我已经为该用户运行了 SELECT 请求,则每次迭代都非常快,否则非常慢。是否擦除了 RAM(服务器重新启动)并不重要。我也知道这不是最优的,它可以在单个查询而不是循环中调用。

以上是关于为啥 MySQL 查询在我第二次运行时更快?的主要内容,如果未能解决你的问题,请参考以下文章

当我第二次实例化预制件时,为啥会出现错误?

当我第二次设置它的 ItemsSource 时,为啥这个选择器会崩溃?

为啥当我第二次使用完全相同的参数调用 IMMUTABLE 函数时,计划时间会加倍?

IOS模拟器问题应用程序仅在第二次启动时运行..

RxAlamofire 请求在我第二次调用该函数时没有被触发

iOS UITableView reloadData 仅在我第二次调用我的 reload 函数时刷新表