1

SQLite データベースの IO に関するいくつかの測定を行いました。このデータベースからいくつかのオブジェクトをロードするには、約 6 秒かかります。Asynctask を拡張するクラスがあります。このクラスの仕事は、データベースに最後の 10 個のエントリをロードすることです。このクラスは次のように構築されます。

import View.CustomAdapter;
import android.app.ProgressDialog;
import android.content.Context;
import android.os.AsyncTask;
import android.widget.ListView;
import android.widget.ProgressBar;
import android.widget.TextView;
import android.util.Log;
import android.view.*;

public class LoadCases extends AsyncTask<String, Integer, ArrayList<Case>> {

    ProgressBar progressBar;
    ArrayList<Case> lastTenCases; 
    CustomAdapter cAdapter; 
    Context context;
    ListView lastCases;
    DatabaseHandler db;
    TextView loading;
    int options;

    public LoadCases(ProgressBar progressBar, Context context, ListView lastCases, TextView loading, ArrayList<Case> lastTenCases) {
        this.progressBar = progressBar;
        this.context = context;
        this.lastCases = lastCases;
        this.loading = loading;
        this.lastTenCases = lastTenCases;
        db = new DatabaseHandler(context);
    }

    public void onPreExecute() {
        progressBar.incrementProgressBy(1);
    }


    @Override
    protected ArrayList<Case> doInBackground(String... params) {
        long start = System.nanoTime();
        lastTenCases = db.getAllCases(10);
        long end = System.nanoTime();
        Log.d("TIME TO LOAD CASES FROM BASE: ", Long.toString((end-start)/1000000000)); 
        return lastTenCases;
    }

    public void onPostExecute(ArrayList<Case> result) {
        progressBar.setVisibility(View.GONE);
        loading.setVisibility(View.GONE);
        cAdapter = new CustomAdapter(context, lastTenCases);    
        cAdapter.notifyDataSetChanged();
        lastCases.setAdapter(cAdapter); 

} }

ご覧のとおり、測定はメソッドを呼び出す直前に行われますgetAllCases(10)

long start = System.nanoTime();
lastTenCases = db.getAllCases(10);
long end = System.nanoTime();
Log.d("TIME TO LOAD CASES FROM BASE: ", Long.toString((end-start)/1000000000)); 

前述したように、データベースから 10 件のケースを読み込むのに約 6 秒かかります。

さて、getAllCasesメソッドに戻ります

public ArrayList<Case> getAllCases(int take) {

    ArrayList<Case> caseList = new ArrayList<Case>();
    String selectQuery = "SELECT  *, (strftime('%s', DATE) * 1000) AS DATENOW FROM " + TABLE_CASES + " ORDER BY " + DATE + " DESC LIMIT " + Integer.toString(take) + " ;";

    SQLiteDatabase db = this.getWritableDatabase();
    Cursor cursor = db.rawQuery(selectQuery, null);

    // looping through all rows and adding to list
    if (cursor.moveToFirst()) {
        do {
            Case c = new Case();

            long millis = cursor.getLong(cursor.getColumnIndexOrThrow("DATENOW"));
            Date addedOn = new Date(millis);
            c.setCaseNumber(cursor.getString(0));
            c.setDate(addedOn.toLocaleString());
            c.setStatus(cursor.getString(cursor.getColumnIndex(STATUS)));
            caseList.add(c);
        } while (cursor.moveToNext());
    }
    cursor.close();
    db.close();
    return caseList;
}

Caseこのメソッドはオブジェクトを構築し、これを に追加しArrayListます。この ArrayList が返されます。ええ、私はあなたがコードを理解していると思います。でも本当に6秒?私は何を間違っていますか?この操作を高速化するにはどうすればよいですか?

ありがとう!

4

1 に答える 1

1

これは、データベース構造 (たとえば、TABLE_CASES が別の複雑なクエリの場合) と のフィールド数によって異なりますTABLE_CASESが、少なくとも次の点が改善される可能性があります。

  • strftime('%s', DATE) * 1000)- CASEを取得する必要がある場合、毎回計算する必要がありますか? 計算の代わりにその値を保存すると、クエリが確実に高速化されます。
  • ArrayList が必要かどうかは不明ですが、おそらくCursorLoaderを使用できます。
  • このヒントに基づいて、new Date(millis)おそらくの呼び出しはループの外に移動する必要があります。
  • getColumnIndexOrThrowand の呼び出しgetColumnIndexもループの外に移動する必要があります。
  • toLocaleStringAPI レベル 1 では非推奨です。DateFormatを使用してください

最後に、traceview のこのガイドに従って、遅延が実際に SQLite で発生するか、またはその直後のループで発生するかを判断することをお勧めします。

于 2012-11-20T13:20:54.007 に答える