选择查询花费的时间超过了原先的时间


9

我有一个具有近2300万条记录的MySQL数据库表。该表没有主键,因为没有唯一的键。它有2列,均已索引。下面是它的结构:

在此处输入图片说明

以下是一些数据:

在此处输入图片说明

现在,我运行了一个简单的查询:

SELECT `indexVal` FROM `key_word` WHERE `hashed_word`='001'

不幸的是,这花费了超过5秒钟才能检索数据并将其显示给我。我的未来表将有1500亿条记录,因此这一次非常高。

我运行Explain命令以查看发生了什么。结果如下。

在此处输入图片说明

然后,我使用以下命令运行配置文件。

SET profiling=1;
SELECT `indexVal` FROM `key_word` WHERE `hashed_word` = '001';
SHOW profile;

以下是分析的结果:

在此处输入图片说明

以下是有关我的表格的更多信息:

在此处输入图片说明

那么,为什么要花这么长时间?他们也被索引!将来,我必须运行很多LIKE命令,因此这会花费太多时间。出了什么问题?


“该表没有主键,因为没有唯一的。” 是的,没错...是时候重新检查您的设计了。所有表都应具有主键(或唯一键)。
ypercubeᵀᴹ

Answers:


10

您问“ 为什么要花太长时间?”。您还说:“ 不幸的是,这花费了5秒钟以上的时间来检索数据并将其显示给我 ”。另外,您报告了查询的概要分析输出。

如您所见,分析器为每个步骤报告的时间总和为0.000154秒。因此,从分析器的角度来看,查询是在这样的时间(0.000154)中完成的。

那么,为什么要在“ ...超过5秒内 ” 获得结果

您说过要过滤一个3字符字段的2千3百万条记录表。不幸的是,您没有告诉我们您的查询正在返回多少条记录...,但是由于提供了EXPLAIN SELECT,看来您的查询返回了336052条记录。

同样,您的所有活动似乎都通过某个GUI(PHPMyAdmin?)运行。

因此,在完成上述所有操作之后,我们可以将您的原始问题重新表述为:

“如果相关查询的MySQL执行时间为0.000154秒,为什么我会在5秒钟以上的GUI内得到336.052条记录?”

在我看来,答案很简单: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严格相关的魔术路径:-)


我期待着操作员的答复。
Jnanaranjan

5
  1. 检查mysql innodb_buffer_pool_size。它应该足够大-越多越好。但是要避免操作系统交换,要避免太多。

    show variables like 'innodb_buffer_pool_size'

    将显示缓冲区大小(以字节为单位)。

  2. 多次检查查询。第一次运行可能会太长,因为应该将数据从磁盘读取到内存中。第一次运行查询时,数据仍不在innodb缓冲区中,必须从磁盘读取。这比数据已经在缓存中要慢得多。因此,请运行查询几次,以确保从缓存中获取查询。

  3. 禁用查询缓存,因为每次后续运行都会从中完成,并且会使测试结果产生偏差。MySQL中有一种机制称为“查询缓存”,该机制旨在存储查询及其结果。因此,第二次请求MySQL运行查询时,它可以绕过执行并从查询缓存中检索结果。

  4. 考虑使用“覆盖索引”:

    ALTER TABLE key_word ADD KEY IX_hashed_word_indexVal (hashed_word, indexVal);

这将更加有效,因为这样MySQL便可以仅通过索引来满足查询请求。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.