使用IFNULL会阻止SQLite使用索引吗?

假设我有一个表T和一个在字段f上的索引.我想基于一些整数myF对f进行过滤.如果整数为0,则我希望所有记录为f为空.可以肯定的写法是:

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)});

相反,它更加简单,易于阅读并且易于维护.¹

我的问题是:如果f上有一个索引,sqlite仍会使用该索引还是将其用于表扫描?我问是因为在后一种情况下,我不是比较字段和参数,而是比较表达式和参数,而且我不确定sqlite查询优化器的“智能程度”.

¹请注意,数据库中没有f = 0的记录.

解决方法:

这将导致表扫描.

使用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)

相关文章

Android性能优化——之控件的优化 前面讲了图像的优化,接下...
前言 上一篇已经讲了如何实现textView中粗字体效果,里面主要...
最近项目重构,涉及到了数据库和文件下载,发现GreenDao这个...
WebView加载页面的两种方式 一、加载网络页面 加载网络页面,...
给APP全局设置字体主要分为两个方面来介绍 一、给原生界面设...
前言 最近UI大牛出了一版新的效果图,按照IOS的效果做的,页...