循环使用SQLite Cursor需要花费太多时间

时间:2011-09-16 17:35:14

标签: android sqlite benchmarking

我在Android应用程序上使用SQLite数据库,我写的getAll方法在我看来花了太多时间。

这是我正在谈论的代码:

public static List<Feed> getAll(Context context) {
        List<Feed> feeds = new ArrayList<Feed>();
        Uri allFeeds = Uri.parse(ContentProvidersUris.URL_CONTENT_PROVIDER_FEED);

        long startQuery = BenchmarkUtils.start();
        Cursor c = context.getContentResolver().query(allFeeds, null, null, null, "title desc");

        long startCursor = BenchmarkUtils.start();
        for (c.moveToFirst(); !c.isAfterLast(); c.moveToNext()) {
            long startInsideCursor = BenchmarkUtils.start();

            Feed feed = new Feed();
            feed.setContent(c.getString(c.getColumnIndex(FeedsProvider.COL_WEBVIEW_CONTENT)));
            feed.setDate(c.getString(c.getColumnIndex(FeedsProvider.COL_PUB_DATE)));
            feed.setDescription(c.getString(c.getColumnIndex(FeedsProvider.COL_DESCRIPTION)));
            feed.setName(c.getString(c.getColumnIndex(FeedsProvider.COL_FEED_NAME)));

            Log.d(TAG, "This loop  cursor iteration took : " + BenchmarkUtils.stop(startInsideCursor) + " ms.");
        }

        Log.d(TAG, "Looping through the ENTIRE Cursor took: " + BenchmarkUtils.stop(startCursor) + " ms.");


        return feeds;
}

正如您所看到的,我也在测量每次迭代时此循环所花费的时间,结果表明平均时间 1800 ms (在Nexus S上)。我发现这是很多时间。而我不明白的是,大部分时间都花在第一次迭代上,如日志中所示:

  

D / FeedsProviderHelper(5800):此循环光标迭代采用:1726 ms。

     

D / FeedsProviderHelper(5800):此循环光标迭代采用:3 ms。

     

D / FeedsProviderHelper(5800):此循环光标迭代耗时:2 ms。

     

D / FeedsProviderHelper(5800):此循环光标迭代采用:3 ms。

     

D / FeedsProviderHelper(5800):此循环光标迭代耗时:2 ms。

     

D / FeedsProviderHelper(5800):此循环光标迭代采用:3 ms。

     

D / FeedsProviderHelper(5800):此循环光标迭代采用:3 ms。

     

D / FeedsProviderHelper(5800):此循环光标迭代耗时:2 ms。

     

D / FeedsProviderHelper(5800):此循环光标迭代采用:0 ms。

     

D / FeedsProviderHelper(5800):此循环光标迭代耗时:5毫秒。

     

D / FeedsProviderHelper(5800):此循环光标迭代采用:1 ms。

     

D / FeedsProviderHelper(5800):此循环光标迭代采用:1 ms。

     

D / FeedsProviderHelper(5800):此循环光标迭代耗时:5毫秒。

     

D / FeedsProviderHelper(5800):此循环光标迭代采用:1 ms。

     

D / FeedsProviderHelper(5800):此循环光标迭代采用:1 ms。

     

D / FeedsProviderHelper(5800):此循环光标迭代采用:1 ms。

     

D / FeedsProviderHelper(5800):通过整个游标循环:   1770毫秒。

所以我的问题是:

这是正常的吗?如果是,为什么?如果没有,我做错了什么?有没有更快的方法对SQLite数据库进行selectAll

谢谢!

修改

我将@ getColumnIndex调用排除在@superfell建议的循环之外,现在我以平均 1500ms 运行getAll方法。在我看来,它更快但不够快(再次)!

2 个答案:

答案 0 :(得分:9)

你应该做的第一件事就是把getColumnIndex调用带出循环,它们很昂贵,你只需要做一次,而不是每一行。

答案 1 :(得分:3)

  

这是正常的吗?

不确定

  

如果是,为什么?

磁盘I / O价格昂贵,尤其是在闪存上。查询本身正在针对Cursor的第一个实际请求上执行,这就是为什么您的第一次“迭代”花费的时间要长得多。

  

对SQLite数据库执行selectAll的更快方法是什么?

首先,您没有针对SQLite数据库执行“selectAll”。你正在对内容提供商进行“selectAll”。

使用Traceview准确确定您的时间占用时间,并相应地调整您的应用程序。例如,您可能会发现,首先不将数据从Cursor复制到POJO列表中会更有意义。