數據庫分區分表以及讀寫分離


談談怎么實現Oracle數據庫分區表

Oracle數據庫分區是作為Oracle數據庫性能優化的一種重要的手段和方法,做手頭的項目以前,只聆聽過分區的大名,感覺特神秘,看見某某高手在討論會上誇誇其談時,真是罵自己學藝不精,最近作GPS方面的項目,處理的數據量達到了幾十GB,為了滿足系統的實時性要求,必須提高數據的查詢效率,這樣就必須通過分區,以解燃眉之急!

先說說分區的好處吧!

1) 增強可用性:如果表的某個分區出現故障,表在其他分區的數據仍然可用;

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

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

4) 改善查詢性能:對分區對象的查詢可以僅搜索自己關心的分區,提高檢索速度。

Oracle數據庫提供對表或索引的分區方法有三種:

ü 范圍分區

ü Hash分區(散列分區)

ü 復合分區

 

一、范圍分區詳細說明

范圍分區就是對數據表中的某個值的范圍進行分區,根據某個值的范圍,決定將該數據存儲在哪個分區上。如根據序號分區,根據時間等來進行分區。根據序號,比如小於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來負責主庫和多個讀庫的數據同步。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM