MySQL優化筆記(五)--數據庫存儲引擎(主要分析對比InnoDB和MyISAM以及講述Mrg_Myisam分表)

學校里做的項目都是默認MySQL的InnoDB存儲引擎,沒有思考過為什么使用,也沒思考過其優缺和其他數據庫存儲引擎。直到我去實習了,在學習優化的過程中,才發現自己很無知,知識很局限。為此做次彌補。

本系列demo下載

(一)MySQL優化筆記(一)--庫與表基本操作以及數據增刪改

(二)MySQL優化筆記(二)--查找優化(1)(非索引設計)

(三)MySQL優化筆記(二)--查找優化(2)(外連接、多表聯合查詢以及查詢注意點)

(四) MySQL優化筆記(三)--索引的使用、原理和設計優化

(五) MySQL優化筆記(四)--表的設計與優化(單表、多表)

(六)MySQL優化筆記(五)--數據庫存儲引擎

(七)MySQL優化筆記(六)--存儲過程和存儲函數

(八)MySQL優化筆記(七)--視圖應用詳解

(九) MySQL優化筆記(八)--鎖機制超詳細解析(鎖分類、事務并發、引擎并發控制)


文章結構:(1)存儲引擎概述;(2)MySQL各大存儲引擎;(3)InnoDB和MyIsam使用及其原理對比;(4)InnoDB和MyIsam引擎原理;(5)剩余引擎的使用DEMO(主要是Mrg_Myisam分表);

文章目錄:(例子下載在最下方)

(1)存儲引擎概述

  • 為什么要合理選擇數據庫存儲引擎
  • 定義
  • 存儲引擎作用
  • 如何修改數據庫引擎
  • 怎么查看修改成功

(2)MySQL各大存儲引擎

  • InnoDB
    • 適用場景
    • MySQL官方對InnoDB的講解
  • MyIsam
    • 適用場景
    • 補充:ISAM索引方法--索引順序存取方法
  • Memory(也叫HEAP)堆內存嘛
  • Mrg_Myisam:(分表的一種方式--水平分表)
  • Blackhole(黑洞引擎)

(3)InnoDB和MyIsam使用及其原理對比

  • 使用的效果與區別展示
  • 效果對比總述
  • 使用建議

(4)InnoDB和MyIsam引擎原理

  • MyIASM引擎的索引結構
  • InnoDB引擎的索引結構

(5)剩余引擎的使用DEMO(主要是Mrg_Myisam分表)

  • Mrg_Myisam引擎分表
  • 項目中如何使用MRG_MYISAM總表
  • MRG_MYISAM分表的優點
  • 使用MRG_MyISAM分表的必須思考問題

一、存儲引擎的概述:

基于此博客MySQL數據庫引擎去擴展,不過每個我都會用例子去驗證,并寫出的見解。

(1)為什么要合理選擇數據庫存儲引擎:

MySQL中的數據用各種不同的技術存儲在文件(或者內存)中。這些技術中的每一種技術都使用不同的存儲機制、索引技巧、鎖定水平并且最終提供廣泛的不同的功能和能力。通過選擇不同的技術,你能夠獲得額外的速度或者功能,從而改善你的應用的整體功能。

這些不同的技術以及配套的相關功能在MySQL中被稱作存儲引擎(也稱作表類型)。MySQL默認配置了許多不同的存儲引擎,可以預先設置或者在MySQL服務器中啟用。你可以選擇適用于服務器、數據庫和表格的存儲引擎,以便在選擇如何存儲你的信息、如何檢索這些信息以及你需要你的數據結合什么性能和功能的時候為你提供最大的靈活性。

(2)定義:

數據庫引擎是用于存儲、處理和保護數據的核心服務。利用數據庫引擎可控制訪問權限并快速處理事務,從而滿足企業內大多數需要處理大量數據的應用程序的要求。 使用數據庫引擎創建用于聯機事務處理或聯機分析處理數據的關系數據庫。這包括創建用于存儲數據的表和用于查看、管理和保護數據安全的數據庫對象(如索引、視圖和存儲過程)。

(3)存儲引擎作用:

1)設計并創建數據庫以保存系統所需的關系或XML文檔。

2)實現系統以訪問和更改數據庫中存儲的數據。包括實現網站或使用數據的應用程序,還包括生成使用SQL Server工具和實用工具以使用數據的過程。

3)為單位或客戶部署實現的系統。

4)提供日常管理支持以優化數據庫的性能。

(4)如何修改數據庫引擎:

方式一:

修改配置文件my.ini

將mysql.ini另存為my.ini,在[mysqld]后面添加default-storage-engine=InnoDB,重啟服務,數據庫默認的引擎修改為InnoDB

方式二:

在建表的時候指定

create table mytbl(   
    id int primary key,   
    name varchar(50)   
)type=MyISAM;

方式三:

建表后更改

alter table table_name type = InnoDB;

(5)怎么查看修改成功?

方式一:

show table status from table_name; 

方式二:

show create table table_name

方式三:

使用數據庫管理工具啊。


二、MySQL各大存儲引擎:

最好先看下你下的MySQL支持什么數據庫引擎

這里寫圖片描述

存儲引擎主要有: 1. MyIsam , 2. InnoDB, 3. Memory, 4. Blackhole, 5. CSV, 6. Performance_Schema, 7. Archive, 8. Federated , 9 Mrg_Myisam

但是我們主要分析使用MyIsam 和InnoDB。其余略微帶過,詳情請分別百度。

(1)InnoDB:

定義:(默認的存儲引擎)

InnoDB是一個事務型的存儲引擎,有行級鎖定和外鍵約束。

Innodb引擎提供了對數據庫ACID事務的支持,并且實現了SQL標準的四種隔離級別,關于數據庫事務與其隔離級別的內容請見數據庫事務與其隔離級別這類型的文章。該引擎還提供了行級鎖和外鍵約束,它的設計目標是處理大容量數據庫系統,它本身其實就是基于MySQL后臺的完整數據庫系統,MySQL運行時Innodb會在內存中建立緩沖池,用于緩沖數據和索引。但是該引擎不支持FULLTEXT類型的索引,而且它沒有保存表的行數,當SELECT COUNT(*) FROM TABLE時需要掃描全表。當需要使用數據庫事務時,該引擎當然是首選。由于鎖的粒度更小,寫操作不會鎖定全表,所以在并發較高時,使用Innodb引擎會提升效率。但是使用行級鎖也不是絕對的,如果在執行一個SQL語句時MySQL不能確定要掃描的范圍,InnoDB表同樣會鎖全表。

//這個就是select鎖表的一種,不明確主鍵。增刪改查都可能會導致鎖全表,在以后我們會詳細列出。
SELECT * FROM products WHERE name='Mouse' FOR UPDATE;

適用場景:

1)經常更新的表,適合處理多重并發的更新請求。

2)支持事務。

3)可以從災難中恢復(通過bin-log日志等)。

4)外鍵約束。只有他支持外鍵。

5)支持自動增加列屬性auto_increment。

MySQL官方對InnoDB的講解:

1)InnoDB給MySQL提供了具有提交、回滾和崩潰恢復能力的事務安全(ACID兼容)存儲引擎。

2)InnoDB鎖定在行級并且也在SELECT語句提供一個Oracle風格一致的非鎖定讀,這些特色增加了多用戶部署和性能。沒有在InnoDB中擴大鎖定的需要,因為在InnoDB中行級鎖定適合非常小的空間。

3)InnoDB也支持FOREIGN KEY強制。在SQL查詢中,你可以自由地將InnoDB類型的表與其它MySQL的表的類型混合起來,甚至在同一個查詢中也可以混合。

4)InnoDB是為處理巨大數據量時的最大性能設計,它的CPU效率可能是任何其它基于磁盤的關系數據庫引擎所不能匹敵的。

5) InnoDB被用來在眾多需要高性能的大型數據庫站點上產生。

補充:什么叫事務?簡稱ACID

A 事務的原子性(Atomicity):指一個事務要么全部執行,要么不執行.也就是說一個事務不可能只執行了一半就停止了.比如你從取款機取錢,這個事務可以分成兩個步驟:1劃卡,2出錢.不可能劃了卡,而錢卻沒出來.這兩步必須同時完成.要么就不完成.

C 事務的一致性(Consistency):指事務的運行并不改變數據庫中數據的一致性.例如,完整性約束了a+b=10,一個事務改變了a,那么b也應該隨之改變.

I 獨立性(Isolation):事務的獨立性也有稱作隔離性,是指兩個以上的事務不會出現交錯執行的狀態.因為這樣可能會導致數據不一致.

D 持久性(Durability):事務的持久性是指事務執行成功以后,該事務所對數據庫所作的更改便是持久的保存在數據庫之中,不會無緣無故的回滾.

(2)MyIsam:

定義

MyIASM是MySQL默認的引擎,但是它沒有提供對數據庫事務的支持,也不支持行級鎖和外鍵,因此當INSERT(插入)或UPDATE(更新)數據時即寫操作需要鎖定整個表,效率便會低一些。

MyIsam 存儲引擎獨立于操作系統,也就是可以在windows上使用,也可以比較簡單的將數據轉移到linux操作系統上去。

意味著:引擎在創建表的時候,會創建三個文件,一個是.frm文件用于存儲表的定義,一個是.MYD文件用于存儲表的數據,另一個是.MYI文件,存儲的是索引。操作系統對大文件的操作是比較慢的,這樣將表分為三個文件,那么.MYD這個文件單獨來存放數據自然可以優化數據庫的查詢等操作。有索引管理和字段管理。MyISAM還使用一種表格鎖定的機制,來優化多個并發的讀寫操作,其代價是你需要經常運行OPTIMIZE TABLE命令,來恢復被更新機制所浪費的空間。

適用場景

1)不支持事務的設計,但是并不代表著有事務操作的項目不能用MyIsam存儲引擎,可以在service層進行根據自己的業務需求進行相應的控制。

2)不支持外鍵的表設計。

3)查詢速度很快,如果數據庫insert和update的操作比較多的話比較適用。

4)整天 對表進行加鎖的場景。

5)MyISAM極度強調快速讀取操作。

6)MyIASM中存儲了表的行數,于是SELECT COUNT(*) FROM TABLE時只需要直接讀取已經保存好的值而不需要進行全表掃描。如果表的讀操作遠遠多于寫操作且不需要數據庫事務的支持,那么MyIASM也是很好的選擇。

缺點:

就是不能在表損壞后恢復數據。(是不能主動恢復)

補充:ISAM索引方法--索引順序存取方法

定義:

是一個定義明確且歷經時間考驗的數據表格管理方法,它在設計之時就考慮到 數據庫被查詢的次數要遠大于更新的次數。

特性:

ISAM執行讀取操作的速度很快,而且不占用大量的內存和存儲資源。

在設計之初就預想數據組織成有固定長度的記錄,按順序存儲的。---ISAM是一種靜態索引結構。

缺點:

1.它不 支持事務處理

2.也不能夠容錯。如果你的硬盤崩潰了,那么數據文件就無法恢復了。如果你正在把ISAM用在關鍵任務應用程序里,那就必須經常備份你所有的實 時數據,通過其復制特性,MYSQL能夠支持這樣的備份應用程序。

(3)Memory(也叫HEAP)堆內存嘛:

定義

使用存在內存中的內容來創建表。每個MEMORY表只實際對應一個磁盤文件。MEMORY類型的表訪問非常得快,因為它的數據是放在內存中的,并且默認使用HASH索引。

但是一旦服務關閉,表中的數據就會丟失掉。 HEAP允許只駐留在內存里的臨時表格。駐留在內存里讓HEAP要比ISAM和MYISAM都快,但是它所管理的數據是不穩定的,而且如果在關機之前沒有進行保存,那么所有的數據都會丟失。在數據行被刪除的時候,HEAP也不會浪費大量的空間。HEAP表格在你需要使用SELECT表達式來選擇和操控數據的時候非常有用。

適用場景:

1)那些內容變化不頻繁的代碼表,或者作為統計操作的中間結果表,便于高效地堆中間結果進行分析并得到最終的統計結果。

2)目標數據比較小,而且非常頻繁的進行訪問,在內存中存放數據,如果太大的數據會造成內存溢出。可以通過參數max_heap_table_size控制Memory表的大小,限制Memory表的最大的大小。

3)數據是臨時的,而且必須立即可用得到,那么就可以放在內存中。

4)存儲在Memory表中的數據如果突然間丟失的話也沒有太大的關系。

注意: Memory同時支持散列索引和B樹索引,B樹索引可以使用部分查詢和通配查詢,也可以使用<,>和>=等操作符方便數據挖掘,散列索引相等的比較快但是對于范圍的比較慢很多。

特性要求:

1)要求存儲的數據是數據長度不變的格式,比如,Blob和Text類型的數據不可用(長度不固定的)。

2)要記住,在用完表格之后就刪除表格。

(4)Mrg_Myisam:(分表的一種方式--水平分表)

定義:

是一個相同的可以被當作一個來用的MyISAM表的集合。“相同”意味著所有表同樣的列和索引信息。

也就是說,他將MyIsam引擎的多個表聚合起來,但是他的內部沒有數據,真正的數據依然是MyIsam引擎的表中,但是可以直接進行查詢、刪除更新等操作。

比如:我們可能會遇到這樣的問題,同一種類的數據會根據數據的時間分為多個表,如果這時候進行查詢的話,就會比較麻煩,Merge可以直接將多個表聚合成一個表統一查詢,然后再刪除Merge表(刪除的是定義),原來的數據不會影響。

(5)Blackhole(黑洞引擎)

定義

任何寫入到此引擎的數據均會被丟棄掉, 不做實際存儲;Select語句的內容永遠是空。

他會丟棄所有的插入的數據,服務器會記錄下Blackhole表的日志,所以可以用于復制數據到備份數據庫。

使用場景

1)驗證dump file語法的正確性

2)以使用blackhole引擎來檢測binlog功能所需要的額外負載

3)充當日志服務器

其余引擎,大家感興趣就各自先百度吧。本文主要是對比引擎使用以及其原理。


三、InnoDB和MyIsam使用及其原理對比:

(1)使用的效果與區別展示:

MySQL數據庫實戰例子(存儲引擎、視圖、鎖機制、分表)

(一)在一個普通數據庫中創建兩張分別以MyIsam和InnoDB作為存儲引擎的表。

create table testMyIsam(  
id int unsigned primary key auto_increment,  
name varchar(20) not null  
)engine=myisam;  
 create table testInnoDB( 
 id int unsigned primary key auto_increment, 
 name varchar(20) not null 
 )engine=innodb;  


嘿嘿嘿,,效果如圖,一會總結。

這里寫圖片描述

(二)對比插入效率(百萬級插入):(雖然速度上MyISAM快,但是增刪改是涉及事務安全的,所以用InnoDB相對好很多)

為了更好地對比,我們可以使用函數的方式或者存儲過程的方式。博主采用存儲過程。(存儲過程在往后的章節會講到)

//創建存儲過程
delimiter $$
drop procedure if exists ptestmyisam;
create procedure ptestmyisam()
begin
declare pid int ;
set pid = 1000000;
while pid>0 
do
insert into testmyisam(name) values(concat("fuzhu", pid));
set pid = pid-1;
end while;
end $$

//使用存儲過程:
call ptestmyisam();
這里寫圖片描述
//創建存儲過程(盡量把Innodb的數量級壓低,不然,,卡在那里半天也不奇怪)
delimiter $$
drop procedure if exists ptestInndb;
create procedure ptestInndb()
begin
declare pid int ;
set pid = 1000000;
while pid>0 
do
insert into testinnodb(name) values(concat("fuzhu", pid));
set pid = pid-1;
end while;
end $$

//使用存儲過程:
call ptestInndb();

本博主在幾次innodb測試百萬插入的時候,數據庫炸了(笑哭)。最終只成功插入1W條。可見效率對比。

當然innodb默認是開啟事務的,如果我們把事務給停了,會快很多。

//停掉事務
set autocommit = 0;  
//調用存儲過程
call ptestInndb; 
//重啟事務
set autocommit = 1;  
這里寫圖片描述

(三)對比更新:(雖然速度上MyISAM快,但是增刪改是涉及事務安全的,所以InnoDB相對好很多)

//耗時3秒多
update testinnodb set name = 'fuzhu' where id>0 and id<10000;
//耗時0.171秒
update testmyisam set name = 'fuzhu' where id>0 and id<13525;

(四)查詢對比

1)查詢總數目

select count(*) from testInnoDB;  

select count(*) from testMyIsam;

這就是innodb查一萬跟myisam查一百萬的區別??效果對比立刻出現。

這里寫圖片描述

2)查詢無索引的列:(這些都自己拿我給出或者自己寫的數據庫去體驗下吧,,差距很明顯)

select * from testMyIsam where name > "fuzhu100" ;

select * from testInnoDB where name > "fuzhu100" ;

3)查詢有索引的列:

select * from testMyIsam where  id > 10 ;
select * from testinnodb where  id > 10 ;

4)存儲大小:

testMyIsam 存了一百萬。testinnodb 存了兩萬。

這里寫圖片描述

(2)效果對比總述:

1)事務。MyISAM類型不支持事務處理等高級處理,而InnoDB類型支持,提供事務支持已經外部鍵等高級數據庫功能。

InnoDB表的行鎖也不是絕對的,假如在執行一個SQL語句時MySQL不能確定要掃描的范圍,InnoDB表同樣會鎖全表,例如updatetable set num=1 where name like “a%”

就是說在不確定的范圍時,InnoDB還是會鎖表的。

2)性能主題。MyISAM類型的表強調的是性能,其執行數度比InnoDB類型更快。

3)行數保存。InnoDB 中不保存表的具體行數,也就是說,執行select count() fromtable時,InnoDB要掃描一遍整個表來計算有多少行,但是MyISAM只要簡單的讀出保存好的行數即可。注意的是,當count()語句包含where條件時,兩種表的操作是一樣的。

4)索引存儲。對于AUTO_INCREMENT類型的字段,InnoDB中必須包含只有該字段的索引,但是在MyISAM表中,可以和其他字段一起建立聯合索引。

MyISAM支持全文索引(FULLTEXT)、壓縮索引,InnoDB不支持

MyISAM的索引和數據是分開的,并且索引是有壓縮的,內存使用率就對應提高了不少。能加載更多索引,而Innodb是索引和數據是緊密捆綁的,沒有使用壓縮從而會造成Innodb比MyISAM體積龐大不小。
InnoDB存儲引擎被完全與MySQL服務器整合,InnoDB存儲引擎為在主內存中緩存數據和索引而維持它自己的緩沖池。InnoDB存儲它的表&索引在一個表空間中,表空間可以包含數個文件(或原始磁盤分區)。這與MyISAM表不同,比如在MyISAM表中每個表被存在分離的文件中。InnoDB 表可以是任何尺寸,即使在文件尺寸被限制為2GB的操作系統上。

5)服務器數據備份。InnoDB必須導出SQL來備份,LOAD TABLE FROM MASTER操作對InnoDB是不起作用的,解決方法是首先把InnoDB表改成MyISAM表,導入數據后再改成InnoDB表,但是對于使用的額外的InnoDB特性(例如外鍵)的表不適用。

而且MyISAM應對錯誤編碼導致的數據恢復速度快。MyISAM的數據是以文件的形式存儲,所以在跨平臺的數據轉移中會很方便。在備份和恢復時可單獨針對某個表進行操作。

InnoDB是拷貝數據文件、備份 binlog,或者用 mysqldump,在數據量達到幾十G的時候就相對痛苦了。

6)鎖的支持。MyISAM只支持表鎖。InnoDB支持表鎖、行鎖 行鎖大幅度提高了多用戶并發操作的新能。但是InnoDB的行鎖,只是在WHERE的主鍵是有效的,非主鍵的WHERE都會鎖全表的

//用于把表的拷貝從主服務器轉移到從屬服務器。
LOAD TABLE tbl_name FROM MASTER 

(3)使用建議:

以下兩點必須使用 InnoDB:

1)可靠性高或者要求事務處理,則使用InnoDB。這個是必須的。

2)表更新和查詢都相當的頻繁,并且表鎖定的機會比較大的情況指定InnoDB數據引擎的創建。

對比之下,MyISAM的使用場景:

1)做很多count的計算的。如一些日志,調查的業務表。

2)插入修改不頻繁,查詢非常頻繁的。

MySQL能夠允許你在表這一層應用數據庫引擎,所以你可以只對需要事務處理的表格來進行性能優化,而把不需要事務處理的表格交給更加輕便的MyISAM引擎。對于 MySQL而言,靈活性才是關鍵。


四、InnoDB和MyIsam引擎原理:

在此之前,先去理解什么是聚簇和非聚簇索引。

(1)MyIASM引擎的索引結構:

MyISAM索引結構: MyISAM索引用的B+ tree來儲存數據,MyISAM索引的指針指向的是鍵值的地址,地址存儲的是數據。

B+Tree的數據域存儲的內容為實際數據的地址,也就是說它的索引和實際的數據是分開的,只不過是用索引指向了實際的數據,這種索引就是所謂的非聚集索引。

圖取自博客

這里寫圖片描述

因此,過程為: MyISAM中索引檢索的算法為首先按照B+Tree搜索算法搜索索引,如果指定的Key存在,則取出其data域的值,然后以data域的值為地址,根據data域的值去讀取相應數據記錄。

(2)InnoDB引擎的索引結構:

也是B+Treee索引結構。Innodb的索引文件本身就是數據文件,即B+Tree的數據域存儲的就是實際的數據,這種索引就是聚集索引。這個索引的key就是數據表的主鍵,因此InnoDB表數據文件本身就是主索引。

InnoDB的輔助索引數據域存儲的也是相應記錄主鍵的值而不是地址,所以當以輔助索引查找時,會先根據輔助索引找到主鍵,再根據主鍵索引找到實際的數據。所以Innodb不建議使用過長的主鍵,否則會使輔助索引變得過大。

建議使用自增的字段作為主鍵,這樣B+Tree的每一個結點都會被順序的填滿,而不會頻繁的分裂調整,會有效的提升插入數據的效率。

這里寫圖片描述

上圖,可以看到葉節點包含了完整的數據記錄。這種索引叫做聚集索引。因為InnoDB的數據文件本身要按主鍵聚集,所以InnoDB要求表必須有主鍵(MyISAM可以沒有),如果沒有顯式指定,則MySQL系統會自動選擇一個可以唯一標識數據記錄的列作為主鍵,如果不存在這種列,則MySQL自動為InnoDB表生成一個隱含字段作為主鍵,這個字段長度為6個字節,類型為長整形。

而且,與MyISAM索引的不同是InnoDB的輔助索引data域存儲相應記錄主鍵的值而不是地址。換句話說,InnoDB的所有輔助索引都引用主鍵作為data域。

因此,過程為:將主鍵組織到一棵B+樹中,而行數據就儲存在葉子節點上,若使用”where id = 13”這樣的條件查找主鍵,則按照B+樹的檢索算法即可查找到對應的葉節點,之后獲得行數據。若對Name列進行條件搜索,則需要兩個步驟:第一步在輔助索引B+樹中檢索Name,到達其葉子節點獲取對應的主鍵。第二步使用主鍵在主索引B+樹種再執行一次B+樹檢索操作,最終到達葉子節點即可獲取整行數據。


五、剩余引擎的使用DEMO(主要是Mrg_Myisam分表)

Memory(Heap):

CREATE TABLE tbHeap (
id int unsigned primary key auto_increment,  
name varchar(20) not null  
) TYPE=Heap

(1)Mrg_Myisam引擎分表:

(一)先創建兩張user表,也就是說我要把用戶表進行水平分表(因為用戶太多啦,10億)

//用戶表一
CREATE TABLE IF NOT EXISTS `user1` (  
 `id` int(11) NOT NULL ,
 `name` varchar(50) DEFAULT NULL,  
 PRIMARY KEY (`id`)  
) ENGINE=MyISAM  DEFAULT CHARSET=utf8 ;  

//用戶表二
CREATE TABLE IF NOT EXISTS `user2` (  
 `id` int(11) NOT NULL ,
 `name` varchar(50) DEFAULT NULL,  
 PRIMARY KEY (`id`)  
) ENGINE=MyISAM  DEFAULT CHARSET=utf8 ;  

//分別插入兩條測試數據先
INSERT INTO `user1` (`name`) VALUES('輔助');  
INSERT INTO `user2` (`name`) VALUES('JackFrost');  

分表的要求:

1)分表必須使用MyISAM存儲引擎;

2)每個分表的表結構必須相同;

3)MySQL必須具有存儲分表數據文件和索引文件的目錄的讀寫權限;

4)必須啟用MySQL的符號鏈接支持功能。

文件存儲:

1)MYD文件是MyISAM表的數據文件;

2)MYI文件是MyISAM表的索引文件;

3)frm文件用于存儲MyISAM表的表結構。

(二)最后創建一個MERGE表,作為一個分發作用的總表。

CREATE TABLE IF NOT EXISTS `alluser` (  
  `id` int(11) NOT NULL ,  
  `name` varchar(50) DEFAULT NULL,  
   PRIMARY KEY (`id`)
) ENGINE=MRG_MYISAM  
DEFAULT CHARSET=utf8 
UNION=(user1,user2)  ;  

(三)測試:

1. 查詢:

select id,name from alluser;  

可見根據總表把所有數據都查出來了

這里寫圖片描述

2. 然而,當你測試插入的時候:

你會發現,總表只有只讀權限

這里寫圖片描述

3. 但是我們又想在總表去插入,怎么辦呢??

允許通過總表插入數據,數據存儲在MRG文件列出的第一個分表之中。例如,執行以下SQL語句,將總表的INSERT_METHOD修改為FIRST,然后通過總表插入一條數據:

//就是插入總表的時候,其實也是插入到第一個分表。
ALTER TABLE `test_engine`.`alluser` INSERT_METHOD = FIRST;


INSERT INTO `alluser` (id,`name`) VALUES(2,'插入到第一個分表');  
這里寫圖片描述

這里寫圖片描述

而,允許通過總表插入數據,數據存儲在MRG文件列出的最后一個分表之中。例如,執行以下SQL語句,將總表的INSERT_METHOD修改為LAST,然后通過總表插入一條數據:

//就是插入總表的時候,其實也是插入到最后一個分表。
ALTER TABLE `test_engine`.`alluser` INSERT_METHOD = LAST;
這里寫圖片描述

這里寫圖片描述

注意INSERT_METHOD :

INSERT_METHOD選項只會影響通過總表插入(INSERT)數據的行為,通過總表對數據進行刪除(DELETE)、查詢(SELECT)、修改(UPDATE)、清空(TRUNCATE)都不會受影響。

(2)項目中如何使用MRG_MYISAM總表:

(一)插入(INSERT)數據時,需要根據給定的路由策略將新數據分別插入不同的子表,此處采用對id進行模3計算(可能結果為0、1、2)來決定插入哪個子表。

所以我們需要創建一張表專門去創建id。

CREATE TABLE `create_id` (
    `id` INT(11) NOT NULL AUTO_INCREMENT,
    PRIMARY KEY (`id`)
)
COLLATE='utf8_general_ci'
ENGINE=MyISAM
;

(二)ORM框架的時候使用上面這個表生成id

insert into create_id () values();

(三)真正插入的時候:

先獲取ID,然后根據拿到的創建ID去插入到分表。

INSERT INTO {$table_name} (id, name) VALUES ('{$id}');

(四)獲取表名和ID:

這個就需要我們自定義自己的規則了。比如取余、比如范圍預判斷。

其他的刪除(DELETE)、查詢(SELECT)、修改(UPDATE)、清空(TRUNCATE)等操作都可以通過總表alluser完成。

基于MRG_MYISAM存儲引擎實現的分表機制,比較適用于插入和查詢頻率較高的場景。由于MyISAM具有表級別的鎖機制,所以不適用于更新頻率較高的場景。

(3)MRG_MYISAM分表的優點:

(一)適用于存儲日志數據。例如,可以將不同月份的數據存入不同的表,然后使用一些工具壓縮數據,最后通過一張MRG_MYISAM表來查詢這些數據。

(二)可以獲得更快的速度。可以根據某種指標,將一張只讀的大表分割成若干張小表,然后將這些小表分別放在不同的磁盤上存儲。當需要讀取數據時,MERGE表可以將這些小表的數據組織起來,就好像使用先前的大表一樣,但是速度會快很多。

(三)可以提高搜索效率。可以根據某種指標將一張只讀的大數據表分割為若干個小表,然后根據不同的查詢維度,可以得到若干種小表的組合,然后再為這些組合分別創建不同的MERGE表。例如,有一張只讀的大數據表T,分割為T1、T2、T3、T4,共4張小表,有兩種查詢維度A和B,A可以得到小表組合T1、T2和T3,B可以得到小表組合T2、T3和T4,分別為A和B創建兩個MERGE表,也就是M1和M2,這兩個MERGE表分別關聯的小表是存在交疊的。

(四)可以更加有效的修復表。修復單個的小表要比修復大數據表更加容易。

(五)多個子表映射至一個總表的速度極快。因為MERGE表本身不會存儲和維護任何索引,索引都是由各個關聯的子表存儲和維護的,所以創建和重新映射MERGE表的速度非常快。

(六)不受操作系統的文件大小限制。單個表會受到文件大小的限制,但是拆分成多個表,則可以無限擴容。

(七)MERGE表還可以用來給單個表創建別名,并且幾乎不會影響性能。

(4)使用MRG_MyISAM分表的必須思考問題:(針對總表)

(一)總表(MERGE表)必須使用MRG_MyISAM存儲引擎,子表必須使用MyISAM存儲引擎,不可避免會受到MyISAM存儲引擎的限制。(比如不支持事務)

(二)MERGE表不能使用某些MyISAM特性。例如,雖然可以為子表創建全文索引,但是卻不能使用全文索引,只能通過MERGE表查詢數據。

(三)若使用ALTER TABLE語句修改總表的存儲引擎,那么會立即丟失總表和子表的映射關系,并且會將所有子表的數據拷貝至修改后的新表。

(四)總表和子表的主鍵都不能使用自動增長(auto increment)。

(五)子表之間不能保證唯一鍵約束,只能保證單個子表內部的唯一性約束。也就是說,直接查總表全部,id可能會重復。

(六)由于不能保證唯一鍵約束,導致REPLACE語句的行為會不可預期,INSERT ... ON DUPLICATE KEY UPDATE語句也有類似問題。因此,只能使用路由策略,對子表使用這些語句,而不能對總表使用。

(七)當正在使用總表時,不能對任何子表執行ANALYZE TABLE、REPAIR TABLE、OPTIMIZE TABLE、ALTER TABLE、DROP TABLE、DELETE或TRUNCATE TABLE語句,否則會導致不可預期的結果。

(八)總表和子表的表結構必須完全一致。

(九)總表可以映射的所有子表的總行數上限為 2的64次方 行。

(十)不支持INSERT DELAYED語句。


數據庫DEMO下載:MySQL數據庫實戰例子(存儲引擎、視圖、鎖機制、分表)

好了,MySQL優化筆記(五)--數據庫存儲引擎(主要分析對比InnoDB和MyISAM)講完了,又是一篇數據庫優化記錄,這是積累的必經一步,我會繼續出這個系列文章,分享經驗給大家。歡迎在下面指出錯誤,共同學習!!你的點贊是對我最好的支持!!

更多內容,可以訪問JackFrost的博客

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,363評論 6 532
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,497評論 3 416
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,305評論 0 374
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,962評論 1 311
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,727評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,193評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,257評論 3 441
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,411評論 0 288
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,945評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,777評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,978評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,519評論 5 359
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,216評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,642評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,878評論 1 286
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,657評論 3 391
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,960評論 2 373

推薦閱讀更多精彩內容