2011-09-16 82 views
6

我在Android應用程序上使用SQLite數據庫,我寫的getAll方法在我看來花費了太多時間。通過SQLite光標循環需要的時間太長

這是我講的代碼:

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毫秒。

D/FeedsProviderHelper(5800):此循環遊標迭代花費:3毫秒。

D/FeedsProviderHelper(5800):此循環遊標迭代花費:2 ms。

D/FeedsProviderHelper(5800):此循環遊標迭代花費:3毫秒。

D/FeedsProviderHelper(5800):此循環遊標迭代花費:2 ms。

D/FeedsProviderHelper(5800):此循環遊標迭代花費:3毫秒。

D/FeedsProviderHelper(5800):此循環遊標迭代花費:3毫秒。

D/FeedsProviderHelper(5800):此循環遊標迭代花費:2 ms。

D/FeedsProviderHelper(5800):此循環遊標迭代花費:0毫秒。

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建議,現在我在平均1500毫秒運行getAll方法。這是更快但速度不夠快,在我看來(再次)!

+0

如果內容提供者處於相同的過程中,還是跨越過程,那麼第一行的時序看起來很奇怪。 – superfell

+0

@superfell同樣的過程。 –

回答

3

這是正常的嗎?

當然。

如果是,爲什麼?

磁盤I/O很貴,特別是在閃存上。查詢本身正在對Cursor的第一個真實請求執行,這就是爲什麼您的第一次「迭代」要花費更長時間。

任何更快的方式來執行selectAll對SQLite數據庫?

首先,您沒有對SQLite數據庫執行「selectAll」操作。您正在對內容提供者執行「selectAll」操作。

使用Traceview精確確定您的時間正在被佔用的位置,並相應地調整您的應用程序。例如,您可能會發現,首先不要將Cursor中的數據複製到POJO列表中更有意義。

+0

謝謝,現在更清楚!鑑於你在談論Traceview,你能看看這個問題嗎? http://stackoverflow.com/questions/6491855/android-cant-use-traceview 我只是不能使用它:( –

+0

@CommonsWare什麼是你的建議?當我們做什麼,而不是將數據複製到POJO列表做原始查詢嗎?謝謝 – Ewoks

+0

@Ewoks:你的選擇是直接用'Cursor'工作(例如,把它放在'SimpleCursorAdapter'中)。 – CommonsWare

9

你應該做的第一件事就是將getColumnIndex調用從循環中取出,它們很昂貴,而且你只需要做一次而不是每一行。

+0

好點。我會做的。 –

+0

救了我〜300ms。 –