2

我正在尝试进行查询以查找特定用户的电子邮件,该用户要么编写电子邮件(存储在电子邮件表本身中),要么在电子邮件中抄送,存储在另一封电子邮件中,该电子邮件已加入到电子邮件表中查询。

这个查询很慢。email_cc 表中有大约 150 万封电子邮件和令牌数量的条目;但是 WHERE 子句中的 OR 会将针对电子邮件表的简单查询变成需要 1,000 倍的查询。

如何重写此查询以使其高效?

**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
4

2 回答 2

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 上都有索引,“或”也会导致对电子邮件表进行表扫描。联合会将其转换为索引查找 + 索引扫描。(假设有两列的索引)

于 2013-08-08T17:02:28.193 回答
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 )
于 2013-08-08T17:07:13.710 回答