我有一个由两个快速查询组成的 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/