2010-06-19 84 views
119

在處理大型數據庫時,哪個性能更好,INOR - SQL Where - 條款?IN vs OR中的SQL WHERE子句

他們的執行方式有什麼不同嗎?

+0

我的第一個猜想是,或者執行更好,除非SQL引擎轉換成或幕後。你見過這兩個查詢計劃嗎? – Raj 2010-06-19 07:19:21

+0

[MYSQL OR vs IN性能]可能的重複(http://stackoverflow.com/questions/782915/mysql-or-vs-in-performance) – 2016-11-08 08:30:49

回答

125

我假設你想知道下面之間的性能差異:

WHERE foo IN ('a', 'b', 'c') 
WHERE foo = 'a' OR foo = 'b' OR foo = 'c' 

根據manual for MySQL如果值是常數IN排序列表,然後使用二進制搜索。我會想象,OR評估他們一個接一個沒有特定的順序。所以IN在某些情況下速度更快。

要知道的最好方法是使用特定數據在數據庫上分析兩者,以查看哪個更快。

我試着用1000000行的MySQL。列索引時,性能沒有明顯差異 - 兩者幾乎都是即時的。使用

SELECT COUNT(*) FROM t_inner WHERE val IN (1000, 2000, 3000, 4000, 5000, 6000, 7000, 8000, 9000); 
1 row fetched in 0.0032 (1.2679 seconds) 

SELECT COUNT(*) FROM t_inner WHERE val = 1000 OR val = 2000 OR val = 3000 OR val = 4000 OR val = 5000 OR val = 6000 OR val = 7000 OR val = 8000 OR val = 9000; 
1 row fetched in 0.0026 (1.7385 seconds) 

因此,在這種情況下,方法或慢約30%:當列沒有被索引我得到了這些結果。增加更多的術語會使差異更大。其他數據庫和其他數據的結果可能會有所不同。

+15

如果優化器值得它的鹽,它們應該執行相同的操作。 – 2010-06-19 07:30:52

+21

@inflagranti:不幸的是沒有優化器是完美的。優化器是非常複雜的程序,每個實現都有其優點和缺點。這就是爲什麼我說你應該介紹一個特定的實現。我想像'IN'方法的額外結構可以比一大堆可能相關的'OR'子句更容易優化。如果有一個'OR'方法更快的引擎,我會感到驚訝,但我並不感到有些時候OR更慢時並不感到驚訝。 – 2010-06-19 08:12:31

+2

@MarkByers優化器不能總是用多個'OR'替代'IN'嗎? – mayu 2016-09-19 22:23:20

1

OR(從可讀性的角度來看)是有意義的,當有較少的值進行比較時。 IN尤其有用。當你有一個動態的來源,你想要比較值。

另一種替代方法是將JOIN與臨時表一起使用。
我不認爲性能應該是一個問題,只要你有必要的索引。

26

找出最佳方法是查看執行計劃。


試了一下甲骨文,這是完全一樣的。

CREATE TABLE performance_test AS (SELECT * FROM dba_objects); 

SELECT * FROM performance_test 
WHERE object_name IN ('DBMS_STANDARD', 'DBMS_REGISTRY', 'DBMS_LOB'); 

即使查詢使用IN,執行計劃說,它使用OR

--------------------------------------------------------------------------------------  
| Id | Operation   | Name    | Rows | Bytes | Cost (%CPU)| Time  |  
--------------------------------------------------------------------------------------  
| 0 | SELECT STATEMENT |     |  8 | 1416 | 163 (2)| 00:00:02 |  
|* 1 | TABLE ACCESS FULL| PERFORMANCE_TEST |  8 | 1416 | 163 (2)| 00:00:02 |  
--------------------------------------------------------------------------------------  

Predicate Information (identified by operation id):          
---------------------------------------------------          

    1 - filter("OBJECT_NAME"='DBMS_LOB' OR "OBJECT_NAME"='DBMS_REGISTRY' OR     
       "OBJECT_NAME"='DBMS_STANDARD')            
+1

如果您有超過3個正在測試的值,Oracle會發生什麼情況?你知道Oracle是否無法像MySQL一樣執行相同的二分搜索優化,或者它是否在這兩種情況下都能執行? – 2010-06-19 08:59:44

+2

@Mark Byers:我用10個值嘗試了相同的查詢,結果仍然相同。請注意,優化器按字母順序使用了我的值。如果Oracle對該過濾器進行了一些內部優化,我不會感到驚訝... – 2010-06-19 09:49:12

+5

Oracle也有一個'INLIST ITERATOR'操作,它會選擇是否有可用的索引。不過,當我試用它時,'IN'和'OR'結果都是相同的執行計劃。 – 2010-06-19 15:47:04

5

我認爲甲骨文很聰明,可以將效率較低的一方(無論是哪一方)轉換成另一方。所以我認爲答案應該取決於每個的可讀性(我認爲IN明顯勝出)

5

OR運算符需要比IN構造更復雜的評估過程,因爲它允許許多條件,不僅等於像在。

這裏是一個你可以使用的但是與IN不兼容的: 更大。大於或等於,小於,小於或等於,LIKE和一些更像oracle的REGEXP_LIKE。 另外考慮到條件可能並不總是比較相同的值。

對於查詢優化器來說,更容易管理IN運算符,因爲它只是一個構造,它在多個條件中使用=運算符定義OR運算符的值相同。如果使用OR運算符,優化程序可能不會認爲您總是對相同的值使用=運算符,並且如果它沒有執行更深入和更復雜的闡述,則可能會排除僅可能存在=所有相關條件下的相同值的運算符,並隨後排除優化的搜索方法(如已提及的二進制搜索)。

[編輯] 可能優化器可能不會實現優化的IN評估過程,但這並不排除它可能發生的一次(數據庫版本升級)。因此,如果您使用優化精化的OR運算符將不會用於您的情況。

1

我在大量的OR(350)中做了一個SQL查詢。 Postgres做它437.80ms

Use OR

現在使用IN:

Use IN

23.18ms

+1

這不完全相同,因爲你已經使用了IN子句的子查詢。 – gliljas 2017-01-16 16:35:52