MySql - 缓慢发送数据阶段

时间:2009-05-14 13:53:35

标签: mysql performance

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

mysql> SELECT source_id FROM directions WHERE (destination_id = 10);
+-----------+
| source_id |
+-----------+
|         2 |
|         8 |
...
|      2563 |
+-----------+
341 rows in set (2.13 sec)

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

如果它有帮助,我在这个表上有3个文本字段,但由于它们没有被选中,我预计它们不会导致这种缓慢。

此查询每天运行数千次,并且每次都不能花费2秒。

分析结果:

mysql> show profile for query 4;
+--------------------------------+----------+
| Status                         | Duration |
+--------------------------------+----------+
| (initialization)               | 0.000003 |
| checking query cache for query | 0.000051 |
| checking permissions           | 0.000007 |
| Opening tables                 | 0.000011 |
| System lock                    | 0.000005 |
| Table lock                     | 0.000023 |
| init                           | 0.00002  |
| optimizing                     | 0.00001  |
| statistics                     | 0.00006  |
| preparing                      | 0.000014 |
| executing                      | 0.000005 |
| Sending data                   | 2.127019 |
| end                            | 0.000015 |
| query end                      | 0.000004 |
| storing result in query cache  | 0.000039 |
| freeing items                  | 0.000011 |
| closing tables                 | 0.000007 |
| logging slow query             | 0.000047 |
+--------------------------------+----------+
18 rows in set (0.00 sec)

更新:我偶然发现了以下显示

的网址
Each time means the time elapsed between the previous event and the new event. So, the line:
| Sending data | 0.00016800 |
means that 0.00016800 seconds elapsed between "executing" and "Sending data". It is, it takes 0.00016800 seconds to execute the query.

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

有人可以验证吗?

8 个答案:

答案 0 :(得分:19)

解释计划通常是每当您查询速度较慢时启动的最佳位置。要获得一个,请运行

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

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

在这种情况下,在destination_id上添加索引可以大大加快查询速度,但需要花费一些成本来插入和删除速度(因为索引也需要更新)。

答案 1 :(得分:6)

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

  

发送数据

     

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

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

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

答案 2 :(得分:5)

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

经过深入挖掘后,我发现我的join正在比较两个被索引的字段,但是有不同的校对 - 一个是latin1_swedish_ci,另一个是uft8_general_ci。

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

答案 3 :(得分:1)

这张桌子上有索引吗?你说它返回大约300.但是需要多少搜索才能找到那些300?

答案 4 :(得分:1)

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

SELECT source_id FROM directions
    WHERE (destination_id = 10);

受益

INDEX(destination_id, source_id)

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

答案 5 :(得分:0)

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

  

CREATE INDEX index_destination_id ON direction(destination_id);

然后您的请求将顺利进行。

答案 6 :(得分:0)

我从MySQL 5.5.x迁移到5.7.x后经历过这种情况。我使用连接的查询在MySQL 5.5上很快,在MySQL 5.7上确实很慢。

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

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

答案 7 :(得分:0)

我有两个索引(date_indexid),在查询中我有WHERE date_index>NOW() - INTERVAL 24 HOURS,在查询中我有ORDER BY id, MySql首选id进行查询,这导致大表的查询时间较长。

表生长了5年后,我在旧系统中发现了它。