Цикл курсора SQLite занимает слишком много времени - PullRequest
6 голосов
/ 16 сентября 2011

Я использую базу данных 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;
}

Как вы можете видеть, я также измеряю время, затрачиваемое этим циклом на каждой итерации, и получается, что оно занимает в среднем 1800 мс (на Nexus S). Я считаю, что это много времени. И что я не понимаю, так это то, что большая часть этого времени уходит на первую итерацию , как показано в журналах:

D / FeedsProviderHelper (5800): Эта итерация курсора цикла заняла: 1726 мс.

D / FeedsProviderHelper (5800): Эта итерация курсора цикла заняла: 3 мс.

D / FeedsProviderHelper (5800): Эта итерация курсора цикла заняла: 2 мс.

D / FeedsProviderHelper (5800): Эта итерация курсора цикла заняла: 3 мс.

D / FeedsProviderHelper (5800): Эта итерация курсора цикла заняла: 2 мс.

D / FeedsProviderHelper (5800): Эта итерация курсора цикла заняла: 3 мс.

D / FeedsProviderHelper (5800): Эта итерация курсора цикла заняла: 3 мс.

D / FeedsProviderHelper (5800): Эта итерация курсора цикла заняла: 2 мс.

D / FeedsProviderHelper (5800): Эта итерация курсора цикла заняла: 0 мс.

D / FeedsProviderHelper (5800): Эта итерация курсора цикла заняла: 5 мс.

D / FeedsProviderHelper (5800): Эта итерация курсора цикла заняла: 1 мс.

D / FeedsProviderHelper (5800): Эта итерация курсора цикла заняла: 1 мс.

D / FeedsProviderHelper (5800): Эта итерация курсора цикла заняла: 5 мс.

D / FeedsProviderHelper (5800): Эта итерация курсора цикла заняла: 1 мс.

D / FeedsProviderHelper (5800): Эта итерация курсора цикла заняла: 1 мс.

D / FeedsProviderHelper (5800): Эта итерация курсора цикла заняла: 1 мс.

D / FeedsProviderHelper (5800): цикл по ВСЕМУ курсору занял: 1770 мс.

Итак, мои вопросы:

Это нормально? Если да, то почему? Если нет, что я делаю не так? Есть ли более быстрый способ сделать selectAll для базы данных SQLite?

Спасибо!

EDIT

Я вынул getColumnIndex вызовы из цикла, как предложил @superfell, и теперь я использую метод getAll в среднем 1500 мс . Это быстрее, но не достаточно быстро, на мой взгляд (снова)!

Ответы [ 2 ]

9 голосов
/ 16 сентября 2011

Первое, что вы должны сделать, это вывести вызовы getColumnIndex из цикла, они дороги, и вам нужно делать их только один раз, а не для каждой строки.

3 голосов
/ 16 сентября 2011

Это нормально?

Конечно.

Если да, то почему?

Дисковый ввод-вывод дорог, особенно на флэш-памяти. Сам запрос выполняется по вашему первому реальному запросу против Cursor, поэтому ваша первая «итерация» занимает значительно больше времени.

Есть ли более быстрый способ сделать selectAll для базы данных SQLite?

Во-первых, вы не делаете selectAll для базы данных SQLite. Вы делаете «selectAll» против провайдера контента.

Используйте Traceview, чтобы точно определить, где ваше время занято, и соответствующим образом настроить приложение. Например, вы можете обнаружить, что более разумно не копировать данные из Cursor в список POJO.

...