在面試時經常會問一個問題請列舉出hash在數據庫內部的應用hash的原理雖然簡單但是它在數據庫中可以說是無處不在其中hash partition是hash在數據庫中一個簡單的應用雖然它沒有range partition那麼常用但是我們在做數據庫水平拆分時其實就是利用了hash partition的原理利用hash函數對某個key進行運算然後將其分布到不同的主機上原理很簡單
我們在設計時遇到了一個問題當分區的數量需要變化時基於hash的原理數據可能會從一個分區移動到另外一個分區因為某個key在個分區時可能被分布在分區而在個分區時可能被分布在分區這樣每當分區數量變化時就需要全部重新分布數據代價很高
那麼Oracle是怎麼做的?首先可以肯定的是Oracle的hash partition在分區增加時不需要做全部數據的重新分布有人告訴我Oracle的hash函數比較牛可以保證分區數量增加時這個hash函數可以讓原來的數據還在舊的分區中而新的數據可以分布在新的分區Oracle的函數無非就是get_hash_value或ora_hash(g)從hash的原理上來說這也是不可能做到的
我們對hash partition都有一個常識就是partition的數量最好是的次方也就是……否則分區會出現不分區均衡的現象按照hash的原理不管是幾個分區都可以做到完全均衡的為什麼會不均衡其實答案已經出來了Oracle為了能夠增加分區為你預留了幾個看不到的分區
假設我們有個分區一共條數據數據的分布如下圖
![hash_partition1](http://tw.wingwit.com/Article/UploadFiles/201311/2013111315544339.jpg)
hash partition不能直接增加分區而是split當前分區當需要增加到個分區時實際上是分區和分區分別split產生新的分區和分區如下圖
![hash_partition2](http://tw.wingwit.com/Article/UploadFiles/201311/2013111315544438.jpg)
Oracle如何做到分區數量增加後其他分區的數據不受影響呢其實很簡單Oracle在做hash運算時預留了分區比如個分區實際上是用個分區的hash來運算的只不過把缺少的分區的數據合並到其他分區這樣就會出現數據不均衡的情況Oracle的公式是這樣的用等於或者大於當前分區數量的最小的一個的N次方比如個分區做個hash bucket我們再來考慮一下(的N次方)的情況比如要把個分區加為個分區因為已經是的N次方所以數據會均勻分布而且Oracle還是使用個hash bucket這時新增的分區實際上把分區 split後產生的這時因為有個分區了所以會使用個hash bucket這時Oracle的hash函數就比較牛了它可以保證個分區時同一個鍵值分布在相同的分區或者是對應可以合並的分區看下面的SQL
select ora_hash(hellodba)+ parora_hash(hellodba)+ parora_hash(hellodba)+ parora_hash(hellodba)+ par from dual;
PAR PAR PAR PAR
上面的SQL我們看到分區的數量在時hellodba這個key分別落在在號分區雖然落在不同的分區上但是分區和分區是對應可合並的這樣就保證了數據是不需要移動的一句話總結就是hash bucket總是的N次方如果分區數不足則會合並數據產生不均衡的情況這樣增加分區時只需要對應分區的數據做split即可同理減少分區也不是簡單的drop而是合並分區
再回到我們的項目中我們為了解決這個問題采用了更簡單的處理方案直接就做了個分區我們有個物理數據庫每個數據庫中有個表以後再分拆時只要移動這些表並修改應用中的對應關系就可以了其實和Oracle合並再拆分的思路是一樣的
From:http://tw.wingwit.com/Article/program/Oracle/201311/17498.html