1. 程式人生 > >分表分庫原則

分表分庫原則

        分表分庫雖然能解決大表對資料庫系統的壓力,但它並不是萬能的,也有一些不利之處,因此首要問題是,分不分庫,分哪些庫,什麼規則分,分多少分片。

       原則一:能不分就不分,1000 萬以內的表,不建議分片,通過合適的索引,讀寫分離等方式,可以很好的解決效能題。

       原則二:分片數量儘量少,分片儘量均勻分佈在多個DataHost 上,因為一個查詢 SQL 跨分片越多,則總體效能越差,雖然要好於所有資料在一個分片的結果,只在必要的時候進行擴容,增加分片數量。

       原則三:分片規則需要慎重選擇,分片規則的選擇,需要考慮資料的增長模式,資料的訪問模式,分片關聯性問題,以及分片擴容問題,最近的分片策略為範圍分片,列舉分片,一致性 Hash分片,這幾種分片都有利於擴容。

       原則四:儘量不要在一個事務中的SQL 跨越多個分片,分散式事務一直是個不好處理的問題。

       原則五:查詢條件儘量優化,儘量避免Select * 的方式,大量資料結果集下,會消耗大量頻寬和CPU 資源,查詢儘量避免返回大量結果集,並且儘量為頻繁使用的查詢語句建立索引。

       這裡特別強調一下分片規則的選擇問題,如果某個表的資料有明顯的時間特徵,比如訂單、交易記錄等,則他們通常比較合適用時間範圍分片,因為具有時效性的資料,我們往往關注其近期的資料,查詢條件中往往帶有時間欄位進行過濾,比較好的方案是,當前活躍的資料,採用跨度比較短的時間段進行分片,而歷史性的資料,則採用比較長的跨度儲存。

      總體上來說,分片的選擇是取決於最頻繁的查詢SQL 的條件,因為不帶任何Where 語句的查詢SQL,會便利所有的分片,效能相對最差,因此這種 SQL 越多,對系統的影響越大,所以我們要儘量避免這種SQL 的產生。

       如何準確統計和分析當前系統中最頻繁的 SQL 呢?有幾個簡單做法:

- 採用特殊的 JDBC 驅動程式,攔截所有業務 SQL,並寫程式進行分析

- 採用 Mycat的 SQL 攔截器機制,寫一個外掛,攔截所欲 SQL,並進行統計分析

- 開啟 MySQL日誌,分析統計所有 SQL

      找出每個表最頻繁的SQL,分析其查詢條件,以及相互的關係,並結合 ER圖,就能比較準確的選擇每個表的分片策略。

       對於大家經常提起的同庫內分表的問題,這裡做一些分析和說明,同庫內分表,僅僅是單純的解決了單一表資料過大的問題,由於沒有把表的資料分佈到不同的機器上,因此對於減輕MySQL 伺服器的壓力來說,並沒有太大的作用,大家還是競爭同一個物理機上的 IO、CPU、網路。此外,庫內分表的時候,要修改使用者程式發出的SQL,可以想象一下A、B兩個表各自分片 5個分表情況下的 Join SQL 會有多麼的反人類。這種複雜的 SQL 對於DBA 調優來說,也是個很大的問題。因此,Mycat和一些主流的資料庫中介軟體,都不支援庫內分表,但由於MySQL 本身對此有解決方案,所以可以與Mycat 的分庫結合,做到最佳效果,下面是 MySQL的分表方案:

  • MySQL 分割槽;

  • MERGE 表(MERGE 儲存引擎)。

       通俗地講 MySQL分割槽是將一大表,根據條件分割成若干個小表。mysql5.1 開始支援資料表分割槽了。 如:某使用者表的記錄超過了600 萬條,那麼就可以根據入庫日期將表分割槽,也可以根據所在地將表分割槽。當然也可根據其他的條件分割槽。

  •  RANGE 分割槽:基於屬於一個給定連續區間的列值,把多行分配給分割槽,MySQL分割槽支援的分割槽規則有以下幾種:LIST分割槽:類似於按 RANGE 分割槽,區別在於LIST 分割槽是基於列值匹配一個離散值集合中的某個值來進行選擇。

  •  HASH分割槽:基於使用者定義的表示式的返回值來進行選擇的分割槽,該表示式使用將要插入到表中的這些行的列值進行計算。這個函式可以包含 MySQL 中有效的、產生非負整數值的任何表示式。

  • KEY分割槽:類似於按 HASH 分割槽,區別在於KEY分割槽只支援計算一列或多列,且 MySQL伺服器提供其自身的雜湊函式。必須有一列或多列包含整數值。

       在Mysql 資料庫中,Merge 表有點類似於檢視,mysql 的 merge引擎型別允許你把許多結構相同的表合併為一個表。之後,你可以執行查詢,從多個表返回的結果就像從一個表返回的結果一樣。每一個合併的表必須有完全相同表的定義和結構,但只支援只是支援 MyISAM 引擎。

  • Mysql Merge表的優點:

  • 更容易維護大資料集;

  • 查詢時可以訪問更少的資料;

  • 利用結構接近的的資料來優化查詢;

  • 分離靜態的和動態的資料。

       在資料量、查詢量較大的情況下,不要試圖使用Merge 表來達到類似於Oracle的表分割槽的功能,會很影響效能。我的感覺是和union 幾乎等價。

        Mycat建議的方案是 Mycat分庫+MySQL 分割槽,此方案具有以下優勢:

  •  充分結合分散式的並行能力和MySQL 分割槽表的優化;

  •  可以兩個維度對錶進行分片,MyCAT 一個維度分庫,MySQL一個維度分割槽;

  • 可以靈活的控制表的資料規模。