加快MYSQL的自我加入

时间:2013-05-10 15:04:37

标签: mysql optimization self-join


我有一个约280万行,3列的表。每行代表公司的营销方式,并且具有“customer_id”,“marketing_type”和“week_num”。“customer_id”上有索引,“marketing_type”上有另一个索引

数据的一个例子:

72, catalog,  7
72, email,    3
99, catalog, 13
82, catalog,  7

我需要一个包含电子邮件但没有目录的所有customer_id的列表。 (还有其他类型的营销,而且还有没有得到任何东西的customer_id)

首先尝试:

SELECT DISTINCT cust_id
FROM marketing_campaign
WHERE marketing_type = 'email'
AND cust_id NOT IN (
 SELECT cust_id
 FROM marketing_campagin
 WHERE marketing_type = 'catalog'
 )
;

此查询需要30多分钟才能运行


第二次尝试:

SELECT m1.cust_id 
FROM marketing_campaign m1
LEFT OUTER JOIN marketing_campaign m2 
  ON m1.cust_id = m2.cust_id 
 AND m2.MARKETING_TYPE = 'catalog'
WHERE m1.MARKETING_TYPE = 'email'
 AND m2.cust_id IS NULL
;

此查询在3.8秒内执行,但提取时间超过30分钟。


第三次尝试:

SELECT distinct cust_id
FROM   marketing_campaign a
WHERE  MARKETING_TYPE = 'email'
  AND  NOT EXISTS (
           SELECT 'X'
           FROM   marketing_campaign b
           WHERE  a.cust_id = b.cust_id
           AND    MARKETING_TYPE = 'catalog' 
           )
ORDER BY cust_id
;

此查询也在< 5秒内执行,但随后提取超过20分钟。

<小时/> 有人可以建议替代方案吗?

1 个答案:

答案 0 :(得分:2)

不要忽视复合索引:

ALTER TABLE marketing_campaign ADD KEY (marketing_type, cust_id);

然后使用查询#2。

另外,请确保已将缓冲区调整得足够大,以使索引驻留在RAM中。