簡體   English   中英

SQLite-在Android應用中加快4,000行插入

[英]SQLite - Speed up 4,000 row insert in Android app

public synchronized void updateStop(ArrayList<StopBean> beanList){
    SQLiteDatabase db = getWritableDatabase();
    String query = "DELETE FROM 'stop'";
    db.execSQL(query);
    for(StopBean bean : beanList){
        String atco_code = bean.getAtco_code();
        String name = bean.getName();
        String locality = bean.getLocality();
        String bearing = bean.getBearing();
        String latitude = bean.getLatitude()+"";
        String longitude = bean.getLongitude()+"";

        ContentValues values = new ContentValues();
        values.put("atco_code", atco_code);
        values.put("name", name);
        values.put("locality", locality);
        values.put("bearing", bearing);
        values.put("latitude", latitude);
        values.put("longitude", longitude);
        db.insert("stop", null, values);
    }

    db.close();
}

當前,我們的應用程序通過上述方法插入了4,000行。 這種方法的問題在於實際執行需要10到15秒。 顯然,對於簡單的4,000行插入來說,這太長了。

如何更改此方法,以便大大加快這些插入的執行時間?

使用beginTransaction()endTransaction()markTransactionAsSuccessful()在事務中包裝整個內容。 現在,您每個插入執行一次事務,這意味着每個插入一個磁盤I / O脈沖,這將非常慢。

除此之外:

  • 不要在循環的每個遍歷中分配新的ContentValues

  • 如果沒有優化掉局部變量(例如atco_code

  • 使用比“”更有效的方式將數字轉換為字符串(例如, Double.toString()

  • 實驗用編譯普通的SQL INSERT語句來SQLiteStatement 通過compileStatement()看看是否比只調用更好地insert()

如果您仍然不滿意,請使用Traceview並確定將剩余時間花在哪里。

最新版本的sqlite中根據模擬器 ,它們是Kit Kat,Jelly Bean和Lollipop),您可以使用多插入語句:

INSERT INTO table (col1, col2) VALUES 
  ('row1col1', 'row1col2'), ('row2col1', 'row2col2');

如果您要導入靜態可信數據,請在應用程序的文件中包含sqlite腳本和數據,並在首次啟動時運行它。 注意:切勿將SQL值連接到SQL查詢中,因為這將使您可以進行數據庫注入(並且這樣做不會更快,因為您和sqlite會兩次解析數據並進行不必要的重新序列化)。

如果需要插入動態生成的數據,或者需要支持較舊的版本,則應使用准備好的語句對SQL查詢進行預編譯,並使用綁定變量。 例:

db.beginTransaction();
String sql = "INSERT INTO stop(atco_code, name, locality, bearing, latitude, longitude) VALUES (?,?,?,?,?,?)";
SQLiteStatement stmt = db.compileStatement(sql);

for(StopBean stop : stopList){
    stmt.bindString(1, stop.getAtco_code());
    stmt.bindString(2, stop.getName());
    stmt.bindString(3, stop.getLocality();
    stmt.bindString(4, stop.getBearing());
    stmt.bindDouble(5, stop.getLatitude());
    stmt.bindDouble(6, stop.getLongitude());

    stmt.execute();
    stmt.clearBindings();
}

db.setTransactionSuccessful();
db.endTransaction();

在所有情況下,都應將所有插入物包裝在一個事務中。 使用單個事務允許數據庫將值緩存在快速RAM中,並且僅在緩存已滿或完成時才刷新數據,而不是為每個插入語句將數據刷新到持久性存儲中。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM