我对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
有人可以验证吗?
答案 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_index
和id
),在查询中我有WHERE date_index>NOW() - INTERVAL 24 HOURS
,在查询中我有ORDER BY id
,
MySql首选id
进行查询,这导致大表的查询时间较长。
表生长了5年后,我在旧系统中发现了它。