Mysql 基礎課十一:分庫分表

需求

  1. 因爲數據庫單表容量超過 1000 萬,性能會變差,並且單節點 Mysql 實例支持的併發也有限,所以需要對數據進行切分,有分庫和分表的手段;
	分庫,將併發訪問高的表,單獨放在一個庫中,這樣提高了併發性能,但無法解決單表過大的問題
	分表,選擇合適的分片鍵,對錶進行拆分
	如果單筆超過 1000 億條數據,建議使用 Hadoop 等大數據工具
  1. 分庫分表有幾個原則,儘量不要分表,選擇合適的分片鍵,分片鍵是查詢的熱點條件,且能比較均勻的劃分數據,字典表進行數據冗餘,合理劃分數據,將關聯表的關聯數據劃分在同一分片;

  2. 引入多個數據庫後,就需要多數據源的管理,並且還需要非分片字段的查詢,join 操作和分佈式事務的支持,爲此可以引入一箇中間層 proxy,使得應用層不用關心分庫分表後的細節處理,如 Mycat;

Mycat

  1. 中間代理層 MyCat,是對 SQL 進行分析,確定分片,將 SQL 發往真實數據庫執行,單節點無法返回結果的,還需要多節點查詢,數據處理後返回給上層應用;

  2. 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:定義分片規則

分片查詢

  1. 如果查詢沒有分片字段,
	where 子句,MyCat 需要去每一個節點都做一次查詢
	limit n 操作,同樣需要去所有節點查詢,並隨機返回一份
	order by col_name limit n 操作,需要將所有節點的查詢結果彙總,使用排序算法,排序後返回
	對於 limit m, n 操作,會改寫爲 limit 0,m+n,節點查詢結果彙總後,根據 limit m, n 返回,這類查詢,性能影響極大
  1. limit m, n 的一種改造思路,是每次查詢,獲取上一次查詢的排序字段的最大值 last_max,這樣下次查詢,直接使用 limit n where field > last_max;

  2. 使用 left join 或者 right join 時,on 子句的匹配條件會優先執行,where 條件在最後執行,所以儘可能在 on 語句中進行條件判斷;

  3. 對於某些全局表,如字典表,Mycat 採用冗餘的方式在每個節點緩存,避免一定的跨庫 join 操作;

	// 配置全局表
	<table name="company" primaryKey="ID" type="global" dataNode="dn1,dn2,dn3" />
  1. 分片策略上,可以將經常關聯的幾張表,根據關聯關係,將關聯數據放在一個分片上,這樣就能實現局部 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…

分區表

  1. 分區表,對引擎層來說,是多個表,對 Server 層來說,是 1 個表;information_schema 庫的表 partitions 保存該庫的所有分區信息;

  2. 分區表有幾個特點,首先第一次打開分區表,需要訪問所有的分區,其次,所有分區會共用一個 MDL 鎖,這樣訪問一個分區會阻塞所有分區的更新操作,最後,會根據分區的規則,對應的語句只訪問必要的分區;

  3. 如果使用分區表,建議不要創建太多的分區,並且往往可以用手工分表來代替分區表,避開了分區表的一些弊端,分區表的優點是對業務透明,能擴展表容量;

  4. 分區表,根據分區規則,分爲 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 (...) 
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章