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

Amo*_*tir 6 sqlite benchmarking android

SQLite在Android应用程序上使用数据库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;
}
Run Code Online (Sandbox Code Playgroud)

正如您所看到的,我也在测量每次迭代时此循环所花费的时间,结果表明它需要1800 ms的平均时间(在a上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 ms.

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

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

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

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

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

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

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

所以我的问题是:

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

谢谢!

编辑

我把这些getColumnIndex调用带出了@superfell建议的循环,现在我运行的getAll方法平均为1500ms.在我看来,它更快但不够快(再次)!

sup*_*ell 9

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


Com*_*are 3

正常吗?

当然。

如果是,为什么?

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

有没有更快的方法对 SQLite 数据库执行 selectAll?

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

使用 Traceview 准确确定您的时间都花在哪里,并相应地调整您的应用程序。例如,您可能会发现一Cursor开始就不将数据从 POJO 列表复制到 POJO 列表中更有意义。