mysql使用MRG_MyISAM(MERGE)实现水平分表
來源:http://m.oschina.net/blog/382658
在MySql中數據的優化尤其是大數據量的優化是一門很大的學問,當然其它數據庫也是如此,即使你不是DBA,做為一名程序員掌握一些基本的優化信息,也可以讓你在自己的程序開發中受益匪淺。當然數據庫的優化有很多的方方面面,本篇主要講,Mysql的水平分表技術,也可以說是其技術的其中之一。
在使用水平分表時,首先問下自己幾個問題。
第一、為什么要水平分表?
第二、什么時候需要水平分表?
第三、怎樣實現水平分表?
一、為什么要水平分表?
簡而言之,當單表數據量過大時,無法對其進行有效的維護,以及查詢速度嚴重變慢時,我們就需要對其時行水平分表
二、什么時候需要水平分表?
在數據庫結構的設計中,需要充分考慮后期數據的增長量和增長速度,如果后期的數據增長量過快,以及后期數據量巨大,就需要使用水平分表。
三、怎樣實現水平分表?
其實水平分表的方法,很多,但個人覺得結合程序的增刪改查,本篇介紹的方法MRG_MySIAM存儲引擎(MERGE存儲引擎)個人覺得還是比較簡單方便的,雖然性能方面與其它分表技術相比可能不是第一,但就使用程序對其的操控性來說,個人覺得還是很不錯的。
MERGE存儲引擎基本介紹和使用規范說明【以下截自MySql手冊】:
MERGE存儲引擎,也被認識為MRG_MyISAM引擎,是一個相同的可以被當作一個來用的MyISAM表的集合。“相同”意味著所有表同樣的列和索引信息。你不能合并列被以不同順序列于其中的表,沒有恰好同樣列的表,或有不同順序索引的表。而且,任何或者所有的表可以用myisampack來壓縮。表選項的差異,比如AVG_ROW_LENGTH, MAX_ROWS或PACK_KEYS都不重要。
當你創建一個MERGE表之時,MySQL在磁盤上創建兩個文件。文件名以表的名字開始,并且有一個擴展名來指明文件類型。一個.frm文件存儲表定義,一個.MRG文件包含被當作一個來用的表的名字。這些表作為MERGE表自身,不必要在同一個數據庫中。
你可以對表的集合用SELECT, DELETE, UPDATE和INSERT。你必須對你映射到一個MERGE表的這些表有SELECT, UPDATE和DELETE 的權限。
如果你DROP MERGE表,你僅在移除MERGE規格。底層表沒有受影響。
當你創建一個MERGE表之時,你必須指定一個UNION=(list-of-tables)子句,它說明你要把哪些表當作一個來用。如果你想要對MERGE表的插入發生在UNION列表中的第一個或最后一個表上,你可以選擇地指定一個INSERT_METHOD選項。使用FIRST或LAST值使得插入被相應地做在第一或最后一個表上。如果你沒有指定INSERT_METHOD選項,或你用一個NO值指定該選項。往MERGE表插入記錄的試圖導致錯誤。
大致了解了MERGE存儲引擎的基本介紹后,就讓我們真正開始動手吧。
在分表的我們必須考慮如下問題:
1、根據什么樣的規則來實現分表,即通過什么樣的規則來插入不同的數據表?
2、即使分表成功,那么程序對其的處理是否簡潔?
下面以下實例來說明,
假設我們有個郵件服務器,需要存儲很多很多用戶的郵件,為了解決后期數據量具大問題,我們就需要使用水平分表技術。
以什么樣的規則來實現分表,分表數據如何確定?
首先我們必須大概估算以后的數據量會多大,分多少張表比較合適,從而來確定分表規則。
以我的情況為例,
我覺得以郵件的發送時間來計算,按天來劃分,分為31張表比較合適。
那么我的分表規則,則如下設計,:
????email為主表,email_X為子表,先創建子表,結構與主表相同,在創建子表時注意要將ENGINE=MRG_MyISAM替換為ENGINE=MyISAM,否則會出現Unable to open underlying table which is differently defined or of non-MyISAM type or doesn't exist的錯誤提示,不能對主表進行查詢
CREATE?TABLE?`email`?(`id`?int(10)?unsigned?NOT?NULL?AUTO_INCREMENT,`euid`?mediumint(8)?unsigned?NOT?NULL?DEFAULT?'0'?COMMENT?'帳號ID',`uid`?char(50)?NOT?NULL?COMMENT?'郵件UID',`reciever`?char(255)?NOT?NULL?COMMENT?'收件人',`sender`?char(255)?NOT?NULL?COMMENT?'發送人',`sendTime`?int(10)?unsigned?NOT?NULL?DEFAULT?'0',`sendTitle`?char(100)?NOT?NULL?COMMENT?'主題?',`type`?char(50)?NOT?NULL?COMMENT?'類型',PRIMARY?KEY?(`id`) )?ENGINE=MRG_MyISAMDEFAULT?CHARSET=utf8? UNION=(`email_1`,`email_2`,`email_3`,`email_4`,`email_5`,`email_6`,`email_7`,`email_8`,`email_9`,`email_10`,`email_11`,`email_12`,`email_13`,`email_14`,`email_15`,`email_16`,`email_17`,`email_18`,`email_19`,`email_20`,`email_21`,`email_22`,`email_23`,`email_24`,`email_25`,`email_26`,`email_27`,`email_28`,`email_29`,`email_30`,`email_31`);首先創建一張MERGE存儲類型的主表,
然后再批量創建31張MyISAM存儲類型的數據表。
OK,此時創建完成后,我們需要做的是什么?
當然,第一步肯定是寫入數據。此時我們的分表規則就有了用武之地了。
$sql?=?"INSERT?INTO?email_{$ruleNum}(....)?VALUES(.....);"此時完全可以正確的寫入,并且在Email表中也會存在,是不是很OK。
但別高興太早,我們要做的遠遠不止這些。
首先,因為ID是Auto_Increment,你完全可以不用管,因為每次插入不同的數據表都會有不同的ID,但問題是當你在EMAil這個Merge類型表中查看時你會發現,會有很多重復的ID,因為每張表的ID在email表中展現可能會有大量重復。這對我們修改和刪除會有極大的影響,如果沒有惟的ID,默認修改是根據排序來分別的,當然不可以。
所以在數據寫入時,我們必須還要手動增加ID,來保證整個數據的ID都是惟一的。
方法當然有很多種,簡單介紹下我的做法,
我直接新建了一張表就一個字段:
在每次新增完成數據后,都會使用觸發器自動將此表中的數據值+1,而在每次讀取時,先讀取此表,獲取下一個ID,這樣就能保證數據ID永遠惟一。
PS:也可以將此ID值存入文件,前提是在不會丟失的情況下?;蚱渌糘K。
寫入問題解決后,就剩下UPDATE,DELETE,SELECT了,這些現在都已不是問題,我們直接操作Email這個Merge類型表即可,(Mysql手冊也有詳細的介紹,可自行查看)
INSERT:
SELECT?*?FROM?eamil?where?($where)?limit?20,10;UPDATE:
UPDATE?email?SET?username='$username'?WHERE?id=10DELETE:
DELETE?FROM?email?WHERE?id=11這只是一種MySql的水平分表方法,如果數據表較少的話,也可以使用
union 聯合查詢來實現數據表分表聯合查詢。
其它方法,網上也有很多,可自行查看。
總結
以上是生活随笔為你收集整理的mysql使用MRG_MyISAM(MERGE)实现水平分表的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 违和感(说一说违和感的简介)
- 下一篇: MySQL中merge表存储引擎用法