为什么使用 innodb_file_per_table?

Goo*_*bot 30 mysql innodb performance linux

有很多文章夸大了(当然恕我直言)对innodb_file_per_table. 我知道使用innodb_file_per_table,应该可以更好地控制各个表;比如分别备份每张表。然而,对更好性能的要求是有问题的。

在我的测试中,在性能没有差异innodb_file_per_table,并ibdata1为60GB的数据库。当然,这是一个普通查询的简单测试,现实生活中复杂查询的情况可能会有所不同(这就是我问这个问题的原因)。64 位 linux 搭配ext4可以有效处理大文件。

使用innodb_file_per_table,需要更多的磁盘 I/O 操作;这在复杂的JOINs 和FOREIGN KEY约束中很重要。

表空间在 single 上共享ibdata;单独表的专用表空间如何节省磁盘空间?当然,使用 为每个表释放表空间更容易ALTER,但它仍然是一个昂贵的过程(带有表锁)。

问:是否innodb_file_per_table有关于MySQL的性能更好的效果呢?如果是,为什么?

ype*_*eᵀᴹ 20

我认为这不是绩效问题,而是管理问题。

例如,通过每个表单独的文件,您可以将不同的数据库存储在不同的存储设备中。

您可以处理无法处理大文件的文件系统中非常大的数据库的情况(至少将问题推迟到一张表达到文件大小限制)。

您没有不受控制的表空间增长。如果您删除了一些大表,ibdata文件将保持较小。

可能对性能产生一些影响的一个方面是表数据和索引的碎片,这将受到每个表的限制。但这需要测试才能确认。


Syn*_*ech 16

为什么使用 innodb_file_per_table?

因为管理个人更容易,因为它可以在文件级别完成。这意味着,即使服务器关闭,你仍然可以通过复制表文件,而使用一个共享的表空间的方式,无论复制拷贝数据可以是不必要的块状,或找到一些方法来获取服务器上运行提取数据(您真的不想使用十六进制编辑器手动提取数据)。

有人警告说,您不能简单地将.ibd文件从一台服务器复制并粘贴到另一台服务器。这可能是真的,但它不应该适用于同一台服务器上的备份(我在这里使用备份一词的传统意义是制作副本;即,不会彻底改变整个事情)。此外,ibdata1在启动时自动重新创建(如大多数“转换为每个表文件”指南的删除ibdata1步骤中所见)。这样,你就不会需要复制ibdata1,除了你的.ibd文件(及其相应的.frm,等文件)。

如果尝试恢复丢失的表,复制其.ibd.frm文件以及information_schema小于ibdata1)应该就足够了。这样,您可以将它们放在虚拟服务器中并提取您的表,而无需复制整个庞大的事物。

然而,对更好性能的要求是有问题的。… 使用 innodb_file_per_table,需要更多的磁盘 I/O 操作;这在复杂的 JOIN 和 FOREIGN KEY 约束中很重要。

毫不奇怪,性能将完全取决于所使用的特定数据库。一个人会得到与另一个人(甚至是截然不同的)不同的结果。

确实,使用 file-per-table 会有更多的磁盘 I/O 操作,但只是稍微多一点。想想系统是如何工作的。

  • 对于单体数据库:

    1. 服务器已启动
    2. ibdata1 已打开
    3. 读取标头和元数据
    4. 结构和元数据缓存在内存中
    5. 发生查询
      1. 服务器访问磁盘并从已打开的磁盘中读取数据 ibdata1
      2. 服务器可以将数据缓存在内存中
  • 对于每表数据库:

    1. 服务器已启动
    2. ibdata1 已打开
    3. 读取标头和元数据
    4. 每个单独的.ibd文件被打开
    5. 从每个.ibd文件中读取标题和元数据
    6. 结构和元数据缓存在内存中
    7. 发生查询
      1. 服务器访问磁盘并从已经打开的.ibd文件中读取数据
      2. 服务器可以将数据缓存在内存中

您会注意到,当服务器运行时,您无法移动数据文件,因为服务器已打开它们的句柄。这是因为当它启动时,它会打开它们并让它们保持打开状态。它不会为每个单独的查询打开和关闭它们。

因此,在开始时,当服务器启动时,只会有更多的 I/O 操作;不是在它运行的时候。此外,虽然每个单独的.ibd文件都有自己单独的开销(文件签名、结构等),但它们被缓存在内存中,不会为每个查询重新读取。此外,即使使用共享表空间也可以读取相同的结构,因此几乎不需要(如果有的话)更多内存。

innodb_file_per_table 对提高mysql的性能有影响吗?

实际上,如果有的话,性能实际上可能更糟

使用共享表空间时,有时/通常可以组合读取和写入操作,以便服务器一次性从多个表中读取数据样本ibdata

但是,如果数据分布在多个文件中,则必须为每个文件单独执行单独的 I/O 操作。

当然,这又完全取决于所讨论的数据库;实际性能影响将取决于共享表空间的大小、查询频率和内部碎片。有些人可能会注意到很大的差异,而另一些人可能根本看不到任何影响。

表空间在单个 ibdata 上共享;单独表的专用表空间如何节省磁盘空间?

它不是。如果有的话,它会增加一些磁盘使用量。

我没有一个 60GB 的数据库来测试,但是我的“微不足道的”个人数据库包含我的 WordPress 安装和一些用于个人使用和开发测试的小表,当使用共享表空间时,它的重量约为 30MB。将其转换为 file-per-table 后,它膨胀到 ~85MB。即使删除所有内容并重新导入,它仍然大于 60MB。

这种增长是由于两个因素:

  • 出于某种原因,绝对最小大小为ibdata110MB,即使您除了information_schema存储在其中什么都没有。

  • 对于共享表空间,只有ibdata1文件签名、元数据等开销,但对于每个表,每个单独的.ibd文件都有所有这些。这意味着总数(即使假设 <10MB ibdata1)至少会大一些:

    GetTotalSizeofOverhead() * GetNumTables()
    
    Run Code Online (Sandbox Code Playgroud)

显然,这些不会是巨大的增加(除非您使用的主机限制了您的数据库大小或将它们存储在闪存驱动器等上),但它们仍然会增加,并且通过将(每个)表切换到文件-per表可以收缩ibdata1到10MB,整体总都不可避免地更多比它。


ran*_*omx 12

这是我总是使用 innodb_file_per_table 的原因:

如果没有每个表的文件,ibdata 文件永远不会压缩或缩小或减少空间。不是在删除行、删除表或数据库时。如果您有一个活跃的排队系统,2GB 的数据可以很快变成一个 20GB 的文件。

假设您想在更改之前备份当前的 1GB 表,然后删除它。您的 ibdata 中现在有 GB 未使用的空间。无赖。

临时措施使单个数据文件膨胀的例子可能有无数个例​​子,但我认为,没有理由不使用 innodb_file_per_table

另外,这里有一篇很好的文章可供阅读:http : //code.openark.org/blog/mysql/reasons-to-use-innodb_file_per_table


Tom*_*mor 5

不使用 innodb_file_per_table 的原因是性能。

我在 mysql 5.5.45 Linux CentOS 6.7 版上用 450 个表对我们的数据库做了一些测试

对于在每次测试之前将夹具插入数据库的单元测试(不是每次都使用所有表)并且测试本身确实与数据库一起工作(插入、更新、删除、选择),当数据库表不使用时,性能提高了 3-5 倍分成更多的文件。

我建议在您决定使用 innodb_file_per_table 之前,使用您想要使用的查询来测试您的数据库并进行比较

也许您会发现,对于生产服务器,您可以使用 innodb_file_per_table 但对于启动单元测试(大量使用 DB)的 CI 环境(继续集成)以及启动单元测试很多的开发人员,由于性能原因,最好不要使用它。

  • 我猜这是由于为所有 450 个表分配初始文件所需的时间与分配单个文件所需的时间有关。在生产中,这只会发生一次,所以不应该是一个问题,但你有一个很好的观点,即快速创建一个数据库,然后完全拆除它并一遍又一遍地重复单个 ibdata 文件是更好的。 (2认同)