mySQL JOIN在WHERE子句中使用AND导致查询缓慢

时间:2013-08-08 16:57:40

标签: mysql

我正在尝试进行查询以查找特定用户的电子邮件,其中用户编写了电子邮件(存储在电子邮件表本身中)或者在电子邮件中被抄送,存储在另一个连接到电子邮件的电子邮件中查询中的电子邮件表。

此查询非常慢。 email_cc表中有大约一百五十万封电子邮件和一个令牌数量的条目;但WHERE子句中的OR将对电子邮件表的简单查询转换为需要1000倍的事情。

如何重写此查询以使其具有高性能?

**email**
id (PRIMARY)
userid (INDEX)

**email_cc**
id (PRIMARY)
userid (INDEX)
emailid (INDEX)

SELECT email.id, email.userid
FROM email
LEFT JOIN email_cc ON (email_cc.emailid = email.id)
WHERE (email.userid = 5 OR email_cc.userid = 5)

回复评论:运行此查询:

EXPLAIN SELECT COUNT(DISTINCT email.id) FROM email 
LEFT JOIN email_cc ON email_cc.emailid = email.id 
WHERE (email.userid = 468741 OR email_cc.userid = 468741)

获取

SIMPLE  email   index   IDX_54469DF4217BBB47    IDX_54469DF4217BBB47    5   NULL    1514520 Using index
SIMPLE  email_cc    ref IDX_8D675752700047D2    IDX_8D675752700047D2    4   email.id    1   Using where

2 个答案:

答案 0 :(得分:1)

我建议你使用union,因为它比or要快。这样的事情: -

SELECT email.id, email.userid
FROM email
LEFT JOIN email_cc ON (email_cc.emailid = email.id)
WHERE email.id = 5

union

SELECT email.id, email.userid
FROM email
LEFT JOIN email_cc ON (email_cc.emailid = email.id)
WHERE email_cc.id = 5

“或”导致电子邮件表上的表扫描,即使email.id和email.userid都有索引。联合会将其转换为索引搜索+索引扫描。 (假设有两列索引)

答案 1 :(得分:1)

你可以尝试一下吗

根据OP的评论更新

SELECT 
  email.id, 
  email.userid
FROM 
  email
WHERE 
  email.id = 5
  OR EXISTS ( SELECT 1 FROM email_cc WHERE email_cc.id = 5 )