當我們使用等號和IN運算符具有相同的值時,SQL引擎有什麼不同?執行時間是否改變?等於(=)和IN之間的性能差異與一個值
一日一使用平等檢查操作
WHERE column_value = 'All'
:第二個使用OR運算符和單值
WHERE column_value IN ('All')
是否SQL引擎改變IN
到=
如果只有一個值嗎?
在MySQL和PostgreSQL中有相同的區別嗎?
當我們使用等號和IN運算符具有相同的值時,SQL引擎有什麼不同?執行時間是否改變?等於(=)和IN之間的性能差異與一個值
一日一使用平等檢查操作
WHERE column_value = 'All'
:第二個使用OR運算符和單值
WHERE column_value IN ('All')
是否SQL引擎改變IN
到=
如果只有一個值嗎?
在MySQL和PostgreSQL中有相同的區別嗎?
這兩條語句之間沒有區別,當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 |
-----------------------------------------------------
正如你可以看到,二者相。這是一個索引列。同樣適用於無索引的列(只是全表掃描)。
你對此有任何數據庫的官方參考嗎?我試過搜索,但沒有得到。 –
@SomnathMuluk更新了答案 – sagi
@SomnathMuluk: - 我不認爲有這樣的MySQL官方參考。如果您發現結果之間存在任何差異,您可以創建一個測試用例並自行測試。 –
當您使用單個值時,沒有區別。如果您要檢查上述兩個查詢的表掃描,索引掃描或索引查找,您會發現兩個查詢之間沒有區別。
在Mysql和PostgresSQL中有相同的區別嗎?
不,它不會對兩臺發動機有什麼區別(逸岸它會爲大多數數據庫中包括SQL服務器,Oracle等相同)。兩個引擎將轉換爲爲=
對於單個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子句多個值,最好將它們轉換成連接
我已經提到過只有一個值。 –
@SomnathMuluk:僅針對一個子句進行更新 – TheGameiswar
確實沒有什麼大的差別,但是如果column_value已編入索引,則IN
運算符可能不會將其作爲索引讀取。
遇到此問題一次,所以要小心。
您需要在兩者上運行執行計劃並查看結果。
我相信他們將具有相同的執行計劃,因爲只有一個值放在IN()
語句中時,它將以與正常=
符號相同的方式執行。
沒有理由讓優化器在像這樣的查詢上表現任何不同。
教人以漁,等下面是如何看到自己將做您的查詢什麼變化:
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
行告訴我們查詢是通過比較一個常數值和這個索引來執行的。
只是爲了添加不同的視角,rdbms系統的要點之一就是他們會爲您重寫您的查詢,併爲該查詢和所有等價的查詢選擇最佳執行計劃。這意味着只要兩個查詢在邏輯上相同,應始終在給定的rdbms上生成相同的執行計劃。這就是說,許多查詢是等價的(相同的結果集),但僅僅是因爲數據庫本身並不知道的約束,所以要小心這些情況(例如,對於數字爲1-6的標誌字段,數據庫不會不知道<3
與in (1,2)
相同)。但是在一天結束時,如果您只是在考慮and
和or
聲明的易讀性,那麼您寫入它們的方式對性能沒有影響。
不要試圖學習數以百萬計的規則,這在某種程度上意味着你總是會寫出儘可能絕對性能最好的代碼。寫清楚,簡單,*可以理解的*代碼,顯然會產生正確的結果。設定績效目標。然後*測量*您的代碼的性能。如果它充分執行,繼續前進。只有在表現不佳的情況下,你才應該花更多時間。在那個時候,嘗試像你的問題那樣的微小變化,然後再次測量*就很簡單。也許一個比另一個更快,但*它是否會產生顯着差異*? –
同意@Damien_The_Unbeliever。但是有時我在寫單行或單詞時更擔心SQL –
它們是99.9999999%相同。只要你不做類似'WHERE column_value IN((從list_of_values中選擇值,其中value ='All'limit 1))''那麼你很好。 ()語句中的子查詢帶來了巨大的影響。 – MonkeyZeus