Documentation Home
MySQL 8.4 Reference Manual
Related Documentation Download this Manual
PDF (US Ltr) - 39.8Mb
PDF (A4) - 39.9Mb
Man Pages (TGZ) - 257.9Kb
Man Pages (Zip) - 364.9Kb
Info (Gzip) - 4.0Mb
Info (Zip) - 4.0Mb


MySQL 8.4 Reference Manual  /  ...  /  Optimizing Data Size

10.4.1 数据大小优化

设计表格以减少磁盘空间。这样可以通过减少磁盘写入和读取量来获得巨大改进。较小的表格通常在查询执行期间需要更少的主内存空间。任何表格数据的空间减少也会导致更快地处理索引。

MySQL 支持多种存储引擎(表类型)和行格式。对于每个表,可以决定使用哪种存储和索引方法。选择合适的表格格式可以给您带来很大的性能提高。见第17章,InnoDB 存储引擎,和第18章,Alternative 存储引擎

通过以下技术,可以使表格性能更好、存储空间更小:

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

  • 如果可能,声明列为NOT NULL。这样可以使 SQL 操作更快,通过更好的索引使用和避免每个值是否为 NULL 的测试 overhead。你也可以节省一些存储空间,一位 per 列。如果你真的需要表中的 NULL 值,使用它们。只是不要默认设置允许每列都有 NULL 值。

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

    紧凑行格式家族,包括 COMPACTDYNAMICCOMPRESSED,以代价增加某些操作的 CPU 使用来减少行存储空间。如果您的工作负载是受缓存命中率和磁盘速度限制的,那可能会更快。如果是受 CPU 速度限制的特殊情况,那可能会慢一些。

    紧凑的行格式家族还优化了使用变长字符集,如utf8mb3utf8mb4CHAR列存储。使用ROW_FORMAT=REDUNDANT时,CHAR(N) 占用N × 字符集的最大字节长度。许多语言可以主要使用单字节utf8mb3utf8mb4字符,所以固定存储长度经常浪费空间。紧凑行格式家族中,InnoDB为这些列分配一个变长的存储范围在NN × 字符集的最大字节长度,去除尾部空格。最小存储长度是N个字节,以便在典型情况下进行in-place更新。更多信息,请参见第17.10节,“InnoDB行格式”.

  • 为了进一步减少空间,创建InnoDB表时指定ROW_FORMAT=COMPRESSED,或者在现有MyISAM表上运行myisampack命令。(InnoDB压缩表是可读写的,而MyISAM压缩表是只读的。)

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

索引

  • 表的主键应该尽量短。这样可以轻松地和高效地识别每一行。对于 InnoDB 表,主键列在每个次要索引条目中被复制,所以如果您有很多次要索引,短的主键可以节省很大空间。

  • 只创建需要提高查询性能的索引。索引对于检索操作很好,但会 slows down 插入和更新操作。如果您主要通过搜索多个列来访问表,创建一个组合索引,而不是单独为每个列创建索引。索引的第一个部分应该是最常用的列。如果您总是使用多个列从表中选择数据,那么索引的第一个列应该是具有最多重复值的列,以获得更好的索引压缩。

  • 如果很可能长字符串列在前几个字符上有唯一前缀,创建只索引这个前缀,使用 MySQL 的支持创建索引的左部分(见第15.1.15节,“CREATE INDEX 语句”)。更短的索引不仅因为它们需要更少的磁盘空间,还因为它们也会在索引缓存中更多地命中,减少磁盘寻道次数。见第7.1.1节,“服务器配置”

  • 在某些情况下,扫描非常频繁的表可以被分割成两个表。这尤其适用于动态格式表,如果可能使用更小的静态格式表来找到相关行时。

  • 将具有相同信息的列在不同表中声明相同数据类型,以加速基于相应列的连接操作。

  • 保持列名简单,以便在不同的表中使用相同的名称,简化连接查询。例如,在一个名为 customer 的表中,使用 name 作为列名,而不是 customer_name。为了使名称在其他 SQL 服务器上可移植,考虑将它们保持在 18 个字符以下。

  • 通常情况下,尽量保持所有数据非冗余(遵循数据库理论中的第三范式)。而不是重复长字符串,如名称和地址,分配唯一的 ID,根据需要在多个小表中重复这些 ID,并在查询中通过 join 子句引用 ID。

  • 如果速度比磁盘空间和维护多个数据副本的成本更重要,例如,在业务智能场景中分析大型表中的所有数据,你可以放松 normalization 规则,重复信息或创建摘要表以获得更多速度。