Pea*_*Gen 10 mysql innodb performance select
我有一个包含近 2300 万条记录的 MySQL 数据库表。这个表没有主键,因为没有什么是唯一的。它有 2 列,均已编入索引。下面是它的结构:
下面是它的一些数据:
现在,我运行了一个简单的查询:
SELECT `indexVal` FROM `key_word` WHERE `hashed_word`='001'
Run Code Online (Sandbox Code Playgroud)
不幸的是,这花了超过 5 秒的时间来检索数据并将它们显示给我。我未来的表将有1500亿条记录,所以这个时间非常非常高。
我运行Explain
命令看看发生了什么。结果如下。
然后我使用以下命令运行配置文件。
SET profiling=1;
SELECT `indexVal` FROM `key_word` WHERE `hashed_word` = '001';
SHOW profile;
Run Code Online (Sandbox Code Playgroud)
下面是分析的结果:
以下是有关我的表的更多信息:
那么,为什么这需要这么长时间?他们也被索引了!将来,我必须运行很多LIKE
命令,所以这花费了太多时间。出了什么问题?
小智 10
你问“为什么这需要太长时间?”。您还说“不幸的是,检索数据并将其显示给我用了 5 秒多的时间”。此外,您还报告了查询的分析输出。
正如您自己看到的,分析器报告的每个步骤的时间总和计为 0.000154 秒。因此,从分析器的角度来看,查询是在这样的时间(0.000154)内完成的。
那么为什么您会在“ ...超过 5 秒? ”内获得结果。
你说你正在过滤一个带有 3 个字符字段的 2300 万条记录表。不幸的是,您没有告诉我们您的查询返回了多少条记录……但是由于提供了 EXPLAIN SELECT,您的查询似乎返回了 336052 条记录。
似乎您的所有活动都通过某个 GUI(PHPMyAdmin?)运行。
因此,综上所述,我们可以将您的原始问题重新表述为:
“如果相关查询的 MySQL 执行时间为 0.000154 秒,为什么在我的 GUI 中显示 336.052 条记录超过 5 秒?”
在我看来,答案很简单:5 秒是(确实很低)让 336.052 条记录沿路径传输的时间:MySQL 引擎 => MySQL 客户端库 => PHP MySQL 模块 => Apache => 网络 = > 您的 PC TCP/IP 堆栈 => 浏览器 => DOM 解析器/构建器等。=> 呈现的 HTML 页面。
就我之前的经验而言,传输结果所需的时间“通常”远高于检索此类数据所需的时间。当涉及像 PHP-MySQL 或 Perl-DBD-MySQL 这样的库时尤其如此:在MySQL 正确识别(...并提取)所有记录之后,它们确实需要大量时间来检索记录。
如何解决这个问题呢?
同样,很容易:您真的确定需要在单个完整数据集中包含 336.052 条记录的所有内容吗?
如果您的回答真的是“是的!我需要所有这些”,那么您的应用程序将自行处理分页和/或用户交互,并且……一旦收集了所有此类数据,它可能会花费大量时间无需任何进一步的 MySQL 交互即可与用户交互。在这种情况下,等待 5 秒(甚至更多)应该不是问题;
如果你的回答是“不,我想处理一个更‘人性化’的数据集大小”,那么你必须(至少)优化你的查询,以便它会给你一个更“人性化”的数据集(十或,最多数百条记录)。在这种情况下,我敢打赌你会在更短的时间内得到结果。
顺便说一句:这与您在另一篇文章中遇到的问题完全相同,在 ServerFault:88 秒让 132M 记录沿着......非mysql-严格相关的魔法路径:-)
小智 5
检查 mysql innodb_buffer_pool_size。它应该足够大——越多越好。但不要太多以避免操作系统交换。
show variables like 'innodb_buffer_pool_size'
Run Code Online (Sandbox Code Playgroud)
将显示以字节为单位的缓冲区大小。
检查查询不止一次。第一次运行可能太长,因为数据应该从磁盘读取到内存中。当您第一次运行查询时,数据仍然不在 innodb 缓冲区中,必须从磁盘读取。这比数据已经在缓存中要慢得多。因此,多次运行查询以确保它是从缓存中提供的。
禁用查询缓存,因为每次后续运行都将通过它完成,并且会使测试结果产生偏差。MySQL 中有一种机制,称为“查询缓存”,旨在存储查询及其结果。所以第二次请求 MySQL 运行查询时,它可以绕过执行并从查询缓存中检索结果。
考虑使用“覆盖索引”:
ALTER TABLE key_word ADD KEY IX_hashed_word_indexVal (hashed_word, indexVal);
Run Code Online (Sandbox Code Playgroud)这会更有效率,因为这样 MySQL 可以单独完成来自索引的查询请求。
归档时间: |
|
查看次数: |
46353 次 |
最近记录: |