请在将其标记为重复之前阅读整个问题。
我知道我们只有一种方法可以从 C 中的文件中删除特定文本,即通过重写除我们要删除的文本之外的整个文件。但是如果我们有一个包含数千或数百万个文件的文件,这种方法将不是很有效的文本行。现在,由于 MyISAM 是一个必须提高效率的存储引擎,因为它要用于数百万条记录并且它是用 C 语言制作的,那么它如何在不重新重写整个文件的情况下实现这一点?即我问的是 MyISAM 的开发人员用来从文件中删除特定文本而不重新重写它的技术。
最佳答案
就像在DOS中一样,东西不是“删除”,而是“标记为已删除”,这样对于所有后续操作,删除的内容似乎都消失了。
MyISAM:
InnoDB:
PRIMARY KEY
索引);将其标记为已删除。 ROLLBACK
复活行。 在任一引擎中,只有少数 IOP(BTree 钻取、读取、写入、日志记录)来删除行。实际的 IOP 数量取决于缓存——由于将此删除与表上的其他操作相结合。
MyISAM 的数据是流文件;代码将“寻找”+读取或写入一条记录。
MyISAM 的索引是 BTree,缓存在“key_buffer”(1KB block )中; InnoDB 的数据和索引是 BTrees 并缓存在“buffer_pool”(16KB block )中。所有操作都是一个 block 的查找+读/写。
我认为 InnoDB 重做/撤消日志是流式传输的。
InnoDB 的“双写”缓冲区是一个被冗余写入的 block 。这是针对“撕裂页面”的 ACID 保护,其中在断电期间 block 被写入一半。大多数磁盘的操作单位是一个 512 字节的“扇区”; MyISAM/InnoDB 的单元就是这样的几个。
从长远来看
那么,如果一条记录只被标记为已删除,那么磁盘空间是否已经恢复?我强调磁盘空间而不是“内存” RAM,因为 RAM 仅用作缓存。
这得看情况。如果您正在“搅动”数据——删除和插入——那么
DELETE
释放的空间可用于 INSERT
.但是,由于记录的布局方式,INSERT
可能会也可能不会重新使用最近由 DELETE
释放的空间.但是,从长远来看,插入将填补删除留下的“漏洞”。但...BTrees 本身就有一个小问题。每个节点都是一个固定大小的 block 。做了几次删除后,固定大小并没有缩小。在进行过多插入后,该 block 被“拆分”成两个 block (具有相同的、固定的大小)。尽管如此,随着时间的推移,BTree 将被吸引到大约 69% 的满载。也就是说,最初的 69 个完整 block 将(经过大量流失后)达到大约 100 个 block 的稳定状态,同时仍包含相同数量的记录。
所以,一张 table 会变大,但永远不会缩小。但增长仅限于实际数据大小的某些倍数。缩水了怎么办?...
在 MyISAM 和 InnoDB 中,都有自动“碎片整理”的方法,并将浪费的空间还给操作系统。但是,有一个 SQL 语句可以做到这一点。但不要使用它;这是不值得的。它创建一个新表,复制所有数据,重建索引并将表重命名为您拥有的表。很多努力;几乎从来没有太多好处。
另一件事……如果两个“相邻”的 BTree block 小于一半,则这些 block 将被合并。 (这释放了一个 block 以便在给定表中重用,但不会将其返回给操作系统。)
“大公司”是做什么的?回答:“没什么。”我曾经为这样的公司工作,所以我可以根据经验说话。在 100 个系统上的 10,000 个表中,我只确定了 2 个值得进行碎片整理的案例。而且只有每月一次。还有 MyISAM,而不是 InnoDB。你今天不应该使用 MyISAM。
关于c - MyISAM/InnoDB 以什么有效的方式从文件中删除特定文本?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46411252/