【问题标题】:MySql - slow sending data phaseMySql - 缓慢发送数据阶段
【发布时间】:2010-10-26 04:39:48
【问题描述】:

我对 MySQL 5.0.45 的一个查询在“发送数据”阶段运行缓慢。该查询是一个简单的选择,返回大约 300 个整数 ID 字段作为结果集。

mysql> SELECT source_id FROM Directions WHERE (destination_id = 10); +-----------+ | source_id | +-----------+ | 2 | | 8 | ... |第2563章 +-----------+ 341 行(2.13 秒)

我很清楚为什么“发送数据”阶段如此缓慢,以及可以采取哪些措施来加快速度。请注意,我是在服务器本身的 MySQL 提示符上执行此查询,因此并不真正期望它会在“发送数据”上花费这么多时间。有什么线索吗?

如果有帮助,我在这张表上有 3 个文本字段,但由于它们没有被选中,我希望它们不是造成这种缓慢的原因。

这个查询每天运行数千次,而且每次都花 2 秒时间。

分析结果:

mysql> 显示查询 4 ​​的配置文件; +--------------------------------+----------+ |状态 |持续时间 | +--------------------------------+----------+ | (初始化) | 0.000003 | |检查查询缓存中的查询 | 0.000051 | |检查权限 | 0.000007 | |开桌 | 0.000011 | |系统锁 | 0.000005 | |表锁 | 0.000023 | |初始化 | 0.00002 | |优化 | 0.00001 | |统计 | 0.00006 | |准备| 0.000014 | |执行 | 0.000005 | |发送数据 | 2.127019 | |结束 | 0.000015 | |查询结束 | 0.000004 | |将结果存储在查询缓存中 | 0.000039 | |释放物品 | 0.000011 | |关闭表| 0.000007 | |记录慢查询 | 0.000047 | +--------------------------------+----------+ 18 行一组(0.00 秒)

更新:我偶然发现了以下网址

每个时间是指前一个事件和新事件之间经过的时间。所以,这行:
|发送数据 | 0.00016800 |
表示“执行”和“发送数据”之间经过了 0.00016800 秒。也就是说,执行查询需要 0.00016800 秒。

http://forums.mysql.com/read.php?24,241461,242012#msg-242012

有人可以验证吗?

【问题讨论】:

  • 链接页面上的说法不正确。如果您在查询运行时执行SHOW PROCESSLIST,它将显示查询确实处于Sending data 状态。 (不是上一个)。 - 请不要说进程列表正在显示执行中的下一步步骤。 :)
  • @vbence:你有没有见过一个需要我们几个人才能运行的查询?上述理论是有道理的。
  • @user9111337 哦,是的。带有 WHERE 原因的聚合语句(GROUP BY)通常会导致无法通过使用索引来解决的选择(EXPLAIN ... 会说“USING WHERE”) - 如果表足够大,这可能需要几分钟。 - 这是如何报告的?您可以尝试SHOW PROCESSLIST 亲自查看。
  • 戳!不敢相信这没有好的答案
  • 我认为这个类似的问题应该会有所帮助。 stackoverflow.com/questions/10347193/…

标签: mysql performance


【解决方案1】:

只要查询速度较慢,解释计划通常是最好的起点。要获得一个,请运行

DESCRIBE SELECT source_id FROM directions WHERE (destination_id = 10);

这将显示一个表格,其中列出了执行查询所需的步骤。如果您在 'rows' 列中看到较大的值,而在 'key' 列中看到 NULL,则表明您的查询必须扫描大量行以确定要返回的行。

在这种情况下,在destination_id 上添加索引应该会显着加快您的查询速度,但会以插入和删除速度为代价(因为索引也需要更新)。

【讨论】:

【解决方案2】:

我遇到了同样的问题: 发送数据非常慢,但我有正确的索引等。

经过大量挖掘,我发现我的 join 正在比较两个已编入索引但排序规则不同的字段 - 一个是 latin1_swedish_ci,另一个是 uft8_general_ci。

我将它们都发送到 utf8 后,查询速度明显加快(从 2.7 秒到 0.002 秒)

【讨论】:

  • 万岁这个答案为我们指明了正确的方向!!!我简直不敢相信,但它在我们的测试环境中使用 latin1_swedish_ci 的默认排序规则创建了一个在索引中使用的字段的动态表 - 几乎花了一整天的时间试图弄清楚为什么我们会完全停滞不前查询的“发送数据”步骤需要几毫秒才能运行并且只有几百个结果!
【解决方案3】:

您可能会查看 mysql 服务器的硬件部分。 正如Mysql doc 所说:

发送数据

线程正在读取和处理 SELECT 语句的行,并将数据发送到客户端。由于在此状态期间发生的操作往往会执行大量磁盘访问(读取),因此它通常是给定查询生命周期内运行时间最长的状态。

因此,如果您的服务器由于巨大的 db/table 文件或禁用 tableperfile InnoDB 选项/碎片/不正确配置的 RAID/磁盘崩溃过程启动(等待很快磁盘死亡)/磁盘的任何其他原因而导致磁盘 I/O 缓慢I/O 缓慢 - 可能是显着增加“发送数据”步骤的原因,因为在此阶段服务器从磁盘收集所有请求的数据并将其发送到客户端。

当然,您应该首先尝试优化选择以使用索引,并确保这不是编程问题,因为这在大多数情况下会影响此阶段时间。

【讨论】:

    【解决方案4】:

    我在从 MySQL 5.5.x 迁移到 5.7.x 后遇到了这种情况。我使用连接的查询在 MySQL 5.5 上很快,而在 MySQL 5.7 上非常慢。

    问题在于 MySQL 5.7 选择了另一组索引,而不是 MySQL 5.5。

    添加 USE INDEX 解决了这个问题。

    【讨论】:

      【解决方案5】:

      我有两个索引(date_indexid),

      我在查询中有WHERE date_index>NOW() - INTERVAL 24 HOURSORDER BY id, MySql 首选id 作为索引,它没有使用导致大表查询时间过长的date_index。

      5 年后,我在一个遗留系统中发现了它。

      【讨论】:

        【解决方案6】:

        在我看来,分析是无用的。它具有误导性类别,例如“发送数据”,这无济于事。

        SELECT source_id FROM directions
            WHERE (destination_id = 10);
        

        将受益于

        INDEX(destination_id, source_id)
        

        (按此顺序)。同时,删除INDEX(destination_id),因为该索引处理此类需求。这个索引是一个“覆盖索引”。

        【讨论】:

          【解决方案7】:

          您的查询花费 2.127019 来执行查询。这可能是因为您有大量数据,并且您缺少 destination_id 列上的索引。试试看:

          CREATE INDEX index_destination_id ON 方向(destination_id);

          那么你的请求就会顺利进行。

          【讨论】:

          • 这个陈述是假的,看我对这个问题的评论。
          • 但对我来说,在不同的情况下,实际上添加索引解决了我的慢查询 - 有时明显会被遗漏。
          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2015-07-28
          • 2019-01-08
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2012-10-12
          相关资源
          最近更新 更多