2014-02-27 98 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