2016-08-03 19 views
0

我試圖做一些基本的維恩圖減法來比較臨時表和一些實時數據,並看看它們是如何不同的。神祕查詢失敗:爲什麼這會產生大量輸出?

這個查詢在1500萬個返回行的北部發生了爆炸,並且我注意到它重複了一個已知的唯一字段 - 表明我的查詢出現了一些錯誤(我的意思是,行被複制,我可以通過這個全局唯一標識符字段來驗證)。我期待獲得最多200行返回:

select a.* 
    from TableOfLiveData a 
     inner join #TempDataToBeSubtracted b 
     on a.GUID <> b.guidTemp   --I suspect the issue is here 
    where {here was a limiting condition that should have reduced my live 
      data to a "pre-join" count(*) of 20,000 at most...} 

後我打了執行查詢運行更長的時間比預期的,我可以看到,在我不得不取消了正在返回數百萬行的。

讓我知道什麼是顯而易見的事!!?

編輯:供參考:如果其中不包括條款,我希望返回行的大量...

+3

我的意思是,你很可能在兩張表之間執行差不多的笛卡爾積。考慮一下,從第一個表中取一個'GUID'的值,並且你得到第二個表的每一行的結果,其中'guidTemp'不等於 – Lamak

+0

@Lamak,我想到了同樣的想法...但是它是內部連接?! – ColinMac

+1

內部聯接只是一個交叉聯接,其中包含對所有行進行評估的聯接謂詞。在所有行上進行交叉連接評估'a.GUID <> b.guidTemp'並將其保留爲真。 –

回答

1

謝謝@Lamak和@MartinSmith您的意見是解決了這個問題。

通過在我的「on」子句中使用'not equals',我確保我將在LiveTable中選擇在我的#TempTable中沒有GUID的每一行,而不僅僅是我想要的一次,我的#TempTable中的每個條目,在這種情況下(我的結果乘以大約20,000)(#TempTable的基數)。

爲了解決這個問題,我使用評論中推薦的「Not In」語句在我的#TempTable上做了一個簡單的子查詢。該查詢完成了在一分鐘之內,並在一個100行返回,這是很多更加符合我的期望:

select a.* 
    from TableOfLiveData a 
    where a.GUID not in (select b.guidTemp from #TempDataToBeSubtracted b) 
    and {subsequent constraint statement not relevant to question} 
0

雖然您的查詢是邏輯正確的,問題是你有一個「笛卡爾積「(nxm rows),但是在執行之後執行了where子句,因此您必須執行大量的行,在這些行上必須執行where子句......所以它會非常非常慢。

更好的方法是做一個上鍵列加入,但丟棄所有成功加入由過濾錯過加入:

select a.* 
from TableOfLiveData a 
left join #TempDataToBeSubtracted b on b.guidTemp = a.GUID 
where a.field1 = 3 
and a.field2 = 1515 
and b.guidTemp is null -- only returns rows that *don't* match 

這工作,因爲當外連接錯過了,您仍然可以從主表中獲取該行,並且連接表中的所有列都是null

(field1, field2)上創建索引將提高性能。

+0

我很好奇,如果我告訴你「加入」GUID只佔對於TableOfLiveData總數的1/10000,這個腳本會慢一些,因爲它基本上抓取了所有的TableOfLiveData BEFORE過濾Field1,Field2,GUID是否爲空? – ColinMac

+1

@ColinMac你是對的,它會首先嚐試連接來自TableOfLiveData的所有行,然後拋出匹配。但是這個過程會很快。 15M不是很多行,優化器應該能夠儘早拋出一些東西。只要'#TempDataToBeSubtracted(guidTemp)'上有一個索引,它應該非常快。 – Bohemian