2014-04-02 33 views
3

比方說,我有一個表Tf的索引。我想基於myF的某個整數對f進行過濾。如果整數是0,我想要所有記錄fnull。一個可靠的方式寫這將是:使用IFNULL會阻止SQLite使用索引嗎?

db.rawQuery("SELECT someField FROM T WHERE " 
     + (myF == 0 ? "f IS NULL" : "f = ?"), 
     (myF == 0 ? new String[] {}, new String[] {String.valueOf(myF)})); 

這有點不方便;特別是如果查詢比這更復雜並且具有其他參數。所以我想我會寫

db.rawQuery("SELECT someField FROM T WHERE IFNULL(f, 0) = ?", 
     new String[] {String.valueOf(myF)}); 

代替,這是更簡單,更易於閱讀,更容易maintain.¹

我的問題是:如果在f的索引,將SQLite的還是使用該索引或將訴諸表掃描?我在問,因爲在後一種情況下,我不比較字段和參數,而是表達式和一個參數,我不確定SQLite查詢優化器是多麼「聰明」。


¹請注意,有與數據庫中的f = 0沒有記錄。

回答

4

這將導致表掃描。

實施例使用sqlite3的命令行客戶機:

sqlite> create table t(f); 
sqlite> create index tf on t(f); 
sqlite> explain query plan select * from t where ifnull(f,0)=1; 
0|0|0|SCAN TABLE t (~500000 rows) 
sqlite> explain query plan select * from t where f is null; 
0|0|0|SEARCH TABLE t USING COVERING INDEX tf (f=?) (~10 rows) 
sqlite> explain query plan select * from t where f=1; 
0|0|0|SEARCH TABLE t USING COVERING INDEX tf (f=?) (~10 rows)