需求
- 因爲數據庫單表容量超過 1000 萬,性能會變差,並且單節點 Mysql 實例支持的併發也有限,所以需要對數據進行切分,有分庫和分表的手段;
分庫,將併發訪問高的表,單獨放在一個庫中,這樣提高了併發性能,但無法解決單表過大的問題
分表,選擇合適的分片鍵,對錶進行拆分
如果單筆超過 1000 億條數據,建議使用 Hadoop 等大數據工具
-
分庫分表有幾個原則,儘量不要分表,選擇合適的分片鍵,分片鍵是查詢的熱點條件,且能比較均勻的劃分數據,字典表進行數據冗餘,合理劃分數據,將關聯表的關聯數據劃分在同一分片;
-
引入多個數據庫後,就需要多數據源的管理,並且還需要非分片字段的查詢,join 操作和分佈式事務的支持,爲此可以引入一箇中間層 proxy,使得應用層不用關心分庫分表後的細節處理,如 Mycat;
Mycat
-
中間代理層 MyCat,是對 SQL 進行分析,確定分片,將 SQL 發往真實數據庫執行,單節點無法返回結果的,還需要多節點查詢,數據處理後返回給上層應用;
-
MyCat 使用 schema.xml 來定義物理庫和表,使用 server.xml 定義系統配置信息,使用 rule.xml 定義分片規則等信息;
schema.xml:管理Mycat的邏輯庫,表,分片規則,dataNode以及DataSource
// schema.xml
<schema>:邏輯庫,和Mysql中的database的概念相同
<table>:邏輯表
<dataNode>:標識一個數據節點
<dataHost>:具體的數據庫實例
// server.xml
<user>:定義登錄mycat的用戶和權限
// rule.xml:定義分片規則
分片查詢
- 如果查詢沒有分片字段,
where 子句,MyCat 需要去每一個節點都做一次查詢
limit n 操作,同樣需要去所有節點查詢,並隨機返回一份
order by col_name limit n 操作,需要將所有節點的查詢結果彙總,使用排序算法,排序後返回
對於 limit m, n 操作,會改寫爲 limit 0,m+n,節點查詢結果彙總後,根據 limit m, n 返回,這類查詢,性能影響極大
-
limit m, n 的一種改造思路,是每次查詢,獲取上一次查詢的排序字段的最大值 last_max,這樣下次查詢,直接使用 limit n where field > last_max;
-
使用 left join 或者 right join 時,on 子句的匹配條件會優先執行,where 條件在最後執行,所以儘可能在 on 語句中進行條件判斷;
-
對於某些全局表,如字典表,Mycat 採用冗餘的方式在每個節點緩存,避免一定的跨庫 join 操作;
// 配置全局表
<table name="company" primaryKey="ID" type="global" dataNode="dn1,dn2,dn3" />
- 分片策略上,可以將經常關聯的幾張表,根據關聯關係,將關聯數據放在一個分片上,這樣就能實現局部 join 操作;
// 例如:customer 和 orders 表是兩個分片表,配置兩張表的關聯關係 o.customer_id=c.id 來放在同一分片
<table name="customer" dataNode="dn1,dn2" rule="sharding-by-intfile">
<childTable name="orders" joinKey="customer_id" parentKey="id"/>
</table>
自增 id
1…
分區表
-
分區表,對引擎層來說,是多個表,對 Server 層來說,是 1 個表;information_schema 庫的表 partitions 保存該庫的所有分區信息;
-
分區表有幾個特點,首先第一次打開分區表,需要訪問所有的分區,其次,所有分區會共用一個 MDL 鎖,這樣訪問一個分區會阻塞所有分區的更新操作,最後,會根據分區的規則,對應的語句只訪問必要的分區;
-
如果使用分區表,建議不要創建太多的分區,並且往往可以用手工分表來代替分區表,避開了分區表的一些弊端,分區表的優點是對業務透明,能擴展表容量;
-
分區表,根據分區規則,分爲 range,list,hash,key 幾種分區模式,且分區鍵只能是主鍵或唯一字段;
// 根據birth_date的 hash 值的分爲6個分區的表
create table(
emp_id int,
salary decimal(7,2),
birth_date date)engine = innodb
partition by HASH(MONTH(birth_date)) partitions 6
// 增加8個分區
alter table t add partition partitions 8
// 會刪除分區和分區表中的數據
alter table t drop partition p2;
// 拆分分區
alter table t reorganize partition p3 into (...)