慢UNION查询 - MySQL

Arm*_*min 9 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' )
Run Code Online (Sandbox Code Playgroud)

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

然而,在联盟中,它们运行0.27秒......为什么会这样?在UNION之后没有Order By,为什么MySQL不会简单地采用两个快速查询并连接它们?

Mik*_*ike 12

A UNION会导致创建临时表,即使对于UNION ALL.

执行a UNION DISTINCT(与其相同UNION)时,将使用索引创建临时表,以便可以删除重复项.使用UNION ALL,创建临时表,但没有索引.

这解释了使用时的轻微性能提升UNION ALL,并且还说明了使用UNION而不是两个单独的查询时的性能下降.

有关此内容的更多信息,请参阅MySQL性能博客上的以下条目:

UNION vs UNION ALL表演

如何使用MySQL的内部临时表从MySQL文档页指出,一个临时表创建时:

...如果使用UNION或UNION ALL,则SELECT列表中任何大于512字节的列


Red*_*ter 2

尝试使用UNION ALL.

UNION其本身将删除任何重复的记录,这意味着幕后排序。