2016-06-15 116 views
43

當我們使用等號和IN運算符具有相同的值時,SQL引擎有什麼不同?執行時間是否改變?等於(=)和IN之間的性能差異與一個值

一日一使用平等檢查操作

WHERE column_value = 'All' 

:第二個使用OR運算符和單值

WHERE column_value IN ('All') 

是否SQL引擎改變IN=如果只有一個值嗎?

在MySQL和PostgreSQL中有相同的區別嗎?

+19

不要試圖學習數以百萬計的規則,這在某種程度上意味着你總是會寫出儘可能絕對性能最好的代碼。寫清楚,簡單,*可以理解的*代碼,顯然會產生正確的結果。設定績效目標。然後*測量*您的代碼的性能。如果它充分執行,繼續前進。只有在表現不佳的情況下,你才應該花更多時間。在那個時候,嘗試像你的問題那樣的微小變化,然後再次測量*就很簡單。也許一個比另一個更快,但*它是否會產生顯着差異*? –

+3

同意@Damien_The_Unbeliever。但是有時我在寫單行或單詞時更擔心SQL –

+1

它們是99.9999999%相同。只要你不做類似'WHERE column_value IN((從list_of_values中選擇值,其中value ='All'limit 1))''那麼你很好。 ()語句中的子查詢帶來了巨大的影響。 – MonkeyZeus

回答

41

這兩條語句之間沒有區別,當IN只有一個元素時,優化程序會將IN轉換爲=

雖然當你有這樣的問題時,只需運行兩個語句,運行他們的執行計劃並查看差異。在這裏 - 你不會找到任何。

後大網上搜索,我發現了SQL文件來支持這個(我認爲它適用於所有DBMS):

如果只有一個括號內的值,這稱道的是相當於

WHERE 「欄」=「VALUE1

Here is the link to the document

下面是這兩個查詢了Oracle執行計劃(大多數DBMS將處理此相同):

EXPLAIN PLAN FOR 
select * from dim_employees t 
where t.identity_number = '123456789' 

Plan hash value: 2312174735 
----------------------------------------------------- 
| Id | Operation     | Name   | 
----------------------------------------------------- 
| 0 | SELECT STATEMENT   |    | 
| 1 | TABLE ACCESS BY INDEX ROWID| DIM_EMPLOYEES | 
| 2 | INDEX UNIQUE SCAN   | SYS_C0029838 | 
----------------------------------------------------- 

而對於IN()

EXPLAIN PLAN FOR 
select * from dim_employees t 
where t.identity_number in('123456789'); 

Plan hash value: 2312174735 
----------------------------------------------------- 
| Id | Operation     | Name   | 
----------------------------------------------------- 
| 0 | SELECT STATEMENT   |    | 
| 1 | TABLE ACCESS BY INDEX ROWID| DIM_EMPLOYEES | 
| 2 | INDEX UNIQUE SCAN   | SYS_C0029838 | 
----------------------------------------------------- 

正如你可以看到,二者相。這是一個索引列。同樣適用於無索引的列(只是全表掃描)。

+0

你對此有任何數據庫的官方參考嗎?我試過搜索,但沒有得到。 –

+0

@SomnathMuluk更新了答案 – sagi

+0

@SomnathMuluk: - 我不認爲有這樣的MySQL官方參考。如果您發現結果之間存在任何差異,您可以創建一個測試用例並自行測試。 –

8

當您使用單個值時,沒有區別。如果您要檢查上述兩個查詢的表掃描,索引掃描或索引查找,您會發現兩個查詢之間沒有區別。

在Mysql和PostgresSQL中有相同的區別嗎?

不,它不會對兩臺發動機有什麼區別(逸岸它會爲大多數數據庫中包括SQL服務器,Oracle等相同)。兩個引擎將轉換爲爲=

4

對於單個IN子句,沒有區別..下面是演示使用EMPS表我有..

select * from emps where empid in (1) 
select * from emps where empid=1 

斷言對於第一個查詢的執行計劃:

[PerformanceV3].[dbo].[Emps].[empID]=CONVERT_IMPLICIT(int,[@1],0) 

謂詞在執行計劃第二個查詢:

[PerformanceV3].[dbo].[Emps].[empID]=CONVERT_IMPLICIT(int,[@1],0) 

如果在IN子句多個值,最好將它們轉換成連接

+3

我已經提到過只有一個值。 –

+0

@SomnathMuluk:僅針對一個子句進行更新 – TheGameiswar

5

確實沒有什麼大的差別,但是如果column_value已編入索引,則IN運算符可能不會將其作爲索引讀取。

遇到此問題一次,所以要小心。

1

您需要在兩者上運行執行計劃並查看結果。

我相信他們將具有相同的執行計劃,因爲只有一個值放在IN()語句中時,它將以與正常=符號相同的方式執行。

沒有理由讓優化器在像這樣的查詢上表現任何不同。

5

教人以漁,等下面是如何看到自己將做您的查詢什麼變化:

mysql> EXPLAIN SELECT * FROM sentence WHERE sentence_lang_id = "AMH"\G 
*************************** 1. row *************************** 
      id: 1 
    select_type: SIMPLE 
     table: sentence 
     type: ref 
possible_keys: sentence_lang_id 
      key: sentence_lang_id 
     key_len: 153 
      ref: const 
     rows: 442 
     Extra: Using where 

而且讓我們嘗試用另一種方式:

mysql> EXPLAIN SELECT * FROM sentence WHERE sentence_lang_id in ("AMH")\G 
*************************** 1. row *************************** 
      id: 1 
    select_type: SIMPLE 
     table: sentence 
     type: ref 
possible_keys: sentence_lang_id 
      key: sentence_lang_id 
     key_len: 153 
      ref: const 
     rows: 442 
     Extra: Using where 

你可以請閱讀here以瞭解如何解釋mysql EXPLAIN請求的結果。現在請注意,我們對兩個查詢都得到了相同的輸出:完全相同的「執行計劃」生成。 type行告訴我們查詢使用非唯一索引(在這種情況下是外鍵),ref行告訴我們查詢是通過比較一個常數值和這個索引來執行的。

2

只是爲了添加不同的視角,rdbms系統的要點之一就是他們會爲您重寫您的查詢,併爲該查詢和所​​有等價的查詢選擇最佳執行計劃。這意味着只要兩個查詢在邏輯上相同,應始終在給定的rdbms上生成相同的執行計劃。這就是說,許多查詢是等價的(相同的結果集),但僅僅是因爲數據庫本身並不知道的約束,所以要小心這些情況(例如,對於數字爲1-6的標誌字段,數據庫不會不知道<3in (1,2)相同)。但是在一天結束時,如果您只是在考慮andor聲明的易讀性,那麼您寫入它們的方式對性能沒有影響。

相關問題