文档主页
MySQL 8.4 参考手册
相关文档 下载本手册
PDF (US Ltr) - 39.9Mb
PDF (A4) - 40.0Mb
手册页 (TGZ) - 258.5Kb
手册页 (Zip) - 365.5Kb
信息 (Gzip) - 4.0Mb
信息 (Zip) - 4.0Mb


MySQL 8.4 参考手册  /  ...  /  优化 MyISAM 查询

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 章“备用存储引擎”。

  • 如果您通常按 expr1, expr2, ... 顺序检索行,请使用 ALTER TABLE ... ORDER BY 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 语句”

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