我正在尝试进行查询以查找特定用户的电子邮件,其中用户编写了电子邮件(存储在电子邮件表本身中)或者在电子邮件中被抄送,存储在另一个连接到电子邮件的电子邮件中查询中的电子邮件表。
此查询非常慢。 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
答案 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 )