Android Sqlite Performance

Я делал некоторые эксперименты для измерения производительности sqlite на Android. Я немного разочаровался в результатах. То, что я сделал, это вставить 10.000 запросов в таблицу, и потребовалось 130-140 секунд, но с этими условиями ;

1. Галактика Samsung s3 в режиме энергосбережения

2. Введенные данные (или класс) имеют 3 строки и один float (real для sqlite)

3. Вставка события выполняется в asynctask.

4. В asynctask я показываю диалог прогресса с прошедшим в нем текстом таймера (System.currentTimeMillis – секунды и т. Д. 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 Fuckig 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. Я использую contentValues ​​с методом insertOrThrow в классе helperdb. ЭТО СТАРЫЙ МЕДЛЕННЫЙ КОД

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

Solutions Collecting From Web of "Android Sqlite Performance"

Используйте SQLite transaction для ускорения

Используйте BEGIN TRANSACTION & END TRANSACTION для оптимизации SQLite

По умолчанию каждый оператор SQL заключен в новый блок транзакций по времени выполнения SQLite. Если вы выполняете базовую операцию БД, такую ​​как INSERT , блок транзакций будет создан и обернут вокруг него.

Предоставление SQLite во время выполнения транзакции для вас рекомендуется только в том случае, если ваша программа выполняет только одну операцию БД в наборе данных. Однако, если вы выполняете многочисленные операции с БД (например, INSERT внутри цикла), это становится очень дорогостоящим, так как для повторного открытия, записи и закрытия файла журнала для каждого утверждения это становится очень дорогостоящим. Вы можете обратиться

  1. База данных Android SQLite: медленная вставка

  2. http://www.androidcode.ninja/android-sqlite-transaction-tutorial/

  3. http://www.techrepublic.com/blog/software-engineer/turbocharge-your-sqlite-inserts-on-android/

  4. http://www.android-app-market.com/sqlite-optimization-in-android-programming-sqlite-optimization-in-android-apps.html

Вы можете использовать транзакции SQL в 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() . Вы будете удивлены, увидев, сколько выгоды вы получите с этим.