1. 程式人生 > >除Innodb和MyISAM外MySQL所支持的存儲引擎

除Innodb和MyISAM外MySQL所支持的存儲引擎

數據庫鏈 所有 取代 語句 nali RoCE sql數據庫 增刪改查操作 可見

MySQL常用存儲引擎之CSV

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_rowsmax_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 存儲引擎架構圖:
技術分享圖片

  1. 本地服務器 Federated 存儲引擎的表只存放表的.frm結構文件
  2. 遠程服務器 存放了.frm和數據文件
  3. 增刪改查操作都是通過建立的連接來訪問遠程數據庫進行操作,把結果返回給本地。
  4. 遠程數據表的存儲引擎為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所支持的存儲引擎