我有一个运行缓慢的查询,我已经提出了一个更快的替代方案,但我希望能帮助理解为什么原始查询如此缓慢。
我的问题的一个简化版本使用两个表。第一个表的简化版本称为配置文件,如下所示
`profiles` (
`id` int(11),
`title` char(255),
`body` text,
`pin` int(11),
PRIMARY KEY (`id`),
UNIQUE KEY `pin` (`pin`)
)
我的第二个表calls的简化版本是
`calls` (
`id` int(11),
`pin` int(11),
`duration` int(11),
PRIMARY KEY (`id`),
KEY `ivr_id` (`pin`)
)
我的查询应该获得完整的配置文件,并添加配置文件接收的呼叫数量。我使用的查询是
SELECT profiles.*, COUNT(*) AS num_calls
FROM profiles
LEFT JOIN calls
ON profiles.pin = calls.pin
GROUP BY profiles.pin
对于大约100个配置文件和大约250,000个调用,这个查询大约需要10秒,这是很慢的。
如果我将查询修改为仅从配置文件中选择标题,而不是从所有列中选择标题,则查询速度会快得多。如果我修改查询以删除group by,速度也会快得多。如果我只是从profile表中选择所有内容,那么这也是一个快速查询。
我的实际配置文件表有更多的文本和字符字段。选择的文本字段越多,查询速度就越慢。为什么在连接或组中不涉及文本字段时,它们会导致查询如此缓慢?
我提出了一个略有不同的查询,它的速度要快得多,不到半秒。此查询为:
SELECT profiles.*, temp.readings
FROM profiles
LEFT JOIN (
SELECT pin ,COUNT(*) AS readings
FROM calls
GROUP BY pin
) AS temp
ON temp.pin=profiles.pin
虽然我认为我已经解决了速度问题,但我想了解是什么导致了第一个查询中的问题。
=更新=
我刚刚分析了这两个查询,整个速度的差异是在“发送数据”部分。慢查询约为10秒,快查询约为0.1秒
=更新2=
在与@scaisEdge讨论之后,我想我可以重新表达我的问题。考虑一个表T1,它有大约40列,其中8列是TEXT类型,大约100行;表T2,它有5列,类型为INT和VARCHAR,大约有250,000行。为什么会这样:
SELECT T1.* FROM T1 is fast
SELECT T1.* FROM T1 JOIN T2 GROUP BY T1.joinfield is slow
如果选择字段是INT或VARCHAR,则SELECT T1.selectfield FROM T1 JOIN T2 GROUP BY T1.joinfield
速度很快
发布于 2019-04-08 00:01:11
这应该会发生,因为
第一个查询使用250,000个调用连接100个配置文件,然后根据结果减少返回的行分组。和select配置文件.*表示对配置文件表数据的每个匹配行的完全访问
然后,第二个查询连接100配置文件,其中临时子查询返回的行数(可能远小于250,000)减少了对表配置文件数据的访问次数
而不是配置文件。*尝试仅访问固定列
SELECT profiles.pin, COUNT(*) AS num_calls
FROM profiles
LEFT JOIN calls ON profiles.pin = calls.pin
GROUP BY profiles.pin
作为建议,您应该注意,第一个查询只允许对早于版本5.7的mysql使用group by。因为在select子句中使用group by column而不提及column,并且不受聚合函数的影响,并且在GROUP by中不被提及,因此defualt不允许使用GROUP BY column并产生错误。
https://stackoverflow.com/questions/55560700
复制相似问题