91超碰碰碰碰久久久久久综合_超碰av人澡人澡人澡人澡人掠_国产黄大片在线观看画质优化_txt小说免费全本

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Android 優化之存儲優化的實現

發布時間:2020-09-21 20:25:30 來源:腳本之家 閱讀:152 作者:七適散人 欄目:移動開發

交換數據格式

Google 推出的 Protocal Buffers 是一種更輕便高效的存儲結構,但消耗內存較大。

FlatBuffers 同樣由 Google 推出,專注性能,適合移動端。占用存儲比 Protocal 要大。

SharePreferences 優化

  • 當 SharedPreferences 文件還沒有被加載到內存時,調用 getSharedPreferences 方法會初始化文件并讀入內存,這容易導致 耗時更長。
  • Editor 的 commit 或者 apply 方法的區別在于同步寫入和異步 寫入,以及是否需要返回值。在不需要返回值的情況下,使用 apply 方法可以極大提高性能。
  • SharedPreferences 類 中的 commitToMemory() 會鎖定 SharedPreference 對象,put() 和 getEditor() 方法會鎖定 Editor 對象,在寫入磁盤時更會鎖定一個寫入鎖。因此,最好的優化方法就是避免頻繁地讀寫 SharedPreferences,減少無謂的調用。對于 SharedPreferences 的批量操作,最好先獲取一個 editor 進行批量操作,然后調用 apply 方法。

Bitmap 解碼

  • 4.4 以上 decodeFile 內部沒有使用緩存,效率不高。要使用 decodeStream,同時傳入的文件流為 BufferedInputStream。
  • decodeResource 同樣存在性能問題,用 decodeResourceStream。

數據庫優化

1、使用 StringBuilder 代替 String

2、查詢時返回更少的結果集及更少的字段

查詢時只取需要的字段和結果集,更多的結果集會消耗更多的時間及內存,更多的字段會導致更多的內存消耗。

3、少用 cursor.getColumnIndex

根據性能調優過程中的觀察 cursor.getColumnIndex 的時間消耗跟 cursor.getInt 相差無幾。可以在建表的時候用 static 變量記住某列的 index,直接調用相應 index 而不是每次查詢。

4、異步線程

Android 中數據不多時表查詢可能耗時不多,不會導致 ANR,不過大于 100ms 時同樣會讓用戶感覺到延時和卡頓,可以放在線程中運行,但 sqlite 在并發方面存在局限,多線程控制較麻煩,這時候可使用單線程池,在任務中執行 db 操作,通過 handler 返回結果和 UI 線程交互,既不會影響 UI 線程,同時也能防止并發帶來的異常。

5、SQLiteOpenHelper 維持一個單例

因為 SQLite 對多線程的支持并不是很完善,如果兩個線程同時操作數據庫,因為數據庫被另一個線程占用, 這種情況下會報“Database is locked” 的異常。所以在數據庫管理類中使用單例模式,就可以保證無論在哪個線程中獲取數據庫對象,都是同一個。

最好的方法是所有的數據庫操作統一到同一個線程隊列管理,而業務層使用緩存同步,這樣可以完全避免多線程操作數據庫導致的不同步和死鎖問題。

6、Application 中初始化

  • 使用 Application 的 Context 創建數據庫,在 Application 生命周期結束時再關閉。
  • 在應用啟動過程中最先初始化完數據庫,避免進入應用后再初始化導致相關操作時間變長。

7、少用 AUTOINCREMENT

主鍵加上 AUTOINCREMENT 后,可以保證主鍵嚴格遞增,但并不能保證每次都加 1,因為在插入失敗后,失敗的行號不會被復用,會造成主鍵有間隔,繼而使 INSERT 耗時 1 倍以上。

這個 AUTOINCREMENT 關鍵詞會增加 CPU,內存,磁盤空間和磁盤 I/O 的負擔,所以 盡量不要用,除非必需。通常情況下都不是必需的。

事務

使用事務的兩大好處是原子提交和更優性能:

  • 原子提交:意味著同一事務內的所有修改要么都完成要么都不做,如果某個修改失敗,會自動回滾使得所有修改不生效。
  • 更優性能:Sqlite 默認會為每個插入、更新操作創建一個事務,并且在每次插入、更新后立即提交。這樣如果連續插入 100 次數據實際是創建事務、執行語句、提交這個過程被重復執行了 100 次。如果顯式的創建事務,這個過程只做一次,通過這種一次性事務可以使得性能大幅提升。尤其當數據庫位于 sd 卡時,時間上能節省兩個數量級左右。

主要三個方法:beginTransaction,setTransactionSuccessful,endTransaction。

SQLiteStatement

使用 Android 系統提供的 SQLiteStatement 來插入數據,在性能上有一定的提高,并且也解決了 SQL 注入的問題。

SQLiteStatement statement = dbOpenHelper.getWritableDatabase().compileStatement("INSERT INTO EMPERORS(name, dynasty, start_year) values(?,?,?)"); 
statement.clearBindings();
statement.bindString(1, "Max"); 
statement.bindString(2, "Luk"); 
statement.bindString(3, "1998"); 
statement.executeInsert();

SQLiteStatement 只能插入一個表中的數據,在插入前要清除上一次的數據。

索引

索引就像書本的目錄,目錄可以快速找到所在頁數,數據庫中索引可以幫助快速找到數據,而不用全表掃描,合適的索引可以大大提高數據庫查詢的效率。

優點:大大加快了數據庫檢索的速度,包括對單表查詢、連表查詢、分組查詢、排序查詢。經常是一到兩個數量級的性能提升,且隨著數據數量級增長。

缺點:

  • 索引的創建和維護存在消耗,索引會占用物理空間,且隨著數據量的增加而增加。
  • 在對數據庫進行增刪改時需要維護索引,所以會對增刪改的性能存在影響。

分類

1、直接創建索引和間接創建索引

  • 直接創建: 使用 sql 語句創建,Android 中可以在 SQLiteOpenHelper 的 onCreate 或是 onUpgrade 中直接 excuSql 創建語句,如 CREATE INDEX mycolumn_index ON mytable (myclumn)
  • 間接創建: 定義主鍵約束或者唯一性鍵約束,可以間接創建索引,主鍵默認為唯一索引。

2、普通索引和唯一性索引

  • 普通索引:CREATEINDEXmycolumn_indexONmytable(myclumn)
  • 唯一性索引:保證在索引列中的全部數據是唯一的,對聚簇索引和非聚簇索引都可以使用,語句為 CREATE UNIQUE COUSTERED INDEX myclumn_cindex ON mytable(mycolumn)

3、單個索引和復合索引

  • 單個索引:索引建立語句中僅包含單個字段,如上面的普通索引和唯一性索引創建示例。
  • 復合索引:又叫組合索引,在索引建立語句中同時包含多個字段,如 CREATEINDEXname_indexONusername(firstname,lastname),其中 firstname 為前導列。

4、聚簇索引和非聚簇索引 (聚集索引,群集索引)

  • 聚簇索引:物理索引,與基表的物理順序相同,數據值的順序總是按照順序排列,如 CREATE CLUSTERED INDEX mycolumn_cindex ON mytable(mycolumn) WITH ALLOW_DUP_ROW,其中 WITH ALLOW_DUP_ROW 表示允許有重復記錄的聚簇索引
  • 非聚簇索引:CREATEUNCLUSTEREDINDEXmycolumn_cindexONmytable(mycolumn),索引默認為非聚簇索引

使用場景

  • 當某字段數據更新頻率較低,查詢頻率較高,經常有范圍查詢 (>, <, =,>=, <=) order bygroup by 發生時建議使用索引。并且選擇度(一個字段中唯一值的數量 / 總的數量)越大,建索引越有優勢
  • 經常同時存取多列,且每列都含有重復值可考慮建立復合索引

使用規則

  1. 對于復合索引,把使用最頻繁的列做為前導列 (索引中第一個字段)。如果查詢時前導列不在查詢條件中則該復合索引不會被使用。如 create unique index PK_GRADE_CLASS on student (grade, class)select * from student where class = 2 未使用到索引,select * from dept where grade = 3 使用到了索引
  2. 避免對索引列進行計算,對 where 子句列的任何計算如果不能被編譯優化,都會導致查詢時索引失效 select * from student where tochar(grade)='2
  3. 比較值避免使用 NULL
  4. 多表查詢時要注意是選擇合適的表做為內表。連接條件要充份考慮帶有索引的表、行數多的表,內外表的選擇可由公式:外層表中的匹配行數 * 內層表中每一次查找的次數確定,乘積最小為最佳方案。實際多表操作在被實際執行前,查詢優化器會根據連接條件,列出幾組可能的連接方案并從中找出系統開銷最小的最佳方案
  5. 查詢列與索引列次序一致
  6. 用多表連接代替 EXISTS 子句
  7. 把過濾記錄數最多的條件放在最前面
  8. 善于使用存儲過程,它使 sql 變得更加靈活和高效 (Sqlite 不支持存儲過程)

其它通用優化

  1. 經常用的數據讀取后緩存起來,以免多次重復讀寫造成“寫入放大”
  2. 子線程讀寫數據
  3. ObjectOutputStream 在序列化磁盤時,會把內存中的每個對象保存到磁盤,在保存對象的 時候,每個數據成員會帶來一次 I/O 操作。在 ObjectOutputStream 上面再封裝一個輸出流 ByteArrayOutputStream 或 BufferedOutputStream,先將對象序列化后的信息寫到緩存區中,然后再一次性地寫到磁盤上;相應的,用 ByteArrayInputStream 或 BufferedInputStream 替代 ObjectInputStream。
  4. 合理選擇緩沖區 Buffer 的大小。太小導致 I/O 操作次數增多,太大導致申請時間變長。比如 4-8 KB。

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持億速云。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

江阴市| 锡林郭勒盟| 景东| 出国| 门源| 涿鹿县| 介休市| 双桥区| 清流县| 临城县| 洪江市| 寿阳县| 临泉县| 罗平县| 海淀区| 南平市| 太康县| 墨竹工卡县| 宁安市| 丰都县| 五家渠市| 景谷| 库尔勒市| 阿合奇县| 普陀区| 临江市| 兴安盟| 天峻县| 铜梁县| 七台河市| 兴隆县| 开阳县| 平塘县| 南通市| 祁连县| 鄢陵县| 新营市| 湛江市| 乌拉特前旗| 乌鲁木齐市| 河南省|