2016-07-23 160 views
0

我有這樣的事情:LEFT JOIN或選擇選擇(SQL - 查詢的速度)

SELECT CompanyId 
FROM Company 
WHERE CompanyId not in 
    (SELECT CompanyId 
    FROM Company 
    WHERE (IsPublic = 0) and CompanyId NOT IN 
     (SELECT ShoppingLike.WhichId 
      FROM Company 
      INNER JOIN 
      ShoppingLike ON Company.CompanyId = ShoppingLike.UserId 
      WHERE (ShoppingLike.IsWaiting = 0) AND 
       (ShoppingLike.ShoppingScoreTypeId = 2) AND 
       (ShoppingLike.UserId = 75) 
     ) 
    ) 

它有3個選擇,我想知道我怎麼能有它未做3種選擇,而這一個有100萬條記錄更好的速度? 「select in select」或「left join」?

+0

如果性能出現問題,請嘗試使用硬件上數據庫上數據的每個版本,並查看哪個更快。 –

+0

它有兩個問題,我無法準備左連接,對於大數據我無法測試它,因爲我沒有:(如果MS SQL爲你做了 – dan

+0

,那麼不要擔心,因爲它的優化器會優化你可以在companyId上創建索引,以幫助MS SQL更快地完成查詢。 – Mahmoud

回答

0

我的經驗來自Oracle。優化棘手的查詢永遠不會有正確的答案,這是您與優化器之間的協作。在編寫查詢的每個階段,您都需要檢查解釋計劃和有時候的痕跡,以找出優化者的想法。話雖如此:

  • 你可以通過把它的全部內容刪除外SELECT是在一個NOT( ... )子查詢WHERE條款。表面上會阻止公司的外部全面掃描(或者它是CompanyId的索引)。嘗試一下,檢查輸出是否相同並獲取時間,然後在嘗試下面的內容之前暫時將其刪除。 NOT()很可能會導致優化程序因創建隱式OR而停止考慮針對ShoppingLike子查詢的ANTI-JOIN。
  • 確保CompanyId和WhichId定義爲NOT NULL列。沒有這個(或者明確的CompanyId IS NOT NULL),那麼ANTI-JOIN選項通常會被丟棄。
  • 最內層的子查詢不相關(不引用任何來自外層查詢的內容),因此可以分別提取和調整。就風格而言,我會將表名稱換成INNER JOIN,因爲您希望首先掃描ShoppingLike,因爲它具有針對它的所有過濾器。它不會產生任何影響,但它更容易閱讀,並可以使用提示以指定順序掃描表。我甚至會質疑這個子查詢中公司表的需求。
  • 您已使用NOT IN有時非常相似的NOT EXISTS爲優化器提供了更多/備選選項。

除非您開始嘗試解釋計劃,否則以上所有內容都只是試驗和錯誤。甲骨文可以通過以下方式在LEFT JOININ之間轉換SELECT。 1M +行將創造投資時間。

+0

所以謝謝:)它比我需要的更多幫助我 – dan