2017-08-29 55 views
0

我有一個相當大的查詢,我最近添加了一個新的條件,我檢查字段是否不等於某個值。我會用不等於條件<>但我想設置它來處理多個值,以防將來添加更多值。因此,要保持事情簡單,你可以把大的查詢看起來像下面較小的查詢:「不在」比<>慢嗎?

SELECT * FROM FOO WHERE NVL(BAR, 1) NOT IN (2) 

當我運行查詢,它增加了一個額外的一分鐘,我的執行時間。沒有這個條件的原始查詢會在幾毫秒內返回。所以我調整了狀態看起來像這樣:

SELECT * FROM FOO WHERE NVL(BAR, 1) = 1 

我也嘗試過了這個

SELECT * FROM FOO WHERE NVL(BAR, 1) <> 2 

而且這兩個查詢中所需的幾毫秒內返回。但爲什麼使用NOT IN(2)比其他方法慢得多?對我來說完全是無稽之談。

注意:字段欄有很多可能的空值,並且欄列未被編入索引。

UPDATE:

好,我才意識到我留下了一個非常重要的細節。此問題僅在通過Java運行時才存在。所以我有一個包含查詢字符串,我又把它使用

org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate 

我沒有看到這個問題時,我直接上的SQLDeveloper運行查詢運行。

+1

你看着他們兩人的執行計劃的組合?也許它試圖爲'NOT IN'使用一個糟糕的計劃 – Siyual

+0

這是在運行什麼模式?什麼索引到位? – tadman

+0

這不是一種結構比另一種結構慢的情況,它是一些結構可以限制優化器,從而導致不同的執行計劃。在某些版本的Oracle中可能會出現一些怪癖。大概這個計劃在你的兩個案例中出現了不同。 –

回答

2

在某些情況下,查詢優化器不能夠efficent的方式來管理一個不是在左加入空或不存在,因此全掃描和檢查匹配生成慢查詢

假設你有適當的指數BAR柱 你可以嘗試避免NVL不

SELECT * 
FROM FOO 
WHERE BAR NOT IN (2) 
AND BAR IS NOT NULL 
+0

酒吧列沒有編入索引。我剛更新了這篇文章以反映這一點。儘管謝謝你的迴應。 –

+0

我剛纔意識到我遺漏了一個重要的細節。請參閱我的問題更新。抱歉。 –

+0

我不是在Java框架,但使用與其他語言framwork ..有時框架是不積極使用活動記錄或其他ORM 和可能執行sqlcommand ..直接..避免框架..開銷..可能是這樣也與你的框架.. – scaisEdge