效能最佳化之資料庫最佳化,效能最佳化資料庫

來源:互聯網
上載者:User

效能最佳化之資料庫最佳化,效能最佳化資料庫

本文效能最佳化之資料庫最佳化,原理適用於大部分資料庫包括Sqlite、Mysql、Oracle、Sql server,詳細介紹了索引(優缺點、分類、情境、規則)和事務,最後介紹了部分單獨針對Sqlite的最佳化。

1、索引

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

(1). 優點

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

(2). 缺點

索引的建立和維護存在消耗,索引會佔用物理空間,且隨著資料量的增加而增加。
在對資料庫進行增刪改時需要維護索引,所以會對增刪改的效能存在影響。

(3). 分類

a. 直接建立索引和間接建立索引

直接建立: 使用sql語句建立,Android中可以在SQLiteOpenHelper的onCreate或是onUpgrade中直接excuSql建立語句,語句如

1 CREATE INDEX mycolumn_index ON mytable (myclumn)

間接建立: 定義主鍵約束或者唯一性鍵約束,可以間接建立索引,主鍵預設為唯一索引。

b. 普通索引和唯一性索引

普通索引:

1 CREATE INDEX mycolumn_index ON mytable (myclumn)

唯一性索引:保證在索引列中的全部資料是唯一的,對聚簇索引和非聚簇索引都可以使用,語句為

1 CREATE UNIQUE COUSTERED INDEX myclumn_cindex ON mytable(mycolumn)

c. 單個索引和複合索引

單個索引:索引建立語句中僅包含單個欄位,如上面的普通索引和唯一性索引建立樣本。
複合索引:又叫複合式索引,在索引建立語句中同時包含多個欄位,語句如:

1 CREATE INDEX name_index ON username(firstname, lastname)

其中firstname為前置列。

d. 聚簇索引和非聚簇索引(叢集索引,群集索引)

聚簇索引:物理索引,與基表的物理順序相同,資料值的順序總是按照順序排列,語句為:

1 CREATE CLUSTERED INDEX mycolumn_cindex ON mytable(mycolumn) WITH ALLOW_DUP_ROW

其中WITH ALLOW_DUP_ROW表示允許有重複記錄的聚簇索引

非聚簇索引:

1 CREATE UNCLUSTERED INDEX mycolumn_cindex ON mytable(mycolumn)

索引預設為非聚簇索引

(4). 使用情境

在上面講到了優缺點,那麼肯定會對何時使用索引既有點明白又有點糊塗吧,那麼下面總結下:

a.  當某欄位資料更新頻率較低,查詢頻率較高,經常有範圍查詢(>, <, =, >=, <=)或order by、group by發生時建議使用索引。並且選擇度越大,建索引越有優勢,這裡選擇度指一個欄位中唯一值的數量/總的數量。

b.  經常同時存取多列,且每列都含有重複值可考慮建立複合索引

(5). 索引使用規則

a.  對於複合索引,把使用最頻繁的列做為前置列(索引中第一個欄位)。如果查詢時前置列不在查詢條件中則該複合索引不會被使用。

如create unique index PK_GRADE_CLASS on student (grade, class)

select * from student where class = 2未使用到索引

select * from dept where grade = 3使用到了索引

b.  避免對索引列進行計算,對where子句列的任何計算如果不能被編譯最佳化,都會導致查詢時索引失效

select * from student where tochar(grade)=’2′

c.  比較值避免使用NULL

d.  多表查詢時要注意是選擇合適的表做為內表。串連條件要充份考慮帶有索引的表、行數多的表,內外表的選擇可由公式:外層表中的匹配行數*內層表中每一次尋找的次數確定,乘積最小為最佳方案。實際多表操作在被實際執行前,查詢最佳化工具會根據串連條件,列出幾組可能的串連方案並從中找出系統開銷最小的最佳方案。

e.  查詢列與索引列次序一致

f.  用多表串連代替EXISTS子句

g.  把過濾記錄數最多的條件放在最前面

h.  善於使用預存程序,它使sql變得更加靈活和高效(Sqlite不支援預存程序::>_<:: )

(6)索引檢驗

建立了索引,對於某條sql語句是否使用到了索引可以通過執行計畫查看是否用到了索引。

2、使用事務

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

(1) 原子提交

原則提交意味著同一事務內的所有修改要麼都完成要麼都不做,如果某個修改失敗,會自動復原使得所有修改不生效。

(2) 更優效能

Sqlite預設會為每個插入、更新操作建立一個事務,並且在每次插入、更新後立即提交。

這樣如果連續插入100次資料實際是建立事務->執行語句->提交這個過程被重複執行了100次。如果我們顯示的建立事務->執行100條語句->提交會使得這個建立事務和提交這個過程只做一次,通過這種一次性事務可以使得效能大幅提升。尤其當資料庫位於sd卡時,時間上能節省兩個數量級左右。

Sqlte顯示使用事務,範例程式碼如下:

public void insertWithOneTransaction() {     SQLiteDatabase db = sqliteOpenHelper.getWritableDatabase();     // Begins a transaction     db.beginTransaction();     try {         // your sqls         for (int i = 0; i < 100; i++) {              db.insert(yourTableName, null, value);         }          // marks the current transaction as successful         db.setTransactionSuccessful();     } catch (Exception e) {         // process it         e.printStackTrace();     } finally {         // end a transaction         db.endTransaction();     }}

其中sqliteOpenHelper.getWritableDatabase()表示得到寫表許可權。

3、其他針對Sqlite的最佳化

(1) 語句的拼接使用StringBuilder代替String

這個就不多說了,簡單的string相加會導致建立多個臨時對象消耗效能。StringBuilder的空間預分配效能好得多。如果你對字串的長度有大致瞭解,如100字元左右,可以直接new StringBuilder(128)指定初始大小,減少空間不夠時的再次分配。

(2) 查詢時返回更少的結果集及更少的欄位。

查詢時只取需要的欄位和結果集,更多的結果集會消耗更多的時間及記憶體,更多的欄位會導致更多的記憶體消耗。

(3) 少用cursor.getColumnIndex

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

public static final String HTTP_RESPONSE_TABLE_ID = android.provider.BaseColumns._ID;public static final String HTTP_RESPONSE_TABLE_RESPONSE = "response";public List<Object> getData() {      ……      cursor.getString(cursor.getColumnIndex(HTTP_RESPONSE_TABLE_RESPONSE));      ……}

最佳化為

public static final String HTTP_RESPONSE_TABLE_ID = android.provider.BaseColumns._ID;public static final String HTTP_RESPONSE_TABLE_RESPONSE = "response";public static final int HTTP_RESPONSE_TABLE_ID_INDEX = 0;public static final int HTTP_RESPONSE_TABLE_URL_INDEX = 1;public List<Object> getData() {     ……     cursor.getString(HTTP_RESPONSE_TABLE_RESPONSE_INDEX);     ……}

4、非同步線程

Sqlite是常用於嵌入式開發中的關係型資料庫,完全開源。

與Web常用的資料庫Mysql、Oracle db、sql server不同,Sqlite是一個內嵌式的資料庫,資料庫伺服器就在你的程式中,無需網路設定和管理,資料庫伺服器端和用戶端運行在同一進程內,減少了網路訪問的消耗,簡化了資料庫管理。不過Sqlite在並發、資料庫大小、網路方面存在局限性,並且為表級鎖,所以也沒必要多線程操作。

Android中資料不多時表查詢可能耗時不多,不會導致anr,不過大於100ms時同樣會讓使用者感覺到延時和卡頓,可以放線上程中運行,但sqlite在並發方面存在局限,多線程式控制制較麻煩,這時候可使用單線程池,在任務中執行db操作,通過handler返回結果和ui線程互動,既不會影響UI線程,同時也能防止並髮帶來的異常。關於效能的最佳化,還要知道怎麼樣去採取措施保護原始碼,這點可諮詢移動資訊安全智慧型服務供應商——愛加密,加密技術!

可使用Android提供的AsyncQueryHandler或類似如下程式碼完成:

ExecutorService singleThreadExecutor = Executors.newSingleThreadExecutor();singleThreadExecutor.execute(new Runnable() {     @Override     public void run() {         // db operetions, u can use handler to send message after         db.insert(yourTableName, null, value);         handler.sendEmptyMessage(xx);     }});

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.