Sqlite 操作優(yōu)化

在寫(xiě)項(xiàng)目的時(shí)候會(huì)經(jīng)常接觸 Sqlite ,比如說(shuō)寫(xiě)課程表相關(guān)的東西,雖然數(shù)據(jù)不是很多,但是還是可以感覺(jué)到短暫的卡頓,所以想著通過(guò)一些方法來(lái)提高 Sqlite 的速度。

使用事務(wù)

引用別人博客里面的話(huà)

在Android中,無(wú)論是使用SQLiteDatabase的insert,delete等方法還是execSQL都開(kāi)啟了事務(wù),來(lái)確保每一次操作都具有原子性,使得結(jié)果要么是操作之后的正確結(jié)果,要么是操作之前的結(jié)果。

然而事務(wù)的實(shí)現(xiàn)是依賴(lài)于名為rollback journal文件,借助這個(gè)臨時(shí)文件來(lái)完成原子操作和回滾功能。既然屬于文件,就符合Unix的文件范型(Open-Read/Write-Close),因而對(duì)于批量的修改操作會(huì)出現(xiàn)反復(fù)打開(kāi)文件讀寫(xiě)再關(guān)閉的操作。然而好在,我們可以顯式使用事務(wù),將批量的數(shù)據(jù)庫(kù)更新帶來(lái)的journal文件打開(kāi)關(guān)閉降低到1次。

別人的博客里面其實(shí)說(shuō)的已經(jīng)很清楚了,但是最為影響數(shù)據(jù)庫(kù)時(shí)間效率的是反復(fù)操作 journal 文件,所以如果我們手動(dòng)控制事務(wù)的開(kāi)啟和關(guān)閉,就可以減少 journal 文件的開(kāi)啟和關(guān)閉到一次。

實(shí)例代碼如下

public void insertWithTransaction() {

        long startTime = System.currentTimeMillis();

        try{
            db.beginTransaction();

            ContentValues contentValues = new ContentValues();

            for (UserBean userBean: userBeanList) {

                contentValues.put(TestDBSchema.UserTable.Cols.ID, userBean.getId());
                contentValues.put(TestDBSchema.UserTable.Cols.NAME, userBean.getName());
                contentValues.put(TestDBSchema.UserTable.Cols.GENDER, userBean.getGender());
                contentValues.put(TestDBSchema.UserTable.Cols.AGE, userBean.getAge());
                contentValues.put(TestDBSchema.UserTable.Cols.PHONE, userBean.getPhone());
                contentValues.put(TestDBSchema.UserTable.Cols.REGION, userBean.getRegion());

                db.insert(TestDBSchema.UserTable.NAME, null, contentValues);

            }

            db.setTransactionSuccessful();
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            db.endTransaction();
        }

        long endTime = System.currentTimeMillis();

        long cost = endTime - startTime;

        transactionTextView.setText("" + cost);

    }

重用 SQLiteStatement

在網(wǎng)上查找這方面的資料,介紹使用 SQLiteStatement 減少 SQL 語(yǔ)句的編譯次數(shù),從而提高效率。比如說(shuō)我們平時(shí)插入數(shù)據(jù)的時(shí)候會(huì)在循環(huán)中反復(fù)調(diào)用 execSQL 這個(gè)函數(shù),這樣只要循環(huán)多少遍,就會(huì)將 SQL 語(yǔ)句編譯多少遍,使用
SQLiteStatement 可以將這個(gè)的次數(shù)有效的減為一次。當(dāng)然也要搭配上面介紹的事務(wù)。

實(shí)例代碼如下所示

public void insertWithStatement() {

        long startTime = System.currentTimeMillis();

        SQLiteStatement statement = db.compileStatement(SQL_STATEMENT);

        try {
            db.beginTransaction();
            for (UserBean userBean: userBeanList) {

                statement.clearBindings();

                statement.bindLong(1, userBean.getId());
                statement.bindString(2, userBean.getName());
                statement.bindString(3, userBean.getGender());
                statement.bindLong(4, userBean.getAge());
                statement.bindString(5, userBean.getPhone());
                statement.bindString(6, userBean.getRegion());

                statement.executeInsert();

            }

            db.setTransactionSuccessful();
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            db.endTransaction();
        }

        long endTime = System.currentTimeMillis();

        long cost = endTime - startTime;

        statementTextView.setText("" + cost);

    }

時(shí)間效率的介紹

image.png

從效果圖可以看出,相比沒(méi)有自己手動(dòng)開(kāi)啟事務(wù)相比,手動(dòng)控制開(kāi)啟事務(wù)效率真的高太多了,接著如果你是用了 SQLiteStatement ,效率又會(huì)有小幅的提升,最后附上我的實(shí)例代碼

其它的優(yōu)化技巧

通過(guò)索引提高查詢(xún)的速度

就像以前查字典的時(shí)候會(huì)查找拼音索引,簡(jiǎn)單的就是針對(duì)表里面的一列或者兩列創(chuàng)建一個(gè)目錄一樣的東西(貌似形容的有點(diǎn)不準(zhǔn)確),當(dāng)我們使用 select 語(yǔ)句查詢(xún)的時(shí)候就可以在這個(gè)目錄里面查,不用管其它的幾列,效率自然提升。這里用 SQLite 代碼簡(jiǎn)單的舉個(gè)例子就可以了。

這里借用菜鳥(niǎo)教程里面的例子,假設(shè)有表 COMPANY,我們將創(chuàng)建一個(gè)索引,并用它進(jìn)行 INDEXED BY 操作。

創(chuàng)建索引

CREATE INDEX salary_index ON COMPANY(salary);

依靠索引查詢(xún)

SELECT * FROM COMPANY INDEXED BY salary_index WHERE salary > 5000;

索引的缺點(diǎn)

  • 對(duì)于增加,更新和刪除來(lái)說(shuō),使用了索引會(huì)變慢,這也很好想到,你在刪除表里面的數(shù)據(jù)的時(shí)候要順帶刪除相應(yīng)的索引。
  • 建立索引會(huì)增加數(shù)據(jù)庫(kù)的大小。
  • 為數(shù)據(jù)量比較小的表建立索引,往往會(huì)事倍功半。

在線(xiàn)程里面處理

數(shù)據(jù)庫(kù)屬于本地 IO ,也是比較耗時(shí)的,可能會(huì)引發(fā) ANR , 所以如果數(shù)據(jù)量十分大的情況下可以在異步處理,可以考慮使用單線(xiàn)程+任務(wù)隊(duì)列的形式的 HandlerThread 來(lái)實(shí)現(xiàn)。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀(guān)點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容