Documentation Home
MySQL 8.3 Reference Manual
Related Documentation Download this Manual
PDF (US Ltr) - 40.8Mb
PDF (A4) - 40.9Mb
Man Pages (TGZ) - 294.0Kb
Man Pages (Zip) - 409.0Kb
Info (Gzip) - 4.0Mb
Info (Zip) - 4.0Mb
Excerpts from this Manual

MySQL 8.3 Reference Manual  /  ...  /  Optimizing MyISAM Queries

10.6.1 MyISAM 查询优化

以下是一些加速 MyISAM 表查询的通用提示:

  • 为了帮助 MySQL 更好地优化查询,请使用 ANALYZE TABLE 或在加载数据后对表运行 myisamchk --analyze。这将更新每个索引部分的平均行数值(对于唯一索引,这总是 1)。MySQL 使用此信息来决定在基于非常量表达式的连接时选择哪个索引。你可以使用 SHOW INDEX FROM tbl_name 查看分析结果,并检查 Cardinality 值。myisamchk --description --verbose 显示索引分布信息。

  • 要根据索引对表进行排序,请使用 myisamchk --sort-index --sort-records=1(假设你想根据索引 1 排序)。这是在你想根据索引从头到尾读取所有行时的好方法。第一次对大表进行这种排序可能需要很长时间。

  • 尽量避免在频繁更新的 MyISAM 表上执行复杂的 SELECT 查询,以避免由于读者和写者之间的争用而导致的表锁定问题。

  • MyISAM 支持并发插入:如果表中没有中间空块,你可以在其他线程读取表时 INSERT 新行。如果这很重要,请考虑使用表的方式来避免删除行。另一个可能性是运行 OPTIMIZE TABLE 来碎片表后删除了许多行。这个行为可以通过设置 concurrent_insert 变量来改变。你可以强制新行追加(因此允许并发插入),即使表中有删除的行。见 第 10.11.3 节,“并发插入”

  • 对于频繁更改的 MyISAM 表,请尽量避免所有变长列(VARCHARBLOBTEXT)。表使用动态行格式,如果它包含至少一个变长列。见 第 18 章 替代存储引擎

  • 通常,不需要将表拆分成多个表,因为行变得太大。在访问行时,最大性能损失是找到行的第一个字节所需的磁盘寻道。找到数据后,大多数现代磁盘可以快速读取整个行。只有在以下情况下拆分表才有明显的性能改善:如果它是一个使用动态行格式的 MyISAM 表,可以更改为固定行大小;或者你经常需要扫描表,但不需要大多数列。见 第 18 章 替代存储引擎

  • 使用 ALTER TABLE ... ORDER BY expr1, expr2, ... 如果你通常按 expr1, expr2, ... 顺序检索行。使用这个选项可以在对表进行大量更改后提高性能。

  • 如果你经常需要根据许多行的信息计算结果,例如计数,那么引入一个新表并实时更新计数器可能是可取的。

    UPDATE tbl_name SET count_col=count_col+1 WHERE key_col=constant;

    这非常重要,因为 MySQL 存储引擎(如 MyISAM)只有表级锁定(多个读者和单个写者)。这也使得大多数数据库系统的性能更好,因为行锁定管理器在这种情况下有更少的事情要做。

  • 使用 OPTIMIZE TABLE 定期避免动态格式 MyISAM 表的碎片化。请参阅 第 18.2.3 节,“MyISAM 表存储格式”

  • 使用 DELAY_KEY_WRITE=1 表选项声明 MyISAM 表可以使索引更新更快,因为它们不会被刷新到磁盘,直到表关闭。缺点是,如果服务器在打开表时崩溃,您必须确保表的正确性,方法是使用 myisam_recover_options 系统变量重新启动服务器,或者在重新启动服务器之前运行 myisamchk。(然而,即使在这种情况下,您也不会因为使用 DELAY_KEY_WRITE 而丢失任何内容,因为键信息总是可以从数据行生成的。)

  • 字符串在 MyISAM 索引中自动进行前缀和尾部空格压缩。请参阅 第 15.1.15 节,“CREATE INDEX 语句”

  • 您可以通过在应用程序中缓存查询或答案,然后一起执行多个插入或更新操作来提高性能。在此操作期间锁定表,以确保索引缓存仅在所有更新后刷新一次。