改进的内存存储引擎¶
的MySQL5.5.15,固定行格式(降维)仍在使用内存存储引擎。固定行格式对列的类型施加了限制,因为它预先为每行分配了有限的内存量。这将呈现VARCHAR字段在字符在实践领域,使之不可能有一个文本或团字段与该引擎实现。
为了克服这一限制,采用了改进的内存存储引擎在这个版本中引入了支持吗真正的VARCHAR,VARBINARY,文本,团字段内存表。
此实现基于动态行格式(DFR)由mysql-heap-dynamic-rows补丁。
DFR用于以可变长度的形式存储列值,从而有助于减少这些列的内存占用,并使团而且文本Fields和realVARCHAR而且VARBINARY.
与固定的实现不同,每个列的值都在DRF只使用所需的空间。可变长度值最多可以使用4个字节来存储实际值的长度,并且只使用必要数量的块来存储值。
行DFR在内部由多个内存块表示,这意味着单行可以由组织成一个集合的多个块组成。每行至少占用一个块,一个块内不能有多行。块大小可以在创建表时配置(见下文)。
这DFR实现有两个关于排序和索引的注意事项。
警告¶
行排序¶
在没有命令时,记录可能会以与前一个记录不同的顺序返回内存实现。
这不是一个bug。依赖于特定订单的任何应用程序命令子句可能会产生意想不到的结果。一个特定的订单命令是一个副作用的存储引擎和查询优化器实现,这可能会改变之间的小MySQL版本。
索引¶
目前不可能在上使用索引团由于列的某些局限性动态行格式.尝试创建这样的索引将失败,并出现以下错误:
预期的输出
BLOB列''不能用于已使用表类型的键规范。
限制¶
出于性能考虑,我们实现了一种混合解决方案:在行开头使用固定格式,而其余部分使用动态格式。
记录的固定格式部分的大小是自动选择的创建表并且以后无法更改。特别地,这意味着以后不能使用创建索引或ALTER TABLE当使用动态行格式时。
索引中使用的列的所有值都以固定格式存储在行的第一个块中,然后用DRF.
这对表设置了两个限制:
*字段的顺序,因此,*表中使用的块的最小大小。
列的排序¶
中使用的固定格式的列必须在动态列之前定义创建表声明。如果不满足这个要求,引擎将不能为这些字段向集合中添加块,它们将被视为固定的。
最小块大小¶
块大小必须足够大,可以在第一个块中存储所有固定长度的信息。如果没有,创建表或ALTER TABLE语句将失败(见下文)。
限制¶
MyISAM表仍然用于查询优化器内部临时表内存现在可以使用表代替:用于包含大型表的临时表VARCHAR \“年代”、“BLOB,文本列。
设置行格式¶
考虑到这些限制,我们改进的内存存储引擎会选择DRF在降维在按照以下条件创建表时:
*在列类型**OR** *中有一个用户的隐式请求,有一个用户的显式请求,并且**由' DFR '引起的开销是有益的。
隐式的请求¶
当至少有一个时,用户的隐式请求被接受团或文本列的定义。如果没有这些列,并且没有给出相关选项,引擎将进行选择降维.
例如,这将产生动态格式的使用:
mysql >创建表格t1(f1VARCHAR(32),f2文本,主要的关键(f1))引擎=堆;
虽然这不会:
mysql >创建表格t1(f1VARCHAR(16),f2VARCHAR(16),主要的关键(f1))引擎=堆;
显式的请求¶
属性中的以下选项之一设置显式请求创建表声明:
* ' KEY_BLOCK_SIZE = ' *请求指定块大小的DFR(单位:字节)
尽管它的名字叫KEY_BLOCK_SIZEOption指的是用来存储数据而不是索引的块大小。这样做的原因是存在的创建表选项被重用,以避免引入新的选项。
改进的内存引擎检查指定的块大小是否大到足以保存所有键列值。如果它太小,表创建将中止并报错。
后DRF是明确要求的,没有吗团或文本表定义中的列改进的内存引擎将检查使用动态格式是否比固定格式节省空间:
*如果固定行长度小于动态块大小(加上动态行开销-依赖于平台)**或** *表中没有任何变长列或' VARCHAR '字段声明的长度为31或更短,
引擎将恢复到固定格式,因为在这种情况下它更节省空间。引擎使用的行格式可以使用显示表状态.
例子¶
32位平台:
mysql >创建表格t1(f1VARCHAR(32),f2VARCHAR(32),f3VARCHAR(32),f4VARCHAR(32),主要的关键(f1))KEY_BLOCK_SIZE=124引擎=堆;mysql >显示表格状态就像“t1”;
预期的输出
名称引擎版本行Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment t1 MEMORY 10 X 0 X 0 0 NULL NULL NULL latin1_swedish_ci NULL row_format=DYNAMIC KEY_BLOCK_SIZE=124
在64位平台上:
mysqlCREATE表格t1(f1VARCHAR(32),f2VARCHAR(32),f3VARCHAR(32),f4VARCHAR(32),主要的关键(f1))KEY_BLOCK_SIZE=124引擎=堆;
mysqlSHOW表格状态就像“t1”;
预期的输出
名称引擎版本行Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment t1 MEMORY 10 X 0 X 0 0 NULL NULL NULL NULL latin1_swedish_ci NULL KEY_BLOCK_SIZE=124
实现细节¶
MySQL内存表将数据保存在固定大小的块数组中。这些块被组织成两组HP_BLOCK结构:
group1包含一个索引HP_BLOCK每个键(部分HP_KEYDEF),group2包含记录数据,用单HP_BLOCK所有记录。
虽然索引中使用的列通常很小,但表中的其他列可能需要容纳更大的数据。通常,较大的数据被放入VARCHAR或团列。
改进的内存引擎实现数据空间的概念,HP_DATASPACE,其中包含HP_BLOCK结构的记录数据,为管理可变大小的记录添加更多信息。
可变大小的记录存储在多个“块”中,这意味着单个数据记录(数据库“行”)可以由组织成一个“集”的多个块组成,包含在HP_BLOCK结构。
在可变大小格式中,一条记录根据实际数据表示为一个或多个块,而在固定大小模式中,一条记录总是表示为一个块。索引结构总是指向块集中的第一个块。
只有在存在可变大小的列时才需要可变大小的记录。的改进的内存引擎将会寻找团或VARCHAR声明长度为32或更多的列。如果没有找到这样的列,表将切换到固定大小的格式。为了使用可变大小格式,应该始终将这些列放在表定义的末尾。
每当在表中插入或更新数据时,改进的内存引擎将计算需要多少块。
为插入操作时,引擎只在记录空间中分配新的块集。为更新如果需要,它将修改现有块集的长度,在结束时断开不必要的块的链接,或者如果需要更大的长度,则分配和添加更多的块。
当将数据写入块或将数据复制回记录时,固定大小的列将以其完整格式复制,而VARCHAR而且团根据列的实际长度复制列,跳过任何列零值。
当分配一个包含N个块的新块集时,引擎将尝试一个接一个地分配块,并在分配时将它们链接起来。对于分配单个块,它将尝试重用已删除(释放)的块。如果没有可用的空闲块,它将尝试在HP_BLOCK.
当释放块时,引擎将把它们放在数据空间的空闲列表的前面,每个都包含对先前释放块的引用。
实际块的分配和内容在固定和可变大小模式之间有所不同:
固定大小块的格式:
uchar []*与运算符= chunk_dataspace_length,但至少sizeof (uchar \ *)字节。它保留实际数据或指向下一个已删除数据块的指针chunk_dataspace_length等于完整的记录长度uchar*状态字段(1表示“正在使用”,0表示“已删除”)
可变大小块的格式:
uchar []*与运算符= chunk_dataspace_length,但至少sizeof (uchar \ *)字节。它保留实际数据或指向下一个已删除数据块的指针chunk_dataspace_length是按桌子的顺序来的吗key_block_sizeuchar \ **指向这个块集中的下一个块的指针,或者指向最后一个块的NULLuchar*状态字段(1表示“第一次”,0表示“删除”,2表示“已链接”)
总块长度总是与下一个块对齐sizeof (uchar \ *).
另请参阅