mysql - 缓慢的 UNION 查询 - MySQL

标签 mysql optimization

我有一个由两个快速查询组成的 UNION 查询。

( SELECT DISTINCT ( SELECT strStatus FROM User_User_XR uuxr WHERE 
( uuxr.intUserId1 = '1' AND uuxr.intUserId2 = u.intUserId ) ) AS strFriendStatus1,
 uuxro.strStatus AS strFriendStatus2, uuxr.intUserId2 AS intUserId, u.strUserName ,
 u.strGender, IF( u.dtmBirth != '0000-00-00', FLOOR(DATEDIFF(CURDATE(), 
u.dtmBirth) / 365.25) , '?') AS intAge, u.strCountry AS strCountryCode,
 c.strCountry AS strCountry, u.strAvatar, u.fltPoints, 
IF( o.intUserId IS NULL, 'offline', 'online' ) AS strOnline, 
IF ( u.strAvatar != '', CONCAT( 'avatars/60/', u.strAvatar ), 
CONCAT( 'images/avatar_', u.strGender, '_small.png' ) ) as strAvatar,     
IF ( u.strAvatar != '', CONCAT( 'avatars/150/', u.strAvatar ),     
CONCAT( 'images/avatar_', u.strGender, '.png' )) as strLargeAvatar,
 u.dtmLastLogin, u.dtmRegistered FROM User_User_XR uuxr, 
User u LEFT JOIN User_User_XR uuxro ON uuxro.intUserId2 = '1' 
AND uuxro.intUserId1 = u.intUserId
 LEFT JOIN Online o ON o.intUserId = u.intUserId 
LEFT JOIN Country c ON c.strCountryCode = u.strCountry 
WHERE u.intUserId = uuxr.intUserId2 AND ( uuxr.strStatus = 'confirmed' ) 
AND uuxr.intUserId1='1' ) 

UNION 

( SELECT DISTINCT ( SELECT strStatus FROM User_User_XR uuxr 
WHERE ( uuxr.intUserId1 = '1' AND uuxr.intUserId2 = u.intUserId ) ) AS strFriendStatus1,
 uuxro.strStatus AS strFriendStatus2, uuxr.intUserId1 AS intUserId, u.strUserName , 
u.strGender, IF( u.dtmBirth != '0000-00-00', FLOOR(DATEDIFF(CURDATE(),
 u.dtmBirth) / 365.25) , '?') AS intAge,
 u.strCountry AS strCountryCode, c.strCountry AS strCountry, u.strAvatar, u.fltPoints, 
IF( o.intUserId IS NULL, 'offline', 'online' ) AS strOnline, 
IF ( u.strAvatar != '', CONCAT( 'avatars/60/', u.strAvatar ), 
CONCAT( 'images/avatar_', u.strGender, '_small.png' ) ) as strAvatar,
 IF ( u.strAvatar != '', CONCAT( 'avatars/150/', u.strAvatar ), 
CONCAT( 'images/avatar_', u.strGender, '.png' )) as strLargeAvatar, 
u.dtmLastLogin, u.dtmRegistered FROM User_User_XR uuxr, User u 
LEFT JOIN User_User_XR uuxro ON uuxro.intUserId2 = '1' 
AND uuxro.intUserId1 = u.intUserId 
LEFT JOIN Online o ON o.intUserId = u.intUserId 
LEFT JOIN Country c ON c.strCountryCode = u.strCountry 
WHERE u.intUserId = uuxr.intUserId1 AND ( uuxr.strStatus = 'confirmed' )
 AND uuxr.intUserId2='1' )

第一个查询在 0.0047 秒内运行 第二次运行在 0.0043 秒内

但是,在 Union 中,他们运行 0.27 秒……这是为什么?在 UNION 之后没有 Order By,为什么 MySQL 不简单地采用两个快速查询并将它们连接起来?

最佳答案

UNION 会导致创建一个临时表,即使对于 UNION ALL 也是如此。

当执行 UNION DISTINCT(与 UNION 相同)时,将创建带有索引的临时表,以便删除重复项。使用 UNION ALL,创建了临时表,但没有索引。

这解释了使用 UNION ALL 时性能略有提高,也解释了使用 UNION 而不是两个单独的查询时性能下降的原因。

有关这方面的更多信息,请参阅 MySQL performance blog 上的以下条目:

UNION vs UNION ALL Performance

How MySQL Uses Internal Temporary Tables MySQL 文档中的页面指出在以下情况下会创建一个临时表:

... any column larger than 512 bytes in the SELECT list, if UNION or UNION ALL is used

关于mysql - 缓慢的 UNION 查询 - MySQL,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3524654/

相关文章:

mysql - 如何从逗号分隔列mysql中的逗号分隔字符串进行搜索

mysql - 如何在出现特定字符串时删除和更新表字段数据?

mysql - 临时表(Memory Engine)和大物理表(1.7GB myisam)的join优化

c# - 使用静态 Regex.IsMatch 与创建 Regex 实例

c# - 使用循环时获取属性优化

MySQL LEFT JOIN 只有最后一行非常慢

php - 捕获实体状态交易

mysql - 智能聚结

r - 优化全局最小值

java - 平衡括号问题的优化解