1. 程式人生 > >資料庫分割槽分表以及讀寫分離

資料庫分割槽分表以及讀寫分離

資料庫結構的優化有多種方法,主要的有兩種:

一是利用儲存過程來代替常用的SQL查詢語句,減少sql語句解析編譯的過程。

     另一種是使用資料庫管理系統中的分割槽表方法進。使用儲存過程的優化方法有執行速度快的優點,但是其本身不利於除錯、沒有辦法使用資料庫快取機制等缺點,所以在系統安全性和效能要求更高的情況下,建議使用分割槽表的方法。但要注意:並不是只要資料量夠多就需要通過資料庫分割槽表來提高查詢效率,而是要在資料是分段的前提下,我們才需要考慮到是否需要使用分割槽表。

分割槽的好處:

1) 增強可用性:如果表的某個分割槽出現故障,表在其他分割槽的資料仍然可用;

2) 維護方便:如果表的某個分割槽出現故障,需要修復資料,只修復該分割槽即可;

3) 均衡I/O:可以把不同的分割槽對映到磁碟以平衡I/O,改善整個系統性能;

4) 改善查詢效能:對分割槽物件的查詢可以僅搜尋自己關心的分割槽,提高檢索速度。

資料庫的表分割槽有兩種方式,水平表分割槽和垂直表分割槽。

 水平分割槽:目的是將一個表分為多個表。每個表包含的列數(表字段)都是相同的,但是記錄數(資料行)會減少。比如,我們可以將一個包含1億行記錄的資料庫表,按照水平分割槽的方式,分成12個小表,每個小表分別表示這一年份內從1月到12月的資料。這樣,任何需要查詢特定月份資料的查詢只需查詢相應月份的表,而避免從儲存在1個大表中的所有月份的資料進行查詢。根據SQL語句的執行效率,毫無疑問,從小表中的查詢效率會遠遠高於從大表中查詢的效率。

    垂直分割槽:該方式則與水平分割槽方式相反,從縱向進行分割槽,是將一個原始表分成多個只包含較少列的表。在日常的應用中,水平分割槽可以說是最常用的分割槽方式。

1、Partition 技術介紹
    ORACLE的分割槽是一種處理超大型表、索引等的技術。通過將大表和索引按照分割槽規則分成可以管理的若干小塊,從而避免了對每個表作為一個大的、單獨的物件進行管理,為大量資料提供了可伸縮的效能。分割槽通過將操作分配給更小的儲存單元,減少了需要進行管理操作的時間,並通過增強的並行處理提高了效能,通過遮蔽故障資料的分割槽,還增加了可用性。
2、資料庫分割槽設計優化方案
2.1確定哪些大表需要進行分割槽:

    使用分割槽技術時,並不是對資料庫中的所有表都進行分割槽,而只針對資料量比較大的一些大表才進行分割槽。根據分割槽的定義可知:分割槽其實就是將一個大資料段按規則劃分成若干個小資料段,如果表物件本身很小,就失去了分割槽的意義。根據經驗,資料量大於1000萬的表才需要做分割槽。
SQL>select owner,table_name,num_rows
from dba_tables
where num_rows>10000000
and partitioned='NO';
說明:在使用以上語句統計需要做分割槽的大表時,必須先收集資料庫系統的統計資訊。否則num_rows的資料不準確,無法正確表達出表物件的記錄數。
2.2討論分割槽型別及分割槽欄位的選擇:
    這一步至關重要,分割槽型別和分割槽欄位的選擇嚴重影響到資料表的訪問效能。選擇了錯誤的分割槽型別或分割槽欄位給資料庫效能帶來的負面影響會比不做分割槽更大,因此在決定分割槽型別和分割槽欄位時一定要與專案組討論,按照業務需求及業務邏輯共同制定。
根據經驗,選擇分割槽型別的步驟:
1)先確定該表中哪個欄位在select語句的謂詞中使用最頻繁,此欄位將做為分割槽欄位。
    因為分割槽的目的是將一個大表的資料段按規則分離成若干個小資料段,索引也分離為若干小索引段,在資料訪問時,根據索引只需要訪問其中的一個小索引段,最後訪問其中的一個數據段,從而減小了需要訪問的資料量,達到優化的目的。如果select語句的謂詞中不包括分割槽欄位,則必須訪問完整個索引段,最後訪問所有的小資料段,才能定位出需要訪問的資料。
2)根據分割槽欄位的特點,確定分割槽型別。
    如果該欄位有明確的順序先後關係,則該表合適做範圍分割槽。如:時間,如果該欄位沒有明確的範圍順序關係,則是具有唯一值或若干值,則該表合適做列表分割槽。如:部門、分公司,如果該欄位既無明確的範圍順序關係,也無具體值,而是些流水號,則該表合適做雜湊分割槽。如:批處理號、流水號。
2.3資料表空間及索引表空間設計
    表物件和索引物件的第一個規則是把表和索引分離。把表和相應的索引建立在不同的表空間中,最好在不同的磁碟上。這樣可以避免在資料管理和查詢時出現的許多I/O衝突。

    在此優化方案中,我們將為每個分割槽建立一個對應的表空間,讓表分割槽存放在不同的表空間中,達到不同分割槽間資料訪問的分離。同時為每個索引分割槽也建立獨立的索引分割槽表空間。

3、分割槽型別

一、範圍分割槽詳細說明

範圍分割槽就是對資料表中的某個值的範圍進行分割槽,根據某個值的範圍,決定將該資料儲存在哪個分割槽上。如根據序號分割槽,根據時間等來進行分割槽。根據序號,比如小於2000000的放在part01, 2000000~4000000的放在part02。。。

create table AAA
(
 id number primary key,
 indate date not null
)
partition by range(indate)
(
 partition part_01 values less than(to_date('2006-01-01','yyyy-mm-dd'))tablespace space01,
 partition part_02 values less than(to_date('2010-01-01','yyyy-mm-dd'))tablespace space02,
 partition part_03 values less than(maxvalue)tablespace space03
);

space01\ space02\ space03為建立的三個表空間,相當於把建立的一個大的表分在了3個不同的表空間的分割槽上了。

二、Hash分割槽(雜湊分割槽)詳細說明

   雜湊分割槽為通過指定分割槽編號來均勻分佈資料的一種分割槽型別,因為通過在I/O裝置上進行雜湊分割槽,使得這些分割槽大小一致。也就是隻命名分割槽名稱,這樣均勻進行資料分佈。

三、複合分割槽詳細說明

   有時候我們需要根據範圍分割槽後,每個分割槽內的資料再雜湊地分佈在幾個表空間中,這樣我們就要使用複合分割槽。複合分割槽是先使用範圍分割槽,然後在每個分割槽內再使用雜湊分割槽的一種分割槽方法。

partition by range(indate)subpartition by hash(id) 
subpartitions 3 store in (space01, space02, space03) 

partition part_01 values less than(to_date(’2006-01-01’,’yyyy-mm-dd’)), 
partition part_02 values less than(to_date(’2010-01-01’,’yyyy-mm-dd’)), 
partition part_03 values less than(maxvalue) 
 );

四、分割槽表操作

1、插入記錄:insert into AAA values(1 ,sysdate);

2、查詢分割槽表記錄:select * from AAA partition(part_01);

3、更新分割槽表的記錄:update AAA partition(part_01) t set indate=’’where id=1; 但是當更新的時候指定了分割槽,而根據查詢的記錄不在該分割槽中時,將不會更新資料

4、刪除分割槽表記錄:delete from AAA partition(part_02) t where id=4; 如果指定了分割槽,而條件中的資料又不在該分割槽中時,將不會刪除任何資料。

5、增加一個分割槽:alter table AAA add partition part_04 values less than(to_date(’2012-01-01’,’yyyy-mm-dd’)) tablespace dinya_spa ce03; 增加一個分割槽的時候,增加的分割槽的條件必須大於現有分割槽的最大值,否則系統將提示ORA-14074 partition bound must collate higher than that of the last partition 錯誤。

6、合併一個分割槽:alter table AAA merge partitions part_01,part_02 into partition part_02; ,如果在合併的時候把合併後的分割槽定為part_01的時候,系統將提示ORA-14275 cannot reuse lower-bound partition as resulting partition 錯誤。

7、刪除分割槽:alter table AAA drop partition part_01; 刪除分割槽表的一個分割槽後,查詢該表的資料時顯示,該分割槽中的資料已全部丟失,所以執行刪除分割槽動作時要慎重,確保先備份資料後再執行,或將分割槽合併。

五、建立索引

    分割槽表和一般表一樣可以建立索引,分割槽表可以建立區域性索引和全域性索引。當分割槽中出現許多事務並且要保證所有分割槽中的資料記錄的唯一性時採用全域性索引。

1.       區域性索引分割槽的建立:create index idx_t on AAA(id) 
 local 

partition idx_1 tablespace space01, 
partition idx_2 tablespace space02, 
partition idx_3 tablespace space03 
);

2.       全域性索引建立時global 子句允許指定索引的範圍值,這個範圍值為索引欄位的範圍值:create index idx_t on AAA(id)
global partition by range(id) 

partition idx_1 values less than (1000) tablespace space01, 
partition idx_2 values less than (10000) tablespace space02, 
partition idx_3 values less than (maxvalue) tablespace space03 
);

當然也可以不指定索引分割槽名直接對整個表建立索引:

create index idx_t on AAA(id);

資料切分可以是物理上的,對資料通過一系列的切分規則將資料分佈到不同的DB伺服器上,通過路由規則路由訪問特定的資料庫,這樣一來每次訪問面對的就不是單臺伺服器了,而是N臺伺服器,這樣就可以降低單臺機器的負載壓力。

據切分也可以是資料庫內的,對資料通過一系列的切分規則,將資料分佈到一個數據庫的不同表中,比如將article分為article_001,article_002等子表,若干個子表水平拼合有組成了邏輯上一個完整的article表,這樣做的目的其實也是很簡單的。 舉個例子說明,比如article表中現在有5000w條資料,此時我們需要在這個表中增加(insert)一條新的資料,insert完畢後,資料庫會針對這張表重新建立索引,5000w行資料建立索引的系統開銷還是不容忽視的。但是反過來,假如我們將這個表分成100 個table呢,從article_001一直到article_100,5000w行資料平均下來,每個子表裡邊就只有50萬行資料,這時候我們向一張只有50w行資料的table中insert資料後建立索引的時間就會呈數量級的下降,極大了提高了DB的執行時效率,提高了DB的併發量。當然分表的好處還不知這些,還有諸如寫操作的鎖操作等,都會帶來很多顯然的好處。

綜上,分庫降低了單點機器的負載;分表,提高了資料操作的效率,尤其是Write操作的效率

讀寫分離,基本的原理是讓主資料庫處理事務性增、改、刪操作(INSERT、UPDATE、DELETE),而從資料庫處理SELECT查詢操作。資料庫複製被用來把事務性操作導致的變更同步到叢集中的從資料庫。

       為什麼要分庫、分表、讀寫分?

       單表的資料量限制,當單表資料量到一定條數之後資料庫效能會顯著下降。資料多了之後,對資料庫的讀、寫就會很多。分庫減少單臺數據庫的壓力。接觸過幾個分庫分表的系統,都是通過主鍵進行雜湊分褲分表的。這類資料比較特殊,主鍵就是唯一的獲取該條資訊的主要途徑。比如:京東的訂單、財付通的交易記錄等。。。該類資料的用法,就是通過訂單號、交易號來查詢該筆訂單、交易。

        還有一類資料,比如使用者資訊,每個使用者都有系統內部的一個userid,與userid對應的還有使用者看到的登入名。那麼如果分庫分表的時候單純通過userid進行雜湊分庫,那麼根據登入名來獲取使用者的資訊,就無法知道該使用者處於哪個資料庫中。

       或許有朋友會說,我們可以維護一個email----userid的對映關係,根據email先查詢到userid,在根據userid的分庫分表規則到對應庫的對應表來獲取使用者的記錄資訊。這麼做是可以的,但是這個對映關係的條數本身也是個瓶頸,原則上是沒有減少單表內資料的條數,算是一個單點。並且要維護這個對映關係和使用者資訊的一致性(修改登入名、多登入名等其他特殊需求),最大一個原因,其實使用者資訊是一個讀大於寫的庫,web2.0都是以使用者為中心,所有資訊都和使用者資訊相關聯,所以對使用者資訊拆分還是有一定侷限性的。

       對於這類讀大於寫並且資料量增加不是很明顯的資料庫,推薦採用讀寫分離+快取的模式,試想一下一個使用者註冊、修改使用者資訊、記錄使用者登入時間、記錄使用者登入IP、修改登入密碼,這些是寫操作。但是以上這些操作次數都是很小的,所以整個資料庫的寫壓力是很小的。唯一一個比較大的就是記錄使用者登入時間、記錄使用者登入IP這類資訊,只要把這些經常變動的資訊排除在外,那麼寫操作可以忽略不計。所以讀寫分離首要解決的就是經常變化的資料的拆分,比如:使用者登入時間、記錄使用者登入IP。這類資訊可以單獨獨立出來,記錄在持久化類的快取中(可靠性要求並不高,登陸時間、IP丟了就丟了,下次來了就又來了)

        以oracle為例,主庫負責寫資料、讀資料。讀庫僅負責讀資料。每次有寫庫操作,同步更新cache,每次讀取先讀cache在讀DB。寫庫就一個,讀庫可以有多個,採用dataguard來負責主庫和多個讀庫的資料同步。

總結: Oracle資料庫的分割槽技術可以改善查詢效能,僅搜尋自己關心的分割槽,提高檢索速度。同時可以把不同的分割槽分離至不同的磁碟上,以平衡I/0
,改善整個系統的效能。除此之外,在資料維護方面,分割槽技術也有很大的優勢。在進行歷史資料轉儲時,只需要將需要轉儲的資料分割槽export備份出來轉儲至磁帶中。而不需要將整張表全部export備份出來。在歷史資料清理時可以將歷史資料所在的分割槽truncate或drop,而不影響表的其他資料,同時釋放空間。