数据库

时间:2017-12-22 06:25:11

标签: mysql database file cursor fwrite

出于学习/实验目的,我试图模仿我从研究数据库中学到的一些技巧。我很好奇MySQL(以及其他数据库)如何解决这个特殊问题。

所以我正在编写一个应用程序,与其他数据库一样,将记录并排存储在单个文件中。我使用另一个文件来索引记录的位置,以便快速查找它们。一切正常,直到我需要更新一个比当前版本更长的行。我有一些想法,但似乎没有一个对性能友好。

假设我想更新1,000条记录中的记录200。在我的逻辑中,我将文件光标放在行开始的位置,然后写入数据。假设该行的当前版本是100字节长(并且从下一条记录开始的第101字节开始)。新数据长度为150个字节,因此只需使用文件光标写入就会有效地覆盖下一条记录中的字节。

据我所知,你不能从光标向文件中“推送”数据 - 如果可能的话,它似乎不是最友好的操作。

我可以选择附加新数据并用NULL字节替换当前行。但这似乎是 a)浪费空间 b)再次,需要大量的机器工作来重建文件而没有NULL字节

然后可以选择碎片整理,但我还没准备好朝这个方向发展。

有人知道其他数据库是如何处理的吗?

1 个答案:

答案 0 :(得分:2)

其他数据库以多种方式处理此问题。我可以回答MySQL。

  • 第一次将记录写入文件的某个空间时,请留出一些额外的空间。将存储组织为16KB的“页面”,其中有几个记录适合。但最初将1/16空间留空,以允许行扩展。每个页面都按需加载到RAM中,并且在将页面写回磁盘之前可以重新组织其中的记录。

  • 如果记录超出页面中的空间,则可能会将其拆分。某些记录可能会重新定位到其他新页面,这些新页面可能相距甚远。跟踪记录位置的索引不需要记录相邻。

  • 所有记录重组和拆分留下的空白区域会导致一些碎片,但它可能只占整个存储空间的一小部分,所以我们不担心它。最终,碎片可能会变得更糟,所以不时将所有记录的新副本制作成一组新页面,更有效地重新组织,以替换原始页面,这是一个好主意。你应该多久这样做取决于你在数据库中做了多少活动,因此对它没有严格的规定。

  • 可能有用的另一个相对较新的新功能称为sparse fileshole-punching。传统上,无论是否在这些字节中存储有用数据,文件的所有连续字节都占用磁盘空间。但是,如果文件中的间隙可以被视为可用磁盘空间呢?那你就不关心碎片了。所有文件系统都不支持这种情况,“漏洞”通常限于文件系统块大小的倍数(例如4KB)。

    MySQL 5.7在其page compression功能中使用了打孔功能。 MySQL仍然以16KB页面存储数据,但您可以在页面内启用可选的数据压缩。如果压缩留下4KB的空隙(文件系统块的大小),它会将其视为一个漏洞,并为其释放文件系统存储空间。

还有许多其他技巧可行。不值得尝试将存储优化到字节,因为只要您这样做,另一个数据更新将需要您撤消它。优化快速更新通常比完全紧凑的存储更好。一切都归结为不同类型的效率之间的权衡(例如,速度与存储),您必须做出一些关于什么对您的数据库更重要的决定。