論execSQL與executeInsert執行效率之差
阿新 • • 發佈:2019-01-10
看到一遍關於SQLiteDatabase 的execSQL方法和SQLiteStatement的executeInsert的執行效率之比。文中最終得出結論後者比前者效率高,帶著疑惑的心態讓驗證了一把卻得出了截然相反的結論。無論在資料量大小或則是否開啟事務操作上SQLiteDatabase 的execSQL的執行效率還是要比SQLiteStatement的executeInsert高。
以下就是我所做的一個驗證過程
新建一個數據庫和test表
使用SQLiteDatabase 的execSQL方法和SQLiteStatement的executeInsert方法進入插入, 比較執行所需要的時間:public class DBhelper extends SQLiteOpenHelper { private static final String DATABAS_NAME = "testdb"; private static final int DATABAS_VERSION = 1; public DBhelper(Context context) { super(context, DATABAS_NAME, null, DATABAS_VERSION); } @Override public void onCreate(SQLiteDatabase db) { StringBuffer sql =new StringBuffer(); sql.append("create table test"); sql.append("(_id int PRIMARY KEY,name varchar,gender int,age int,phoneNumber varchar,address varchar)"); db.execSQL(sql.toString()); } @Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { } }
public class Dao { private DBhelper dbHelper; private SQLiteDatabase db; private StringBuffer sql_insert; private List<Tester> testers; public Dao(Context context) { this.dbHelper = new DBhelper(context); this.db = dbHelper.getWritableDatabase(); sql_insert = new StringBuffer(); sql_insert .append("INSERT INTO test(name,gender,age,phoneNumber,address) "); sql_insert.append(" VALUES( ?, ?, ?, ?, ?)"); testers = new ArrayList<Tester>(); // 測試資料 for (int i = 0; i < 1000; i++) { Tester tester = new Tester(); tester.setId(i); tester.setName("name" + i); tester.setGender(0); tester.setAge(123); tester.setPhoneNumber("123456789"); tester.setAddress("zhejiang ningbo ." + i); testers.add(tester); } } /** * 使用SQLiteDatabase 的execSQL方法插入資料 */ public long insertexecSQL() { long start = System.currentTimeMillis(); db.beginTransaction(); try { for (Tester tester : testers) { Object[] bindArgs = { tester.getName(), tester.getGender(), tester.getAge(), tester.getPhoneNumber(), tester.getAddress() }; db.execSQL(sql_insert.toString(), bindArgs); } db.setTransactionSuccessful(); } catch (SQLException e) { }finally{ db.endTransaction(); } long end = System.currentTimeMillis(); return end - start; } /** * 使用SQLiteStatement的executeInsert方法插入資料 */ public long insertStatement() { long start = System.currentTimeMillis(); db.beginTransaction(); try { for (Tester tester : testers) { SQLiteStatement statement = db.compileStatement(sql_insert .toString()); statement.bindString(1, tester.getName()); statement.bindLong(2, tester.getGender()); statement.bindLong(3, tester.getAge()); statement.bindString(4, tester.getPhoneNumber()); statement.bindString(5, tester.getAddress()); statement.executeInsert(); } db.setTransactionSuccessful(); } catch (SQLException e) { }finally{ db.endTransaction(); } long end = System.currentTimeMillis(); return end - start; } }
兩個按鈕,分別呼叫不同的插入方法, 並將執行所需的時間顯示在Button上
public class MainActivity extends Activity { private Button btn1; private Button btn2; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); final Dao dao = new Dao(MainActivity.this); btn1 = (Button) findViewById(R.id.button1); btn2 = (Button) findViewById(R.id.button2); btn1.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { btn1.setText(String.valueOf(dao.insertexecSQL())); } }); btn2.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { btn2.setText(String.valueOf(dao.insertStatement())); } }); } }
通過幾次比較發現,在實際實驗後得出的資料是SQLiteStatement的executeInsert並沒有使用SQLiteDatabase 的execSQL方法快,以下為其中一次的秒數截圖,上面按鈕顯示呼叫的方法為SQLiteDatabase 的execSQL,下面按鈕則是SQLiteStatement的executeInsert。
迴圈插入100條資料
迴圈插入1000條資料後
在使用事務迴圈插入1000條資料後
從上面的資料可以看出,隨著資料量的增大,SQLiteDatabase 的execSQL的執行效率遠比SQLiteStatement的executeInsert高,差距非常大。
同時在對其開啟事務後,執行效率也大幅提高,只逼迴圈插入100條資料所需的時間。
db.beginTransaction();
db.setTransactionSuccessful();
db.endTransaction();
以上操做在測試時均未使用非同步類或開啟新執行緒,在插入1000條資料時候,出現非常長的停頓現象,隨著資料量的逐步增加非常容易直接停止響應。
所以建議,在進行大資料操作時候,使用非同步或開啟新執行緒的同時也有必要對其開啟事務。