Androidでsqliteのパフォーマンスを測定するためにいくつかの実験を行っています。結果に少しがっかりしました。私がしたことは、テーブルに10.000クエリを挿入することでした130-140秒かかりましたしかし、これらの条件;
1。省電力モードのSamsung Galaxy s3
2。挿入されたデータ(またはクラス)には3つの文字列と1つの浮動小数点(sqliteの場合は実際)があります
。 asynctaskでイベントの挿入が行われています。
4。 asynctaskで、渡されたタイマーテキストを含む進捗ダイアログを表示しています(System.currentTimeMillis-秒など)
class AddStudentsTask extends AsyncTask<Void,Integer,Void>
{
ProgressDialog prgDialog;
int max = 10000;
Student s;
long seconds = System.currentTimeMillis();
@Override
protected void onPreExecute() {
super.onPreExecute();
prgDialog = new ProgressDialog(MainActivity.this);
prgDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
prgDialog.setMessage(seconds+"");
prgDialog.setMax(max);
prgDialog.setCancelable(false);
prgDialog.show();
}
@Override
protected void onProgressUpdate(Integer... values) {
super.onProgressUpdate();
prgDialog.setProgress(values[0]);
sList.add(s);
String s = (System.currentTimeMillis()-seconds)/100+"";
if(s.length()>2)
s = s.substring(0,s.length()-1) + "." + s.charAt(s.length()-1);
else if(s.length() == 2)
s = s.charAt(0) + "." + s.charAt(1);
prgDialog.setMessage(s + " seconds passed.");
}
@Override
protected Void doInBackground(Void... voids) {
for(int a = 0;a< max; a++ )
{
Random r = new Random();
s = new Student();
s.setGpa(r.nextFloat()*4);
s.setLastName("asdasd");
s.setFirstName("Oh My God");
s.setAddress("1sadasd");
s.setId(sda.insert(s));
publishProgress(a);
}
return null;
}
@Override
protected void onPostExecute(Void aVoid) {
super.onPostExecute(aVoid);
prgDialog.dismiss();
sa.notifyDataSetChanged();
}
}
5。 helperdbクラスのinsertOrThrowメソッドでcontentValuesを使用しています。 これIS古いスローコード
public long insert(Student s)
{
SQLiteDatabase db = sh.getWritableDatabase();
ContentValues cv = new ContentValues();
cv.put(StudentHelper.FIRSTNAME,s.getFirstName());
cv.put(StudentHelper.LASTNAME,s.getLastName());
cv.put(StudentHelper.ADDRESS,s.getAddress());
cv.put(StudentHelper.GPA,s.getGpa());
s.setId(db.insertOrThrow(StudentHelper.TABLE_NAME, null, cv));
return s.getId();
}
6。このタスクは、アクティビティのonCreateメソッドで実行されます。
だから、私はここで何が間違っているのか、それからあまり期待しているのですか?これらの結果は大丈夫ですか、それとも悪いですか?
コードを改善するにはどうすればよいですか?
[〜#〜]編集[〜#〜]
だから私はこれに私の挿入コードを変更し、それは4.5秒に短縮しました!!!
public ArrayList<Long> insertMany(ArrayList<Student> stus)
{
ArrayList<Long> ids = new ArrayList();
String sql = "INSERT INTO "+StudentHelper.TABLE_NAME+"" +
"("+StudentHelper.FIRSTNAME+","+StudentHelper.LASTNAME+"," +
" "+StudentHelper.GPA+") values(?,?,?)";
SQLiteDatabase db = sh.getWritableDatabase();
db.beginTransaction();
for(Student s:stus) {
SQLiteStatement stmt = db.compileStatement(sql);
stmt.bindString(1, s.getFirstName());
stmt.bindString(2, s.getLastName());
stmt.bindDouble(3, s.getGpa());
s.setId(stmt.executeInsert());
ids.add(s.getId());
stmt.clearBindings();
}
db.setTransactionSuccessful();
db.endTransaction();
return ids;
}
使用する SQLite transaction
スピードアップ
SQLiteの最適化にはBEGIN TRANSACTION&END TRANSACTIONを使用します
各SQLステートメントは、デフォルトでSQLiteランタイムによって新しいトランザクションブロックに囲まれます。したがって、[〜#〜] insert [〜#〜]などの基本的なDB操作を実行すると、トランザクションブロックが作成され、その周りにラップされます。
SQLiteランタイムにトランザクションを管理させることは、ルーチンがデータセットに対して1つのDB操作のみを実行する場合にのみ推奨されます。ただし、多数のDB操作(たとえば[〜#〜] insert [〜#〜]forループ内)を実行している場合、これは非常に負荷が高くなります。各ステートメントのジャーナルファイルを再度開いて書き込み、閉じる必要があるためです。あなたは参照するかもしれません
SQLを使用できますtransactions in Androidです。複数の行をデータベースに大きなバッチで挿入してから、単一のコミットを行うことをお勧めします(SQLliteデータファイルに書き込むと非常に低速です) )挿入されたすべての行。
public void insert(List<Student> students)
{
SQLiteDatabase db = sh.getWritableDatabase();
ContentValues cv = new ContentValues();
db.beginTransaction();
try {
for (Student s : students) {
cv.put(StudentHelper.FIRSTNAME,s.getFirstName());
cv.put(StudentHelper.LASTNAME,s.getLastName());
cv.put(StudentHelper.ADDRESS,s.getAddress());
cv.put(StudentHelper.GPA,s.getGpa());
db.insertOrThrow(StudentHelper.TABLE_NAME, null, cv)
}
setTransactionSuccessful();
} finally {
db.endTransaction();
}
}
さて、あなたは非常に多くのレコードを持っていて、すべてのレコードに対してgetWritableDatabase()
を呼び出してからそれを挿入しますが、これはパフォーマンスに悪影響を及ぼします。
トランザクションを使用する必要があります。この質問を見てください Android SQLiteデータベース:挿入が遅い 。基本的には、beginTransaction()
を呼び出し、挿入を行ってから、setTransactionSuccessful()
の前にendTransaction()
を呼び出す必要があります。これでどれだけのパフォーマンス向上が得られるかがわかります。