除Innodb和MyISAM外MySQL所支持的存儲引擎
CSV存儲引擎可以將CSV文件作為mysql表來處理,存儲格式就是普通的CSV文件。如果把數據存儲在myisam和Innodb中,存儲數據的文件是不能直接查看的,因為這兩種存儲引擎都是以二進制文件存儲的。而CSV是以文本方式存儲的,CSV是不支持索引的,查找的時候要進行全表掃描。
文件系統存儲特點:
- 數據以文本方式存儲在文件中(Innodb則是二進制)
- .CSV文件存儲表內容
- .CSM文件存儲表的元數據如表狀態和數據量
- .frm文件存儲表結構信息
CSV存儲引擎特點:
- 以CSV格式進行數據存儲(逗號隔開,引號)
- 所有的列必須都是不能為NULL的
- 不支持索引,所以CSV不適合大表,不適合在線處理類型的應用
- 可以對數據文件直接編輯,因為CSV存儲的是文本內容
- 不支持事務,不支持保存點,不支持XA事務(兩階段提交)
接下來我們創建一張使用CSV存儲引擎的表,但是不指定 not null 看看會發生什麽:
mysql> create table mycsv(id int,c1 varchar(10),c2 char(20)) engine=csv;
ERROR 1178 (42000): The storage engine for the table doesn‘t support nullable columns
mysql>
可以看到,不指定 not null 就會報錯,所以需要指定所有的列為 not null :
mysql> create table mycsv(id int not null ,c1 varchar(10) not null,c2 char(20) not null) engine=csv;
Query OK, 0 rows affected (0.01 sec)
mysql>
然後我們向表中插入一些數據:
mysql> insert into mycsv values ( 1,‘aaa‘,‘bbb‘),(2,‘ccc‘,‘ddd‘); Query OK, 2 rows affected (0.00 sec) Records: 2 Duplicates: 0 Warnings: 0 mysql> select * from mycsv; +----+-----+-----+ | id | c1 | c2 | +----+-----+-----+ | 1 | aaa | bbb | | 2 | ccc | ddd | +----+-----+-----+ 2 rows in set (0.01 sec)
我們查看一下文件系統裏生成的文件以及mycsv.CSV文件的內容:
[root@01server /data/mysql/test_database]# ls mycsv.*
mycsv.CSM mycsv.CSV mycsv.frm
[root@01server /data/mysql/test_database]# cat mycsv.CSV
1,"aaa","bbb"
2,"ccc","ddd"
[root@01server /data/mysql/test_database]#
從cat出來的內容可以看到,該文件的內容是文本格式的,我們來追加一行數據到該文件的末尾
[root@01server /data/mysql/test_database]# echo ‘3,"eee","fff"‘ >> mycsv.CSV
然後回到數據庫中查看mycsv表的內容,會發現我們追加到文件的末尾的數據已經添加到了mycsv表中:
mysql> select * from mycsv;
+----+-----+-----+
| id | c1 | c2 |
+----+-----+-----+
| 1 | aaa | bbb |
| 2 | ccc | ddd |
| 3 | eee | fff |
+----+-----+-----+
3 rows in set (0.00 sec)
之前提到了CSV是不支持索引的,我們來看看如果增加索引會發生什麽:
mysql> create index idx_id on mycsv(id);
ERROR 1069 (42000): Too many keys specified; max 0 keys allowed
mysql>
可以看到報錯了,證明的確是不支持索引的
CSV存儲引擎的適用場景:
適合做為數據交換的中間表,能夠在服務器運行的時候,拷貝和拷出文件,可以將電子表格存儲為CSV文件再拷貝到MySQL數據目錄下,就能夠在數據庫中打開和使用。同樣,如果將數據寫入到CSV文件數據表中,其它web程序也可以迅速讀取到數據。
MySQL常用存儲引擎之Archive
從archive單詞的解釋我們大概可以明白這個存儲引擎的用途,這個存儲引擎基本上用於數據歸檔;它的壓縮比非常的高,存儲空間大概是innodb的10-15分之一所以它用來存儲歷史數據非常的適合,由於它不支持索引同時也不能緩存索引和數據,所以它不適合作為並發訪問表的存儲引擎。Archivec存儲引擎使用行鎖來實現高並發插入操作,但是它不支持事務,其設計目標只是提供高速的插入和壓縮功能。
文件系統存儲特點:
- 以zlib對表數據進行壓縮,磁盤I/O更少
- 數據存儲在ARZ為後綴的文件中
Archiv存儲引擎的特點:
- 只支持insert、replace和select操作,但不支持update和delete操作
- archive支持行級鎖和緩沖區,可以實現高並發的插入
- archive存儲引擎支持blob、text等大字段類型
- archive支持自增列,但是不支持往自增列插入一個小於當前最大的值的值
- 只允許在自增ID列上加索引,同時自增列可以不是唯一索引
存儲特點:
往archive表插入的數據會經過壓縮,archive使用zlib進行數據壓縮,archive支持optimize table、 check table操作。
一個insert語句僅僅往壓縮緩存中插入數據,插入的數據在壓縮緩存中被鎖定,當select操作時會觸發壓縮緩存中的數據進行刷新。insert delay除外。
對於一個bulk insert操作只有當它完全執行完才能看到記錄,除非在同一時刻還有其它的inserts操作,在這種情況下可以看到部分記錄,select從不刷新bulk insert除非在它加載時存在一般的Insert操作。
檢索特點:
對於檢索請求返回的行不會壓縮,且不會進行數據緩存;一個select查詢會執行完整的表掃描;當一個select查詢發生時它查找當前表所有有效的行,select執行一致性讀操作,註意,過多的select查詢語句會導致壓縮插入性能變的惡化,除非使用bulk insert或delay insert,可以使用OPTIMIZE TABLE 或REPAIR TABLE來獲取更好的壓縮,可以使用SHOW TABLES STATUS查看ARCHIVE表的記錄行。
相同數量級下,Archive表比MyISAM表要小大約75%,比支持事務處理的InnoDB表小大約83%。當數據量非常大的時候Archive的插入性能表現會較MyISAM為佳。
Archive表的性能是否可能超過MyISAM?答案是肯定的。根據MySQL工程師的資料,當表內的數據達到1.5GB這個量級,CPU又比較快的時候,Archive表的執行性能就會超越MyISAM表。因為這個時候,CPU會取代I/O子系統成為性能瓶頸。別忘了Archive表比其他任何類型的表執行的物理I/O操作都要少。
較小的空間占用也能在你移植MySQL數據的時候發揮作用。當你需要把數據從一臺MySQL服務器轉移到另一臺的時候,Archive表可以方便地移植到新的MySQL環境,你只需將保存Archive表的底層文件復制過去就可以了。
接下來我們創建一張使用Archive存儲引擎的表:
mysql> create table myarchive( id int auto_increment not null , c1 varchar(10),c2 char(10), primary key(id)) engine = archive;
Query OK, 0 rows affected (0.00 sec)
然後查看文件系統,會發現存在兩個文件,.ARZ文件存儲表內容,.frm文件則存儲表結構:
[root@01server /data/mysql/test_database]# ls myarchive.*
myarchive.ARZ myarchive.frm
[root@01server /data/mysql/test_database]#
回到數據庫中,我們往數據表裏插入一些數據:
mysql> insert into myarchive (c1,c2) values (‘aa‘,‘bb‘),(‘cc‘,‘dd‘);
Query OK, 2 rows affected (0.00 sec)
Records: 2 Duplicates: 0 Warnings: 0
mysql> select * from myarchive;
+----+------+------+
| id | c1 | c2 |
+----+------+------+
| 1 | aa | bb |
| 2 | cc | dd |
+----+------+------+
2 rows in set (0.01 sec)
mysql>
如上文所說,雖然我們可以進行插入和查詢操作,但是刪除和更新操作是不支持的:
mysql> delete from myarchive where id = 1;
ERROR 1031 (HY000): Table storage engine for ‘myarchive‘ doesn‘t have this option
mysql> update myarchive set c1=‘aaaa‘ where id =1;
ERROR 1031 (HY000): Table storage engine for ‘myarchive‘ doesn‘t have this option
mysql>
也無法在非自增鍵上創建索引:
mysql> create index idx_c1 on myarchive(c1);
ERROR 1069 (42000): Too many keys specified; max 1 keys allowed
mysql>
使用場景:
日誌和數據采集類應用(不支持OLTP)
MySQL常用存儲引擎之Memory
MEMORY是MySQL中一類特殊的存儲引擎,稱HEAP存儲引擎,所以數據保存在內存中(服務器重啟則表的數據丟失,但是表結構是保留的,表結構保存在磁盤文件中,而表的內容是存儲在內存中)。基本上使用Memory存儲引擎的出發點是速度,為得到最快的響應時間。因為其基於內存中的特性,這類表的處理速度會非常快,但是,其數據易丟失,生命周期短。基於其這個缺陷,選擇Memory存儲引擎時需要特別小心。
每個基於MEMORY存儲引擎的表實際對應一個磁盤文件。該文件的文件名與表名相同,類型為frm類型。該文件中只存儲表的結構。而其數據文件,都是存儲在內存中,這樣有利於數據的快速處理,提高整個表的效率。值得註意的是,服務器需要有足夠的內存來維持MEMORY存儲引擎的表的使用。如果不需要了,可以釋放內存,甚至刪除不需要的表。MEMORY默認使用哈希索引,速度比使用B型樹索引快。當然如果你想用B型樹索引,可以在創建索引時指定。
Memory存儲引擎通常很少用到,至少我是沒有用到過。因為Memory表的所有數據都是存儲在內存上的,如果內存出現異常會影響到數據的完整性。如果重啟機器或者關機,表中的所有數據都將消失,因此,基於Memory存儲引擎的表的生命周期都比較短,一般都是一次性的。
Memory表的大小是受到限制的,表的大小主要取決於2個參數,分別是max_rows
和max_heap_table_size
。其中,max_rows
可以在創建表時指定,max_heap_table_size
的大小默認為16MB,可以按需要進行擴大。
Memory存儲引擎的功能特點總結:
- 支持HASH索引(等值查詢快)和BTree索引(範圍查找快),默認為HASH
- 所有字段都為固定長度,就算是使用varchar也會被轉換成char類型,
varchar(10) -> char(10)
- 不支持BLOG和TEXT等大字段
- Memory存儲引擎使用的是表級鎖,不是行級鎖
- Memory表的最大大小由
max_heap_table_size
參數決定(默認16M,但是對存在的表修改是無效的)
接下來我們創建一張使用Memory存儲引擎並且使用TEXT字段的表,看看會不會報錯:
mysql> create table mymemory (id int,c1 varchar(10),c2 char(10),c3 text ) engine = memory;
ERROR 1163 (42000): The used table type doesn‘t support BLOB/TEXT columns
mysql>
從報錯的信息中可以看到,明確說明了不支持BLOG和TEXT字段。那麽我們就來創建一張正常的Memory表吧:
mysql> create table mymemory (id int,c1 varchar(10),c2 char(10) ) engine = memory;
Query OK, 0 rows affected (0.00 sec)
然後我們進入文件系統,可以看到只有一個保存表結構的文件,並沒有用於保存數據的文件:
[root@01server /data/mysql/test_database]# ls mymemory.*
mymemory.frm
[root@01server /data/mysql/test_database]#
以上我們提到了Memory引擎默認使用HASH索引,但也可以指定創建BTree索引,我們來創建兩個索引看看:
mysql> create index idx_c1 on mymemory(c1);
Query OK, 0 rows affected (0.00 sec)
Records: 0 Duplicates: 0 Warnings: 0
mysql> create index idx_c2 using btree on mymemory(c2);
Query OK, 0 rows affected (0.01 sec)
Records: 0 Duplicates: 0 Warnings: 0
mysql>
查看一下當前索引類型,可以看到存在兩個索引,一個為默認的HASH,一個是指定的BTree:
mysql> show index from mymemory \G
*************************** 1. row ***************************
Table: mymemory
Non_unique: 1
Key_name: idx_c1
Seq_in_index: 1
Column_name: c1
Collation: NULL
Cardinality: 0
Sub_part: NULL
Packed: NULL
Null: YES
Index_type: HASH
Comment:
Index_comment:
*************************** 2. row ***************************
Table: mymemory
Non_unique: 1
Key_name: idx_c2
Seq_in_index: 1
Column_name: c2
Collation: A
Cardinality: NULL
Sub_part: NULL
Packed: NULL
Null: YES
Index_type: BTREE
Comment:
Index_comment:
2 rows in set (0.00 sec)
mysql>
我們再查看一下表的狀態:
mysql> show table status like ‘mymemory‘\G
*************************** 1. row ***************************
Name: mymemory
Engine: MEMORY
Version: 10
Row_format: Fixed # 固定長度
Rows: 0
Avg_row_length: 26
Data_length: 0
Max_data_length: 4793490
Index_length: 0
Data_free: 0
Auto_increment: NULL
Create_time: 2018-10-10 15:45:18
Update_time: NULL
Check_time: NULL
Collation: latin1_swedish_ci
Checksum: NULL
Create_options:
Comment:
1 row in set (0.00 sec)
mysql>
Memory存儲引擎表和臨時表的區別:
臨時表分兩類:系統為了優化查詢所生成的臨時表和使用
create temporary table
語句建立的臨時表。無論哪種表,只有當前session是可見的。而Memory表是所有線程都可以使用的,所以Memory表並不屬於臨時表。系統使用臨時表又分為兩類:超過內存限制時使用MyISAM臨時表,未超過限制時則會使用Memory表。
使用場景:
- 用於查找或者是映射表,例如郵編和地區的對應表
- 用於保存數據分析中產生的中間表
- 用於緩存周期性聚合數據的結果表
註意一點是:Memory數據易丟失,所以要求存儲的數據都是可再生的
MySQL常用存儲引擎之Federated
mysql 提供了一個類似Oracle中的數據庫鏈接(DBLINK)功能的存儲引擎--Federated,使得可以不使用replication或cluster技術,直接遠程服務器主機的數據表。當我們創建一個以Federated為存儲引擎的表時,服務器在數據庫目錄只創建一個表定義文件。文件由表的名字開始,並有一個frm擴展名。無其它文件被創建,因為實際的數據在一個遠程數據庫上。這不同於為本地表工作的存儲引擎的方式。
Federated 存儲引擎允許訪問遠程MySQL數據庫中的數據,Federated 僅支持表級別的遠程訪問。本地的Federated表中不存儲數據,訪問本地表時,會自動從遠程表中獲取數據。因為使用Federated 存儲引擎的表,本地只存儲表的結構信息,數據都存放在遠程數據庫上,查詢時通過建表時指定的連接符去獲取遠程庫的數據返回到本地。
Federated存儲引擎特點總結:
- 提供了訪問遠程MySQL服務器上表的方法(連接)
- 本地不存儲數據,數據全部放到遠程服務器上
- 本地需要保存表結構(frm文件)和遠程服務器的連接信息
實現原理:
通過創建存儲引擎為Federated 的表來實現遠程共享服務器表數據。Federated:能夠將多個分離(不在同一臺服務器上的機器)的MySQL服務器鏈接起來,從多個物理服務器創建一個邏輯數據庫。十分適合於分布式環境或數據集市環境。
Federated 存儲引擎架構圖:
- 本地服務器 Federated 存儲引擎的表只存放表的.frm結構文件
- 遠程服務器 存放了.frm和數據文件
- 增刪改查操作都是通過建立的連接來訪問遠程數據庫進行操作,把結果返回給本地。
- 遠程數據表的存儲引擎為MySQL支持的存儲引擎,如MyISAM、InnoDB等
Federated 存儲引擎的性能並不是很好,而且可以使用復制的方式來實現 Federated 的功能,所以目前的mysql版本默認是不開啟的,可以使用如下語句查看是否開啟了Federated:
show engines;
執行結果如下, FEDERATED 中Support狀態NO表明引擎未開啟:
需要在MySQL服務的配置中增加federated參數來開啟 [ /etc/my.cnf ] ,如下:
[mysqld]
federated
配置好後重啟 MySQL 再次查看,FEDERATED 中Support狀態成YES表明引擎開啟成功:
由於我這裏只有一臺機器,所以將在本地進行模擬,首先創建如下兩個數據庫:
mysql> create database local;
Query OK, 1 row affected (0.00 sec)
mysql> create database remote;
Query OK, 1 row affected (0.00 sec)
mysql>
在remote庫中,創建一張表格以及插入相應的測試數據,還需要創建一個用戶,如下:
mysql> create table remote_fed(id int auto_increment not null, c1 varchar(10) not null default ‘‘, c2 char(10) not null default ‘‘, primary key(id))engine=innodb;
Query OK, 0 rows affected (0.03 sec)
mysql> insert into remote_fed(c1,c2) values(‘aaa‘,‘bbb‘),(‘ccc‘,‘ddd‘),(‘ddd‘,‘fff‘);
Query OK, 3 rows affected (0.01 sec)
Records: 3 Duplicates: 0 Warnings: 0
mysql> grant select,update,delete,insert on remote.remote_fed to fred_link@‘127.0.0.1‘ identified by ‘123456‘; -- 創建一個用戶
Query OK, 0 rows affected (0.00 sec)
mysql>
完成以上操作後,就可以使用以下語句進行連接了:
mysql://user_name[:password]@host_name[:port_num]/db_name/tbl_name
- user_name 遠程mysql的用戶名
- password 遠程mysql的密碼
- host_name 遠程mysql的主機地址(ip)
- port_num 遠程mysql的端口後
- db_name 需要連接的數據庫
- tbl_name 需要映射的表格
進入local庫,創建與remote.remote_fed
一樣的表結構的表,不同的是需要選擇federated存儲引擎,並且加上連接信息,如下:
mysql> use local;
Database changed
mysql> create table local_fed(id int auto_increment not null, c1 varchar(10) not null default ‘‘, c2 char(10) not null default ‘‘, primary key(id))engine=federated connection=‘mysql://fred_link:[email protected]:3306/remote/remote_fed‘;
Query OK, 0 rows affected (0.01 sec)
mysql>
然後我們來select這張表的數據,看看能否正常查找出remote.remote_fed
表裏的數據,如下:
mysql> select * from local.local_fed;
+----+-----+-----+
| id | c1 | c2 |
+----+-----+-----+
| 1 | aaa | bbb |
| 2 | ccc | ddd |
| 3 | ddd | fff |
+----+-----+-----+
3 rows in set (0.00 sec)
mysql>
可以看到,顯示的是remote.remote_fed
表裏的數據,我們再來測試一下delete語句,看看刪除local.local_fed
表裏的數據後,remote.remote_fed
表是否會跟著刪除:
mysql> delete from local.local_fed where id = 3;
Query OK, 1 row affected (0.01 sec)
mysql>
切換到remote庫,查看remote.remote_fed
表裏的數據,可以看到,id為3的數據已經被刪除了:
mysql> use remote;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A
Database changed
mysql> select * from remote.remote_fed;
+----+-----+-----+
| id | c1 | c2 |
+----+-----+-----+
| 1 | aaa | bbb |
| 2 | ccc | ddd |
+----+-----+-----+
2 rows in set (0.00 sec)
mysql>
上文中提到本地不會存儲遠程表的數據,這一點我們可以通過查看文件系統來證實,如下可以看到只存在一個用於存儲表結構的.frm文件:
[root@01server /data/mysql]# ls local/
db.opt local_fed.frm
[root@01server /data/mysql]#
使用場景:
由於其性能問題,不適用於生產環境中,只能用於偶爾的統計分析及手動查詢
除Innodb和MyISAM外MySQL所支持的存儲引擎