天天看点

【Mysql 学习】memory存储引擎

      MEMORY存储引擎用存在内存中的内容来创建表。每个MEMORY表和一个磁盘文件关联起来。文件名由表的名字开始,并且由一个.frm的扩展名来指明它存储的表定义。

要创建一个MEMORY表,可使用如下语句:

CREATE TABLE t (i INT) ENGINE = MEMORY;

   如它们名字所指明的,MEMORY表被存储在内存中,且默认使用哈希索引。这使得它们非常快,并且对创建临时表非常有用。可是,当服务器关闭之时,所有存储在MEMORY表里的数据被丢失。因为表的定义被存在磁盘上的.frm文件中,所以表自身继续存在,在服务器重启动时它们是空的。

这个例子显示你如何可以创建,使用并删除一个MEMORY表:

mysql> create table tab_memory engine=memory

    -> select id1,id2 ,val

    -> from myisam_auto;

Query OK, 9 rows affected (0.38 sec)

Records: 9  Duplicates: 0  Warnings: 0

MEMORY表有下列特征:

·以小块来分配MEMORY表的空间。表对插入使用100%动态哈希来。不需要溢出区或额外键空间。自由列表无额外的空间需求。已删除的行被放在一个以链接的列表里,并且在往表里插入新数据之时被重新使用。MEMORY表也没有通常与在哈希表中删除加插入相关的问题。

·MEMORY表可以有多达每个表32个索引,每个索引16列,以及500字节的最大键长度。

·MEMORY存储引擎执行HASH和BTREE索引。你可以通过添加一个如下所示的USING子句为给定的索引指定一个或另一个:

·CREATE TABLE lookup(id INT, INDEX USING HASH (id))ENGINE = MEMORY;

·CREATE TABLE lookup(id INT, INDEX USING BTREE (id)) ENGINE = MEMORY;

也可以使用如下语句创建:

mysql> create index mem_hash using hash on tab_memory(id1);

Query OK, 9 rows affected (0.06 sec)

mysql> show index from tab_memory\G

*************************** 1. row ***************************

       Table: tab_memory

  Non_unique: 1

    Key_name: mem_hash

Seq_in_index: 1

 Column_name: id1

   Collation: NULL

 Cardinality: 3

    Sub_part: NULL

      Packed: NULL

        Null:

  Index_type: HASH

     Comment:

1 row in set (0.00 sec)

mysql> drop index mem_hash on tab_memory;

Query OK, 9 rows affected (0.08 sec)

mysql> create index mem_hash using BTREE on tab_memory(id1);

   Collation: A

 Cardinality: NULL

  Index_type: BTREE

1 row in set (0.02 sec)

B树的一般特征和哈希索引将在以后的博客中描述。

· 可以在一个MEMORY表中有非唯一键。(对哈希索引的实现,这是一个不常用的功能)。

· 可以对MEMORY表使用INSERT DELAYED。

· 如果你在一个有高度键重复的(许多索引条目包含同一个值)MEMORY表上有一个哈希索引,对影响键值的表的更新及所有删除都是明显地慢的。这个变慢的程度比例于重复的程度(或者反比于索引cardinality)。你可以使用一个B树索引来避免这个问题。

·MEMORY表使用一个固定的记录长度格式。

·MEMORY不支持BLOB或TEXT列。

·MEMORY支持AUTO_INCREMENT列和对可包含NULL值的列的索引。

·MEMORY表在所有客户端之间共享(就像其它任何非TEMPORARY表)。

·MEMORY表内容被存在内存中,内存是MEMORY表和服务器在查询处理之时的空闲中创建的内部表共享。可是,两个类型的表不同在于MEMORY表不会遇到存储转换,而内部表是:

- 如果一个内部表变得太大,服务器自动把它转换为一个磁盘表。尺寸限制由tmp_table_size系统变量的值来确定。

- MEMORY表决不会转换成磁盘表。要确保你不会偶尔做点傻事,你可以设置max_heap_table_size系统变量给MEMORY表加以最大尺寸。对于单个的表,你也可以在CREATE TABLE语句中指定一个MAX_ROWS表选项。

·服务器需要足够内存来维持所有在同一时间使用的MEMORY表。

·当你不再需要MEMORY表的内容之时,要释放被MEMORY表使用的内存,你应该执行DELETE FROM或TRUNCATE TABLE,或者整个地删除表(使用DROP TABLE)。

·当MySQL服务器启动时,如果你想开拓MEMORY表,你可以使用--init-file选项。例如,你可以把INSERT INTO ... SELECT 或LOAD DATA INFILE这样的语句放入这个文件中以便从持久稳固的的数据源装载表。 LOAD DATA INFILE 'data.txt' INTO TABLE db2.my_table;

·如果你正使用复制,当主服务器被关闭且重启动之时,主服务器的MEMORY表变空。可是从服务器意识不到这些表已经变空,所以如果你从它们选择数据,它就返回过时的内容。自从服务器启动后,当一个MEMORY表在主服务器上第一次被使用之时,一个DELETE FROM语句被自动写进主服务器的二进制日志,因此再次让从服务器与主服务器同步。注意,即使使用这个策略,在主服务器的重启和它第一次使用该表之间的间隔中,从服务器仍旧在表中有过时数据。可是,如果你使用--init-file选项于主服务器启动之时在其上推行MEMORY表。它确保这个时间间隔为零。

·在MEMORY表中,一行需要的内存使用下列表达式来计算:

SUM_OVER_ALL_BTREE_KEYS(max_length_of_key + sizeof(char*) * 4)+SUM_OVER_ALL_HASH_KEYS(sizeof(char*) * 2)+ ALIGN(length_of_row+1, sizeof(char*))

ALIGN()代表round-up因子,它使得行的长度为char指针大小的确切倍数。sizeof(char*)在32位机器上是4,在64位机器上是8。