【发布时间】:2015-01-28 09:00:36
【问题描述】:
我一直在做一些实验来测量 android 上的 sqlite 性能。我对结果有点失望。我所做的是向表中插入 10.000 个查询,花了 130-140 秒 但在这些条件下;
1.三星galaxy s3处于省电模式
2. 插入的数据(或类)有 3 个字符串和 1 个浮点数(对于 sqlite 是实数)
3. 正在异步任务中完成插入事件。
4. 在 asynctask 中,我正在显示一个进度对话框,其中包含传递的计时器文本(System.currentTimeMillis - seconds etc blala)
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 类中使用 contentValues 和 insertOrThrow 方法。 这是旧的慢代码
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.这个任务在activity的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;
}
【问题讨论】:
-
我看不到
endTransaction或setTransactionSuccessful如果您只是在您的beginTransaction方法中添加了insert,那么您错过了整个重点。 -
@M-WaJeEh 你是对的。我编辑了我的帖子。感谢您的建设性批评!
-
不,还是错了。你必须先做
beginTransaction,然后是 10.000 次插入,然后是setTransactionSuccessful,然后是endTransaction。修改您的AddStudentsTask以使其正常工作。 -
我明白了,是的,您是说我要重新打开 10k 次以进行插入。我明白了,谢谢=)。我为未来的问题爱好者编辑了帖子,让他们对使用有所了解。
-
是的,这个很完美。
标签: android android-asynctask android-sqlite