我有一个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.0047s运行 第二次以0.0043s
运行然而,在联盟,他们运行0.27s ...为什么这?在UNION之后没有Order By,为什么MySQL不会简单地采用两个快速查询并将它们连接起来?
答案 0 :(得分:12)
UNION
会导致创建临时表,即使是UNION ALL
也是如此。
当执行UNION DISTINCT
(与UNION
相同)时,将使用索引创建临时表,以便可以删除重复项。使用UNION ALL
,将创建临时表,但不包含索引。
这解释了使用UNION ALL
时性能略有提升,并且还说明了使用UNION
而不是两个单独查询时的性能下降。
有关此问题的详细信息,请参阅MySQL performance blog上的以下条目:
UNION vs UNION ALL Performance
MySQL文档中的How MySQL Uses Internal Temporary Tables页面指出在以下情况下创建临时表:
...任何大于512的列 SELECT列表中的字节,如果是UNION或 使用UNION ALL
答案 1 :(得分:2)
尝试使用UNION ALL
。
UNION
本身将删除任何重复的记录,这意味着幕后的排序。