• 首页
  • vue
  • TypeScript
  • JavaScript
  • scss
  • css3
  • html5
  • php
  • MySQL
  • redis
  • jQuery
  • MEMORY存储引擎

    MEMORY存储引擎(以前称为HEAP)创建具有存储在存储器中的内容的专用的表。由于数据容易受到崩溃,硬件问题或电源中断的影响,因此只能将这些表用作临时工作区或只读缓存,以存储从其他表中提取的数据。

    MEMORY存储引擎功能

    特征支持
    B树索引
    备份/时间点恢复(在服务器中而不是在存储引擎中实现。)
    集群数据库支持没有
    聚集索引没有
    压缩数据没有
    资料快取不适用
    加密数据是(通过加密功能在服务器中实现。)
    外键支持没有
    全文搜索索引没有
    地理空间数据类型支持没有
    地理空间索引支持没有
    哈希索引
    索引缓存不适用
    锁定粒度
    MVCC没有
    复制支持(在服务器中而不是在存储引擎中实现。)受限(请参阅本节后面的讨论。)
    储存限制内存
    T树索引没有
    交易次数没有
    更新数据字典的统计信息

    • 何时使用MEMORY或NDB群集
    • 分区
    • 性能特点
    • 内存表的特征
    • 内存表的DDL操作
    • 指标
    • 用户创建的临时表
    • 加载数据中
    • 内存表和复制
    • 管理内存使用
    • 其他资源

    何时使用MEMORY或NDB群集

    希望部署使用MEMORY存储引擎存储重要,高可用性或经常更新的数据的应用程序的开发人员应考虑NDB Cluster是否是更好的选择。MEMORY引擎的典型用例涉及以下特征:

    • 涉及瞬态,非关键数据的操作,例如会话管理或缓存。当MySQL服务器停止或重新启动时,MEMORY表中的数据将丢失。
    • 内存中存储可实现快速访问和低延迟。数据量可以完全容纳在内存中,而不会导致操作系统换出虚拟内存页面。
    • 只读或只读的数据访问模式(有限的更新)。

    NDB Cluster提供了与MEMORY具有更高性能级别的引擎相同的功能,并提供了以下功能不可用的其他功能MEMORY

    • 行级锁定和多线程操作可减少客户端之间的争用。
    • 即使包含写的语句混合也具有可伸缩性。
    • 可选的磁盘支持操作,可确保数据持久性。
    • 无共享架构和多主机操作,没有单点故障,可实现99.999%的可用性。
    • 跨节点自动数据分发;应用程序开发人员无需制定自定义分片或分区解决方案。
    • 不支持可变长度数据类型(包括BLOBTEXTMEMORY

    分区

    MEMORY表不能分区。

    性能特点

    MEMORY性能受到单线程执行和处理更新时表锁开销所导致的争用的限制。当负载增加时,这会限制可伸缩性,尤其是对于包含写入的语句混合。

    尽管对MEMORY表进行内存内处理,但InnoDB对于一般性查询或在读/写工作负载下,表不一定比繁忙服务器上的表快。特别是,执行更新所涉及的表锁定可能会减慢MEMORY来自多个会话的表的并发使用。

    根据对MEMORY表执行的查询的类型,您可以将索引创建为默认哈希数据结构(用于基于唯一键查找单个值)或通用B树数据结构(用于所有类型的索引)。涉及相等,不相等或范围运算符(例如小于或大于)的查询。以下各节说明了创建两种索引的语法。一个常见的性能问题是在B树索引更有效的工作负载中使用默认哈希索引。

    内存表的特征

    MEMORY存储引擎不磁盘上创建任何文件。表定义存储在MySQL数据字典中。

    MEMORY表具有以下特征:

    • MEMORY表的空间以小块分配。表对插入使用100%动态哈希。不需要溢出区域或额外的密钥空间。空闲列表不需要额外的空间。删除的行将放入链接列表中,并在将新数据插入表中时被重复使用。MEMORY表也没有散列表中通常与删除和插入相关的问题。
    • MEMORY表使用固定长度的行存储格式。可变长度类型(例如,VARCHAR使用固定长度存储)。
    • MEMORY表不能包含BLOBTEXT列。
    • MEMORY包括对AUTO_INCREMENT列的支持。
    • TEMPORARYMEMORY就像其他任何非TEMPORARY表一样,非表在所有客户端之间共享。

    内存表的DDL操作

    要创建MEMORY表,请ENGINE=MEMORYCREATE TABLE语句中指定子句。

    CREATE TABLE t (i INT) ENGINE = MEMORY;
    

    如引擎名称所示,MEMORY表存储在内存中。默认情况下,它们使用哈希索引,这使它们对于单值查找非常快,并且对于创建临时表非常有用。但是,当服务器关闭时,MEMORY表中存储的所有行都会丢失。这些表本身继续存在,因为它们的定义存储在MySQL数据字典中,但是当服务器重新启动时它们为空。

    本示例说明如何创建,使用和删除MEMORY表:

    mysql> CREATE TABLE test ENGINE=MEMORY
               SELECT ip,SUM(downloads) AS down
               FROM log_table GROUP BY ip;
    mysql> SELECT COUNT(ip),AVG(down) FROM test;
    mysql> DROP TABLE test;
    

    MEMORY表的最大大小受max_heap_table_size系统变量的限制,系统变量的默认值为16MB。要对MEMORY表实施不同的大小限制,请更改此变量的值。在效果的值CREATE TABLE,或随后的ALTER TABLETRUNCATE TABLE,是用于表的寿命值。服务器重新启动还会将现有MEMORY表的最大大小设置为全局max_heap_table_size值。您可以按照本节后面的说明设置单个表的大小。

    指标

    MEMORY存储引擎支持HASHBTREE索引。您可以通过添加USING子句为给定索引指定一个或另一个,如下所示:

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

    有关B树和哈希索引的一般特征,请参见“ MySQL如何使用索引”。

    MEMORY每个表最多可以有64个索引,每个索引最多16个列,最大键长为3072字节。

    如果MEMORY表哈希索引具有高度的键重复性(许多索引条目包含相同的值),则影响键值的表更新和所有删除操作的速度将显着降低。此减速的程度与重复程度成正比(或与索引基数成反比)。您可以使用BTREE索引来避免此问题。

    MEMORY表可以具有非唯一键。(这是哈希索引实现的罕见功能。)

    被索引的列可以包含NULL值。

    用户创建的临时表

    MEMORY表内容存储在内存中,这是MEMORY表与服务器在处理查询时动态创建的内部临时表共享的属性。但是,两种类型的表的不同之处在于,这些MEMORY表不进行存储转换,而内部临时表是:

    • 如果内部临时表太大,则服务器会自动将其转换为磁盘存储,如“ MySQL中内部临时表的使用”所述。
    • 用户创建的MEMORY表永远不会转换为磁盘表。

    加载数据中

    MEMORY在MySQL服务器启动时填充表,可以使用init_file系统变量。例如,您可以将诸如INSERT INTO ... SELECT或的语句LOAD DATA放入文件中,以从持久数据源加载表,并用于init_file命名文件。请参见“服务器系统变量”和“ LOAD DATA语句”。

    内存表和复制

    服务器的MEMORY表在关闭并重新启动后将变为空。如果服务器是复制主服务器,则其从属服务器不知道这些表已为空,因此,如果从从属服务器上的表中选择数据,则会看到过期的内容。为了同步主MEMORY表和从表,MEMORY自启动DELETE表以来,首次在主表上使用表时,会将一条语句写入主表的二进制日志中,以同时清空从表上的表。在主服务器重启和第一次使用该表之间的时间间隔中,从服务器仍然有过时的数据。为了避免在直接查询从站可能返回陈旧数据时出现此间隔,请使用init_file系统变量设置为命名一个文件,该文件包含MEMORY启动时填充主服务器上表的语句。

    管理内存使用

    服务器需要足够的内存来维护同时使用的所有MEMORY表。

    如果从MEMORY表中删除单个行,则不会回收内存。仅在删除整个表时才回收内存。先前用于已删除行的内存将重新用于同一表中的新行。要MEMORY在不再需要表的内容时释放表使用的所有内存,请执行DELETETRUNCATE TABLE删除所有行,或者完全删除表DROP TABLE。要释放已删除的行所使用的内存,请使用ALTER TABLE ENGINE=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()表示一个向上舍入因子,使行长成为char指针大小的精确倍数。sizeof(char*)在32位计算机上为4,在64位计算机上为8。

    如前所述,max_heap_table_size系统变量设置MEMORY表的最大大小限制。要控制单个表的最大大小,请在创建每个表之前设置此变量的会话值。(max_heap_table_size除非您打算将该值用于MEMORY所有客户端创建的MEMORY表,否则不要更改全局值。)以下示例创建两个表,最大大小分别为1MB和2MB:

    mysql> SET max_heap_table_size = 1024*1024;
    Query OK, 0 rows affected (0.00 sec)
    
    mysql> CREATE TABLE t1 (id INT, UNIQUE(id)) ENGINE = MEMORY;
    Query OK, 0 rows affected (0.01 sec)
    
    mysql> SET max_heap_table_size = 1024*1024*2;
    Query OK, 0 rows affected (0.00 sec)
    
    mysql> CREATE TABLE t2 (id INT, UNIQUE(id)) ENGINE = MEMORY;
    Query OK, 0 rows affected (0.00 sec)
    

    max_heap_table_size如果服务器重新启动,则两个表都将还原为服务器的全局值。

    您也可以在MAX_ROWS表的CREATE TABLE语句中指定表选项,MEMORY以提示您计划存储在表中的行数。这不能使表增长到超过该max_heap_table_size值的水平,该值仍然是最大表大小的约束。为了获得最大的灵活性,请至少将其MAX_ROWS设置max_heap_table_size为希望每个MEMORY表都可以增长到的值。