2011-09-16 24 views
6

Tôi đang sử dụng cơ sở dữ liệu SQLite trên một ứng dụng Android và phương pháp getAll mà tôi đã viết mất quá nhiều thời gian theo ý kiến ​​của tôi.Lặp qua một Con trỏ SQLite mất quá nhiều thời gian

Đây là mã tôi đang nói về:

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

Như bạn có thể thấy tôi cũng đang đo thời gian thực hiện bằng vòng lặp này tại mỗi lần lặp và nó chỉ ra rằng phải mất một thời gian trung bình của 1800 ms (trên Nexus S). Tôi thấy rằng đây là rất nhiều thời gian. Và những gì tôi không hiểu là hầu hết thời gian này là dành vào ngày đầu tiên lặp như thể hiện trong các bản ghi:

D/FeedsProviderHelper (5800): con trỏ lặp Vòng lặp này mất: 1726 ms.

D/FeedsProviderHelper (5800): Vòng lặp con trỏ vòng lặp này mất: 3 ms.

D/FeedsProviderHelper (5800): Vòng lặp con trỏ vòng lặp này mất: 2 ms.

D/FeedsProviderHelper (5800): Vòng lặp con trỏ vòng lặp này mất: 3 ms.

D/FeedsProviderHelper (5800): Vòng lặp con trỏ vòng lặp này mất: 2 ms.

D/FeedsProviderHelper (5800): Vòng lặp con trỏ vòng lặp này mất: 3 ms.

D/FeedsProviderHelper (5800): Vòng lặp con trỏ vòng lặp này mất: 3 ms.

D/FeedsProviderHelper (5800): Vòng lặp con trỏ vòng lặp này mất: 2 ms.

D/FeedsProviderHelper (5800): Vòng lặp con trỏ vòng lặp này mất: 0 ms.

D/FeedsProviderHelper (5800): Vòng lặp con trỏ vòng lặp này mất: 5 ms.

D/FeedsProviderHelper (5800): Vòng lặp con trỏ vòng lặp này mất: 1 ms.

D/FeedsProviderHelper (5800): Vòng lặp con trỏ vòng lặp này mất: 1 ms.

D/FeedsProviderHelper (5800): Vòng lặp con trỏ vòng lặp này mất: 5 ms.

D/FeedsProviderHelper (5800): Vòng lặp con trỏ vòng lặp này mất: 1 ms.

D/FeedsProviderHelper (5800): Vòng lặp con trỏ vòng lặp này mất: 1 ms.

D/FeedsProviderHelper (5800): Vòng lặp con trỏ vòng lặp này mất: 1 ms.

D/FeedsProviderHelper (5800): Lặp qua con trỏ ENTIRE mất: 1770 ms.

Vì vậy, câu hỏi của tôi là:

Có bình thường không? Nếu đúng thì tại sao? Nếu không, tôi đang làm gì sai? Bất kỳ cách nào nhanh hơn để thực hiện một selectAll đối với cơ sở dữ liệu SQLite?

Cảm ơn!

EDIT

Tôi đã getColumnIndex cuộc gọi ra khỏi vòng lặp như @superfell đề nghị, và bây giờ tôi đang chạy phương pháp getAll ở mức trung bình 1500ms. Nó nhanh hơn nhưng không đủ nhanh theo ý kiến ​​của tôi (một lần nữa)!

+0

Là nhà cung cấp nội dung trong cùng một quy trình, hoặc là nó sẽ vượt qua quá trình, thời gian trên hàng đầu tiên trông rất kỳ quặc. – superfell

+0

@superfell Cùng một quy trình. –

Trả lời

3

Có bình thường không?

Chắc chắn.

Nếu có, tại sao?

Đĩa I/O đắt tiền, đặc biệt là trên flash. Bản thân truy vấn đang thực thi theo yêu cầu thực sự đầu tiên của bạn dựa trên Cursor, đó là lý do tại sao "lần lặp" đầu tiên của bạn mất nhiều thời gian hơn.

Bất kỳ cách nào nhanh hơn để thực hiện lựa chọnTất cả đối với cơ sở dữ liệu SQLite?

Trước tiên, bạn không thực hiện "selectAll" dựa vào cơ sở dữ liệu SQLite. Bạn đang thực hiện "selectAll" đối với nhà cung cấp nội dung.

Sử dụng Traceview để xác định chính xác thời gian của bạn đang được thực hiện và điều chỉnh ứng dụng của bạn cho phù hợp. Ví dụ: bạn có thể thấy rằng không cần sao chép dữ liệu từ Cursor vào danh sách POJO ở địa điểm đầu tiên.

+0

Cảm ơn, giờ đây rõ ràng hơn! Vì bạn đang nói về Traceview, bạn có thể xem câu hỏi này không? http://stackoverflow.com/questions/6491855/android-cant-use-traceview Tôi không thể sử dụng nó: ( –

+0

@CommonsWare Đề xuất của bạn là gì? Thay vào đó hãy sao chép dữ liệu vào danh sách POJO khi chúng tôi làm các truy vấn thô? Cảm ơn – Ewoks

+0

@Ewoks: Bạn thay thế là làm việc trực tiếp với 'Cursor' (ví dụ, đặt nó trong một' SimpleCursorAdapter'). – CommonsWare

9

Điều đầu tiên bạn nên làm là thực hiện cuộc gọi getColumnIndex ngoài vòng lặp, chúng đắt tiền và bạn chỉ cần thực hiện chúng một lần, không phải cho mỗi hàng.

+0

Điểm tốt. Tôi sẽ làm việc này. –

+0

Đã lưu tôi ~ 300 mili giây. –

Các vấn đề liên quan