2014-02-27 81 views
0

我有两个表选择,我想抓住这两个表之间的共同列的具体日期,我也希望这些分组:与JOIN时间太长

SELECT uv.keywordid, uv.competitionid 
    FROM unique_views as uv 
     JOIN signups AS s 
      ON s.keywordid=uv.keywordid 
       AND s.competitionid=uv.competitionid 
WHERE uv.dt_created > "2014-02-27" 
     AND s.dt_created > "2014-02-27" 
GROUP BY 
     uv.keywordid, uv.competitionid 
ORDER BY 
     uv.keywordid, uv.competitionid 

两个keywordid和competitionid在被索引两张桌子。目前这两个表都有大约11k条记录,并且大多数条目具有相同的keywordid和competitionid。

此查询锁定我的表约20秒。我能做些什么来提高速度?

+0

显示此查询的'EXPLAIN'可能会有所帮助 – Volvox

+0

使用'GROUP BY'的原因是什么?显然你没有使用任何聚合函数。 –

+0

你有'dt_created'上的索引吗? “keywordid”和“competitionid”上的索引是分开的还是复合的? – Barmar

回答

2

因此,您希望在2014-02-27之后创建的表中有两个不同的关键字对,在两个表中都有记录。然后使用DISTINCT,而不是GROUP BY。

这是一种保证在进行连接之前从每个表中选择不同元组的方法。所以这应该是快速的:

select keywordid, competitionid 
from 
    (select distinct keywordid, competitionid from unique_views where dt_created > "2014-02-27") uv 
inner join 
    (select distinct keywordid, competitionid from signups where dt_created > "2014-02-27") s 
using (keywordid, competitionid) 
order by keywordid, competitionid; 
0

让我们假设您的一半数据(5K)共享相同的密钥(uv.keywordid,uv.competitionid)。 然后,您的JOIN条件(s.keywordid=uv.keywordid AND s.competitionid=uv.competitionid)对于5k * 5k条可能的一对记录是真实的,这意味着您必须服务的25M个可能结果。我认为你的查询中有一个设计问题。

1

二十秒似乎很长一段时间。我建议将查询重写为exists查询。这消除了聚合并允许进行其他优化。

select s.keywordid, s.competitionid 
from signups s 
where s.dt_created > '2014-02-27' and 
     exists (select 1 
       from unique_views uv 
       where s.keywordid = uv.keywordid and 
        s.competitionid = uv.competitionid and 
        uv.dt_created > '2014-02-27' 
      ); 

这是假定没有重复keywordidcompetitionid双中注册。如果这是可能的,那么使用这个版本:

select s.keywordid, s.competitionid 
from (select distinct s.keywordid, s.competitionid 
     from signups s 
     where s.dt_created > '2014-02-27' 
    ) s 
where exists (select 1 
       from unique_views uv 
       where s.keywordid = uv.keywordid and 
        s.competitionid = uv.competitionid and 
        uv.dt_created > '2014-02-27' 
      ); 

接下来,创建以下两个指标:

create index signups_dt_created_keywordid_competitionid on signups(dt_created, keywordid, competitionid); 
create index unique_views_keywordid_competitionid_dt_created on unique_views(keywordid, competitionid, dt_created); 

这些指标实际上是“覆盖”查询,所以索引可以用于处理而不是原始数据页面。

+0

太棒了!绩效部门要好得多。考虑dt_created是一个日期时间字段,你会说这是索引该列的不错选择吗?我希望有这个查询与额外的情况下:dt_created> ='2014-02-27 00:00:00'和dt_created <='2014-02-27 23:59:59' –

+0

@JorgAncrath。 。 。 'dt_created'在我建议的两个索引中。这些索引也适用于您的子句。 –

1

鉴于你没有使用任何聚合(例如SUM,COUNT),我不知道你为什么要分组。

我也不知道你的意思时,你说:

大多数条目具有相同keywordid和competitionid。

这是否意味着在两个表中都有很多重复的keywordid/competitionid,或者给定的组合大多存在于两个表中?

我怀疑你是在寻找独特的记录而不是分组。如果不知道答案,我上面的两个问题,很难给出一个精确的响应,但你可能要考虑以下几点:

SELECT DISTINCT keywordid, competitionid 
FROM unique_views 
WHERE dt_created > "2014-02-27" 

SELECT DISTINCT keywordid, competitionid 
FROM signups 
WHERE dt_created > "2014-02-27" 

会给你在两个不同的组合表。这些可以结合在一起给你:

SELECT a.keywordid, a.competitionid 
FROM 
    (SELECT DISTINCT keywordid, competitionid 
    FROM unique_views 
    WHERE dt_created > "2014-02-27") a 
INNER JOIN 
    (SELECT DISTINCT keywordid, competitionid 
    FROM signups 
    WHERE dt_created > "2014-02-27") b 
ON a.keywordid = b.keywordid and a.competitionid = b.competitionid 
+0

你甚至解释了我比我想要的更好,谢谢。 –

+0

@ thorsten-kettner在他的回答中给出了几乎相同的查询,只是他使用了更为正确和简洁的'using'关键字 – Owen