簡體   English   中英

Android SQLite和龐大的數據集

[英]Android SQLite and huge data sets

我們正在為SQLite數據庫中具有數百兆字節HTML的客戶端創建一個應用程序。 我們已經實現了一種查詢此數據的方法,並以合理快速的方式滾動瀏覽所有數據。 問題是某些數據庫有非常大的查詢(20,000多行),當我們在用戶滾動時增加查詢時,我們會看到錯誤。 所以我想問題是,我們在Android中查詢和顯示數萬行數據時有哪些選擇?

這是我們看到的堆棧跟蹤:

09-10 19:19:12.575: WARN/IInputConnectionWrapper(640): showStatusIcon on inactive InputConnection
09-10 19:19:18.226: DEBUG/dalvikvm(640): GC freed 446 objects / 16784 bytes in 330ms
09-10 19:19:32.886: ERROR/CursorWindow(19416): need to grow: mSize = 1048576, size = 36, freeSpace() = 30, numRows = 17717
09-10 19:19:32.896: ERROR/CursorWindow(19416): not growing since there are already 17717 row(s), max size 1048576
09-10 19:19:32.916: ERROR/CursorWindow(19416): The row failed, so back out the new row accounting from allocRowSlot 17716
09-10 19:19:33.005: ERROR/Cursor(19416): Failed allocating fieldDir at startPos 0 row 17716
09-10 19:19:35.596: DEBUG/Cursor(19416): finish_program_and_get_row_count row 24315
09-10 19:19:41.545: DEBUG/dalvikvm(698): GC freed 2288 objects / 126080 bytes in 260ms
09-10 19:19:43.705: WARN/KeyCharacterMap(19416): No keyboard for id 0
09-10 19:19:43.717: WARN/KeyCharacterMap(19416): Using default keymap: /system/usr/keychars/qwerty.kcm.bin
09-10 19:20:04.705: ERROR/CursorWindow(19416): need to grow: mSize = 1048576, size = 17, freeSpace() = 3, numRows = 17094
09-10 19:20:04.716: ERROR/CursorWindow(19416): not growing since there are already 17094 row(s), max size 1048576
09-10 19:20:04.726: ERROR/Cursor(19416): Failed allocating 17 bytes for text/blob at 17093,2
09-10 19:20:05.656: DEBUG/Cursor(19416): finish_program_and_get_row_count row 5257
09-10 19:24:54.685: DEBUG/dalvikvm(637): GC freed 9297 objects / 524176 bytes in 247ms
09-10 19:32:07.656: DEBUG/dalvikvm(19416): GC freed 9035 objects / 495840 bytes in 199ms

這是我們的CursorAdapter代碼:

    private class MyAdapter extends ResourceCursorAdapter {

    public MyAdapter(Context context, Cursor cursor) {
        super(context, R.layout.my_row, cursor);        
    }

    public void bindView(View view, Context context, Cursor cursor) {                
        RowData data = new RowData();
        data.setName(cursor.getInt(cursor.getColumnIndex("name")));

        TextView tvItemText = (TextView)view.findViewById(R.id.tvItemText);
        tvItemText.setText(data.getName());

        view.setTag(data);
    }

    @Override
    public Cursor runQueryOnBackgroundThread(CharSequence constraint) {
        /* Display the progress indicator */
        updateHandler.post(onFilterStart);

        /* Run the actual query */               
        if (constraint == null) {
            return myDbObject.getData(null);                     
        }

        return myDbObject.getData(constraint.toString());                
    }            
}

我們在Android中查詢和顯示數萬行數據時有哪些選擇?

你的意思是除了告訴你在3.5英寸液晶顯示器上閱讀20,000多行是蝙蝠 - 鳥糞瘋狂嗎?;-)

它看起來像CursorWindow ,它被用在CursorWindow某個地方,有問題管理> 17,000行。 這可能是兩件事之一:

  1. 你沒有堆空間。 使用16MB非壓縮堆,以及Cursor將整個結果集保存在堆中的事實,這不是不可能的。
  2. CursorWindow僅支持1MB的數據,這是錯誤消息更直接的建議。

如果有一種邏輯方法可以將查詢划分為離散塊,則可以執行增量查詢並使用CursorJoiner將它們拼接在一起,看看是否有幫助。

但是,嚴肅地說,3.5英寸屏幕上的20,000多行,在最接近馬力的12年PC上的設備上,確實需要很多。

如果你真的需要,你也可以拆分你的數據並讀取這樣的塊:

   int limit = 0;
   while (limit + 100 < numberOfRows) {
       //Compose the statement
       String statement = "SELECT * FROM Table ORDER someField LIMIT '"+ limit+"', 100";
       //Execute the query
       Cursor cursor = myDataBase.rawQuery(statement, null);
       while (cursor.moveToNext()) {
           Product product = new Product();
           product.setAllValuesFromCursor(cursor);
           productsArrayList.add(product);
      }
      cursor.close();
      limit += 100;
 }

 //Compose the statement
 String statement = "SELECT * FROM Table ORDER someField LIMIT '"+  (numberOfRows - limit)+"', 100";
 //Execute the query
 Cursor cursor = myDataBase.rawQuery(statement, null);

 while (cursor.moveToNext()) {
     Product product = new Product();
     product.setAllValuesFromCursor(cursor);
     productsArrayList.add(product);
 }
 cursor.close();

如果您有索引表,它在2秒內工作5k行。

謝謝,阿克德

根據我的經驗,限制查詢會使得獲得結果需要更長的時間,因為啟動新游標對於低限制來說是昂貴的。 我現在嘗試用1k甚至10k限制做62k行,因為我必須啟動超過6個游標,所以它非常慢且無法使用。 我只是堅持不支持2.3.3 ....這是我得到CursorWindow ERROR而不是WARN的最新版本。

這是我做的。 這可能是我認為最好的算法。 不必再進行兩次查詢等。但是,對於大查詢和小限制,它可能會變慢,因此您必須測試哪些方法效果最好。 在我的情況下,它不夠快我的目的,因為它不能很好地處理62k行。

int cursorCount = 0;
int limit = 1000; //whatever you want
while (true)
{
    Cursor cursor = builder.query(mDatabaseHelper.getReadableDatabase(), columns, selection, selectionArgs, null, null, null, Integer.toString(limit));
    if (cursor == null) {
        return null;
    } else if (!cursor.moveToFirst()) { //if it is empty, return null
        return null;
    }
    cursorCount = cursor.getCount();
    if (cursorCount % limit != 0)
    {
        return cursor;
    }
    limit+=1000; //same amount as the one above
} 

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM