提高數據庫併發性能概要

1 細粒度鎖表

  1. 減少大事物操作 (一個包含很多SQL語句、牽涉很多表的大事物操作鎖住的資源也會多);
  2. 儘量不使用表級排他鎖,而是用行級鎖;又因爲鎖一般是由數據庫根據你的 SQL自動分配,所以要注意SQL的寫法。比如
    select * into B from A

    該操作會創建B表,並對B表加表鎖。

2 拆表

與降低鎖的粒度異曲同工。

2.1 物理拆分方式

  1. 水平拆分: 把不同行記錄分開放進不同表中。比如男性放入一張表中,女性放入另一張表。
  2. 垂直拆分: 把不同列分別放入不同表中。比如主用戶信息放入一張表,附加信息放入另一張表。
  3. 混合拆分(水平拆分+垂直拆分)

2.2 邏輯拆分方式

  1. 按範圍拆分,比如所有zipcode列的值 between 70000 and 79999的記錄拆成一個表.
  2. 分組拆分,比如country列爲冰島、挪威、瑞典、丹麥這些北歐國家的記錄拆成一個表
  3. 哈希拆分:參見數據庫的哈希設計:http://hi.baidu.com/dapplehou/blog/item/471a277ff8eafc0529388ac4.html
  4. 混合拆分,以上幾種拆分方式的綜合。
  5. 可建立查找表以方便對拆分的子表進行登記、查詢、定位。

3 多數據源(多庫)

本質是拆庫。與拆表異曲同工。數據庫路由(定位),對於程序員來說就是數據源路由(查找、定位),需要定義多個數據源,並採取合適算法進行定位。可參考 http://hi.baidu.com/dapplehou/blog/item/6ba8034f5114e038aec3abdb.html 多庫部分.

什麼是合適算法?那要根據庫的切分方式、性能需要以及業務需要來定奪。

4 樂觀鎖

可以降低數據庫長事物。只在提交的那一剎那判斷自己提交的數據是否已經被別人修改過了,如是,則認爲自己要提交的數據是過期數據,取消提交,否則,提交成功。避免長事物帶來的等待。通常採用版本號來判斷是否過期數據。過程如下:

  1. A、B兩人同時讀取同一條銀行賬戶記錄,記錄版本號爲1。
  2. A修改此記錄:增加100元,版本號加1。
  3. B修改此記錄:減少50元,版本號加1。
  4. A提交。假設提交SQL如下:
    update account set money=money+50,version=version+1 where id=10 and version=1

    提交成功。id=10的這條記錄version爲2.

  5. B提交。提交SQL如下:
    update account set money=money-50,version=version+1 where id=10 and version=1

    因爲version已經等於2了,所以這條更新語句會影響0行。這樣,誰先提交,誰成功。後來者的不會因爲先到者讀取後遲遲不提交而等待等待。減少了站着茅坑不拉屎的情況。提高了併發性能。

5 臨時表

使用局部臨時表提高併發性能。局部臨時表特點是多用戶操作互不干擾。一個局部臨時表只對一個session可見、有效。多用戶併發實際是各操作各自的臨時表,不會產生數據表鎖的問題。提高併發效率。

SQL Server創建臨時表語句:

CREATE TABLE #MyTempTable (cola INT PRIMARY KEY)

Oracle:

CREATE GLOBAL TEMPORARY TABLE MyTempTable

把主表(頻繁使用又數據量大)中的部分數據放入局部臨時表,然後在臨時表裏進行計算、統計等工作,然後同步到主表中去(同步過程可用樂觀鎖機制),減少了主表在併發時鎖等待的開銷。

臨時表性能提升原理和拆分表原理相同:通過把一個大集合拆成小集合,然後在小集合上進行計算。

6 緩存

  1. 原理同臨時表。先在內存裏折騰(計算、update等),然後把折騰的結果一次性的同步給db(同步過程可使用樂觀鎖機制).
  2. 算法優化。

    有的操作,雖然沒有更新過程,但頻繁的複雜查詢也會使數據庫性能降低。這種情況下,可採取把一些查詢後的結果且不輕易變的數據保存在緩存中供後續使用。

    例如:不同用戶登錄後的菜單顯示可能要根據不同部門、不同權限以及委託、兼職等複雜邏輯來確定菜單的顯示項,數據庫的查詢可能非常消耗性能,這種情況下,可緩存所有菜單形成菜單池,再採用亨元模式,緩存每個用戶的可見菜單,這樣減少了數據庫查詢次數,避免了顯示菜單時每次都要查詢數據庫的性能損耗。

    亨元模式可參見:http://hi.baidu.com/dapplehou/blog/item/aeca1d958268e1047bf48089.html

7 數據庫集羣

與多庫(拆庫)區別: 集羣是每個庫上都有一份相同的數據;拆庫是每個庫只有全集的部分數據。

多數據庫冗餘可以減少單個數據庫的負載,總體上提高了性能。它有3個技術關鍵點:

  1. 數據庫查詢路由
  2. 數據庫同步
  3. 負載均衡算法

8 讀寫分離策略

在讀操作遠多於寫操作的大型應用中,可採用讀寫分離策略。用來讀的數據庫叫從數據庫,用來寫或者事務性查詢的叫主數據庫。主數據庫的數據變化會通過某些策略(比如數據庫複製)同步到從數據庫,從而保證主從數據庫數據一致性。其本質是空間換時間,即:通過增加數據庫冗餘,降低數據庫對鎖的複雜調度。但另一方面,增加了應用架構的複雜度 (這種複雜性可以通過使用第三方中間件來降低)。

9 SQL優化

SQL語句是數據庫資源消耗的主要來源,它往往都是可以進一步優化的,SQL優化在時間成本和風險上代價低。

我們寫的SQL語句都會被查詢優化器自動優化,它的優化原則是這樣的:

1. 選擇運算優先運行。(即優先通過條件過濾記錄集)
2. 投影運算與選擇運算同時進行。
3. 將笛卡爾積與隨後的選擇運算合併爲連接運算
4. 投影運算與其他運算同時進行
5. 尋找公共子表達式並將結果加以存儲
6. 對文件進行預處理

由於有了以上優化,所以下面兩種SQL的寫法效率一樣

select * from A,B where A.id=B.id and A.name='Jake'
select * from A,B were A.name='Jake' and A.id=B.id

隨着數據庫的進化,原來效率低的語句現在不一定低,需要實際測試。

10 正確使用索引

  1. 索引列
    1. 經常查詢的列
    2. 經常排序的列
    3. 經常連接的列
  2. 非索引列
    1. 不經常使用的列
    2. 重複記錄太多的列(比如性別)
    3. Image text類型的列
發佈了35 篇原創文章 · 獲贊 2 · 訪問量 22萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章