您在有关 MyISAM 的问题中获得的信息是正确的。不过,我想回答你的另外两个问题:
最新问题
如果用户用更长的数据更新现有数据怎么办? MyISAM 会将记录标记为已删除并找到适合新数据的位置还是简单地使用溢出指针指向不适合的数据?
根据the Book
第 10 章:“存储引擎”第 196 页第 7 段说
对于可变长度的记录,格式更复杂。第一个字节包含描述记录子类型的特殊代码。后续字节的含义因每个子类型而异,但共同的主题是存在一个字节序列,其中包含记录的长度、块中未使用的字节数、NULL 值指示符标志,以及可能指向的指针如果记录不适合先前创建的空间并且必须拆分,则记录的延续。当一条记录被删除,并且要插入到其位置的新记录超过原始记录的大小时,就会发生这种情况。您可以通过研究storage/myisam/mi_dynrec.c中的switch语句in_mi_get_block_info()来详细了解不同代码的含义。
根据该段落,仅当要插入的新数据无法放入先前分配的块中时,旧记录才会被链接数据覆盖。这可能会导致许多行臃肿。
附加问题
如果表被多次删除和插入,记录结构可能会充满溢出指针和未使用的空间,效率是否会非常低?
从我之前的回答来看,会有很多块
- 空间块
- 记录的长度
- 块中未使用的字节数
- NULL 值指示标志
- 如果记录不适合先前创建的空间并且必须拆分,则可能是指向记录延续的指针
此类记录链接将从插入超大数据的每一行的前面开始。这会使 MyISAM 表膨胀.MYD
归档速度非常快。
建议
MyISAM 的默认行格式是动态的。当表是动态的并且经历大量 INSERT、UPDATE 和 DELETE 时,这样的表需要通过以下方式进行优化:
OPTIMIZE TABLE mytable;
还有一种替代方法:将表的行格式切换为“固定”。这样,所有行的大小都相同。这是固定行格式的方法:
ALTER TABLE mytable ROW_FORMAT=Fixed;
即使使用固定行格式,也必须花费时间来查找可用记录,但时间将是 O(1) 搜索时间(通俗地说,无论有多少行,查找可用记录所需的时间都是相同的)该表有或有多少已删除的行)。您可以通过启用来绕过该步骤并发插入如下:
将其添加到 my.cnf
[mysqld]
concurrent_insert = 2
不需要重新启动 MySQL。赶紧跑
mysql> SET GLOBAL concurrent_insert = 2;
这将导致所有 INSERT 都转到表的后面而不寻找可用空间。
固定行表的优点
- INSERT、UPDATE 和 DELETE 会更快一些
- SELECT 速度快 20-25%
以下是我关于 SELECT 因行格式被修复而速度更快的一些帖子
-
May 03, 2012
: InnoDB 和 MyISAM 哪个更快?
-
Sep 20, 2011
: MyISAM 和 InnoDB 的优点
-
May 10, 2011
: 在固定大小字段上使用 CHAR 与 VARCHAR 对性能有何影响?
固定行表的缺点
大多数情况下,当你跑步时ALTER TABLE mytable ROW_FORMAT=Fixed;
,该表可能会增长 80-100%。这.MYI
文件(MyISAM 表的索引页)也会以相同的速度增长。
EPILOGUE
如果您想要 MyISAM 表的速度并且可以使用更大的表,则需要我的替代建议。如果要为每个 MyISAM 表节省空间,请保持行格式不变(动态)。您必须使用以下命令来压缩该表OPTIMIZE TABLE mytable;
更频繁地使用动态表。