c - MyISAM/InnoDB 以什么有效的方式从文件中删除特定文本?

标签 c database file innodb myisam

请在将其标记为重复之前阅读整个问题。

我知道我们只有一种方法可以从 C 中的文件中删除特定文本,即通过重写除我们要删除的文本之外的整个文件。但是如果我们有一个包含数千或数百万个文件的文件,这种方法将不是很有效的文本行。现在,由于 MyISAM 是一个必须提高效率的存储引擎,因为它要用于数百万条记录并且它是用 C 语言制作的,那么它如何在不重新重写整个文件的情况下实现这一点?即我问的是 MyISAM 的开发人员用来从文件中删除特定文本而不重新重写它的技术。

最佳答案

就像在DOS中一样,东西不是“删除”,而是“标记为已删除”,这样对于所有后续操作,删除的内容似乎都消失了。

MyISAM:

  • 标记记录的第一个字节以表明它已“删除”。
  • 从每个索引中删除相应的条目。

  • InnoDB:
  • 转到包含要删除的行的 block (在数据 BTree 中,由 PRIMARY KEY 索引);将其标记为已删除。
  • 将内容添加到重做/撤消日志中——以防后续 ROLLBACK复活行。
  • 向更改缓冲区添加一个条目,以便索引查找不会找到该行。
  • 最终将更改缓冲区条目刷新到实际索引。
  • 最终将数据记录清除出 block 。

  • 在任一引擎中,只有少数 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/

    相关文章:

    sql-server - 我们如何更改SQL Server 的页面大小?

    java - 从具有不同编码的文件中使用 RandomAccessFile 读取字符串

    python - 如何使用pathlib & csv模块来编写?

    c - 无符号字符数组的输出

    c - 我在学习 c 时无法说"is"

    mysql - 找不到基表或 View : 1146 Table '' doesn't exist

    ruby - file.each_char 在 Ruby 中的 file.each_line 之后不能正常工作

    c - 在这个程序中,这一行是如何工作的 "flag[str[i]-' a']++;"有人能解释一下吗?

    .net - 在 Linux/ARM 上使用 pinvoke 和 C 函数回调的 F# 委托(delegate)

    mysql - Information_schema 是否对 MariaDB 中的 everuser 可见?