文档首页
MySQL 9.0 参考手册
相关文档 下载此手册
PDF (US Ltr) - 40.0Mb
PDF (A4) - 40.1Mb
手册页 (TGZ) - 258.2Kb
手册页 (Zip) - 365.3Kb
Info (Gzip) - 4.0Mb
Info (Zip) - 4.0Mb


MySQL 9.0 参考手册  /  ...  /  优化数据大小

10.4.1 优化数据大小

设计您的表以最大程度地减少它们在磁盘上的空间。这可以通过减少写入和读取磁盘的数据量来带来巨大的改进。较小的表通常在查询执行期间对其内容进行积极处理时需要更少的内存。表数据的任何空间减少也会导致更小的索引,这些索引可以更快地处理。

MySQL 支持许多不同的存储引擎(表类型)和行格式。对于每个表,您可以决定使用哪种存储和索引方法。为您的应用程序选择合适的表格式可以为您带来巨大的性能提升。请参阅第 17 章,InnoDB 存储引擎第 18 章,替代存储引擎.

您可以通过使用此处列出的技术来获得表更好的性能并最大程度地减少存储空间

表列

  • 使用尽可能高效(最小)的数据类型。MySQL 有许多专门的类型可以节省磁盘空间和内存。例如,如果可能,请使用较小的整数类型来获得更小的表。MEDIUMINT 通常比 INT 更好,因为 MEDIUMINT 列使用的空间少 25%。

  • 如果可能,请声明列为 NOT NULL。它可以使 SQL 操作更快,因为它可以更好地使用索引并消除测试每个值是否为 NULL 的开销。您还可以节省一些存储空间,每列一个位。如果您确实需要在表中使用 NULL 值,请使用它们。只需避免允许在每列中使用 NULL 值的默认设置即可。

行格式

  • InnoDB 表默认使用 DYNAMIC 行格式创建。要使用除 DYNAMIC 之外的行格式,请配置 innodb_default_row_format,或在 CREATE TABLEALTER TABLE 语句中显式指定 ROW_FORMAT 选项。

    紧凑型行格式系列(包括 COMPACTDYNAMICCOMPRESSED)减少了行存储空间,但以增加某些操作的 CPU 使用率为代价。如果您的工作负载是典型的由缓存命中率和磁盘速度限制的工作负载,那么它可能会更快。如果它是一个由 CPU 速度限制的罕见情况,那么它可能会更慢。

    当使用可变长度字符集(如 utf8mb3utf8mb4)时,紧凑型行格式系列还优化了 CHAR 列存储。使用 ROW_FORMAT=REDUNDANTCHAR(N) 占用 N × 字符集的最大字节长度。许多语言可以用单字节 utf8mb3utf8mb4 字符来主要编写,因此固定存储长度通常会浪费空间。使用紧凑型行格式系列,InnoDB 通过去除尾随空格,为这些列分配了字符集最大字节长度的 NN × 范围内的可变存储量。最小存储长度为 N 字节,以促进典型情况下的就地更新。有关更多信息,请参阅第 17.10 节,“InnoDB 行格式”.

  • 为了通过以压缩形式存储表数据来进一步最小化空间,在创建 InnoDB 表时指定 ROW_FORMAT=COMPRESSED,或者在现有 MyISAM 表上运行 myisampack 命令。(InnoDB 压缩表是可读写的,而 MyISAM 压缩表是只读的。)

  • 对于 MyISAM 表,如果您没有任何可变长度列 (VARCHARTEXTBLOB 列),则使用固定大小的行格式。这更快,但可能会浪费一些空间。参见 第 18.2.3 节,“MyISAM 表存储格式”。即使您有 VARCHAR 列,您也可以使用 CREATE TABLE 选项 ROW_FORMAT=FIXED 来提示您想要使用固定长度的行。

索引

  • 表的索引应尽可能短。这样可以轻松高效地识别每行。对于 InnoDB 表,主键列会在每个辅助索引条目中被复制,因此如果您有许多辅助索引,那么一个短主键可以节省大量空间。

  • 仅创建您需要提高查询性能的索引。索引有利于检索,但会减慢插入和更新操作的速度。如果您主要通过搜索列组合来访问表,请为它们创建一个复合索引,而不是为每个列创建单独的索引。索引的第一部分应该是使用最多的列。如果您 始终 在从表中选择时使用许多列,则索引中的第一列应该是重复次数最多的列,以便更好地压缩索引。

  • 如果很可能长字符串列在其前几个字符上具有唯一的前缀,则最好只索引此前缀,使用 MySQL 支持在列的最左侧部分创建索引(参见 第 15.1.15 节,“CREATE INDEX 语句”)。较短的索引速度更快,不仅因为它们需要的磁盘空间更少,而且因为它们还会在索引缓存中获得更多命中,从而减少磁盘查找次数。参见 第 7.1.1 节,“配置服务器”

联接

  • 在某些情况下,将经常扫描的表拆分为两个表可能是有益的。如果它是一个动态格式的表,并且可以使用一个较小的静态格式表来查找扫描表时的相关行,那么这将尤其如此。

  • 在不同表中声明具有相同信息的列,并使用相同的类型,以加快基于相应列的联接速度。

  • 使列名简洁,以便您可以在不同的表中使用相同的名称,并简化联接查询。例如,在名为 customer 的表中,使用 name 而不是 customer_name 作为列名。要使您的名称可移植到其他 SQL 服务器,请考虑使其长度小于 18 个字符。

规范化

  • 通常,尝试使所有数据不冗余(遵守数据库理论中称为 第三范式 的内容)。不要重复诸如姓名和地址之类的冗长值,而是为它们分配唯一的 ID,根据需要在多个较小的表中重复这些 ID,并在查询中通过引用联接子句中的 ID 来联接这些表。

  • 如果速度比磁盘空间和维护多个数据副本的成本更重要,例如在您分析来自大型表的所有数据的商业智能场景中,您可以放宽规范化规则,复制信息或创建汇总表以获得更高的速度。