Android SQlite效能優化

2021-07-09 13:17:29 字數 3366 閱讀 1500

dec 13th, 2015

資料庫是應用開發中常用的技術,在android應用中也不例外。android預設使用了sqlite資料庫,在應用程式開發中,我們使用最多的無外乎增刪改查。縱使操作簡單,也有可能出現查詢資料緩慢,插入資料耗時等情況,如果出現了這種問題,我們就需要考慮對資料庫操作進行優化了。本文將介紹一些實用的資料庫優化操作,希望可以幫助大家更好地在開發過程中使用資料庫。

很多時候,我們都聽說,想要查詢快速就建立索引。這句話沒錯,資料表的索引類似於字典中的拼音索引或者部首索引。

重溫一下我們小時候查字典的過程:

沒錯,索引做的事情就是這麼簡單,使得我們不需要查詢整個資料表就可以實現快速訪問。

建立索引的基本語法如下

1

create index index_name on table_name;

建立單列索引

1

create index index_name on table_name (column_name);

毋庸置疑,索引加速了我們檢索資料表的速度。然而正如西方諺語 「there are two sides of a coin」,索引亦有缺點:

所以使用索引需要考慮實際情況進行利弊權衡,對於查詢操作量級較大,業務對要求查詢要求較高的,還是推薦使用索引的。

sqlite想要執行操作,需要將程式中的sql語句編譯成對應的sqlitestatement,比如select * from record這一句,被執行100次就需要編譯100次。對於批量處理插入或者更新的操作,我們可以使用顯式編譯來做到重用sqlitestatement。

想要做到重用sqlitestatement也比較簡單,基本如下:

請參考如下簡單的使用**

123

4567

891011

private

void

insertwithprecompiledstatement

(sqlitedatabasedb)

}

在android中,無論是使用sqlitedatabase的insert,delete等方法還是execsql都開啟了事務,來確保每一次操作都具有原子性,使得結果要麼是操作之後的正確結果,要麼是操作之前的結果。

然而事務的實現是依賴於名為rollback journal檔案,借助這個臨時檔案來完成原子操作和回滾功能。既然屬於檔案,就符合unix的檔案范型(open-read/write-close),因而對於批量的修改操作會出現反覆開啟檔案讀寫再關閉的操作。然而好在,我們可以顯式使用事務,將批量的資料庫更新帶來的journal檔案開啟關閉降低到1次。

具體的實現**如下:

123

4567

891011

1213

1415

16

private

void

insertwithtransaction

(sqlitedatabasedb)

db.settransactionsuccessful

();}

catch

(exceptione)

finally

}

上面的**中,如果沒有異常丟擲,我們則認為事務成功,呼叫db.settransactionsuccessful();確保操作真實生效。如果在此過程中出現異常,則批量資料一條也不會插入現有的表中。

對於查詢的優化,除了建立索引以外,有以下幾點微優化的建議

通常情況下,我們處於自己省時省力的目的,對於查詢使用類似這樣的**

1

23

private

void

badquery

(sqlitedatabasedb)

其中上面方法的第二個引數型別為string,意思是返回結果參考的colum資訊,傳遞null表明需要獲取全部的column資料。這裡建議大家傳遞真實需要的字串資料物件表明需要的列資訊,這樣做效率會有所提公升。

當我們需要遍歷cursor時,我們通常的做法是這樣

123

456

private

void

badquerywithloop

(sqlitedatabasedb)

,null

,null

,null

,null

,null);

while

(cursor

.movetonext

())}

但是如果我們將獲取columnindex的操作提到迴圈之外,效果會更好一些,修改後的**如下:

123

4567

8

private

void

goodquerywithloop

(sqlitedatabasedb)

,null

,null

,null

,null

,null);

intinserttimecolumnindex

=cursor

.getcolumnindex

(tabledefine

.column_insert_time

);while

(cursor

.movetonext

())cursor

.close

();}

sqlitedatabase提供了方便的contentvalues簡化了我們處理列名與值的對映,contentvalues內部採用了hashmap來儲存key-value資料,contentvalues的初始容量是8,如果當新增的資料超過8之前,則會進行雙倍擴容操作,因此建議對contentvalues填入的內容進行估量,設定合理的初始化容量,減少不必要的內部擴容操作。

使用資料庫,比較常見的就是忘記關閉cursor。關於如何發現未關閉的cursor,我們可以使用strictmode,詳細請戳這裡android效能調優利器strictmode

資料庫的操作,屬於本地io,通常比較耗時,如果處理不好,很容易導致anr,因此建議將這些耗時操作放入非同步執行緒中處理,這裡推薦乙個單執行緒 + 任務佇列形式處理的handlerthread實現非同步化。

示例原始碼,存放在github,位址為androidsqlitetuningdemo

android sqlite基本操作

package com.xiangqiao.sqlite3 import android.content.contentvalues import android.database.cursor import android.database.sqlite.sqlitedatabase import...

關於Android SQLite詳細

一 sqlite簡介 在android平台上,整合了乙個嵌入式關係型資料庫 sqlite,sqlite3支援 null integer real 浮點數字 text 字串文字 和blob 二進位制物件 資料型別,雖然它支援的型別雖然只有五種,但實際上sqlite3也接受varchar n char ...

android SQLite疑點分析

當我們從乙個資料來源去查詢資料會用到下面的查詢方法,db.query db.rawquery db.exesql 這些方法的構造引數都不一樣,甚至有的方法還是多型的,這裡不對每個方法的多型做具體說明,只是簡單的說一下這些方法的區別是什麼 db.query 首先這是個查詢資料的,返回游標,游標裡面包含...