MySQL 8.0 参考手册  / 第8章优化  / 8.6 优化 MyISAM 表  /  8.6.1 优化 MyISAM 查询

8.6.1 优化 MyISAM 查询

加快 MyISAM表查询的一些一般技巧:

  • 为了帮助 MySQL 更好地优化查询, 在表加载数据后使用ANALYZE TABLE或运行 myisamchk --analyze 。这会为每个索引部分更新一个值,该值指示具有相同值的平均行数。(对于唯一索引,这始终为 1。)当您基于非常量表达式连接两个表时,MySQL 使用它来决定选择哪个索引。您可以通过使用 和检查该值来检查表分析的结果。myisamchk --description --verbose显示索引分布信息。 SHOW INDEX FROM tbl_nameCardinality

  • 要根据索引对索引和数据进行排序,请使用 myisamchk --sort-index --sort-records=1 (假设您要对索引 1 进行排序)。如果您有一个唯一索引,您希望根据该索引从中按顺序读取所有行,这是一种加快查询速度的好方法。第一次以这种方式对大表进行排序时,可能需要很长时间。

  • 尽量避免对频繁更新SELECT 的表进行复杂的查询MyISAM,避免因读写器争用而导致表锁定的问题。

  • MyISAM支持并发插入:如果一个表在数据文件中间没有空闲块,您可以INSERT在其他线程从表中读取的同时向其中插入新行。如果能够做到这一点很重要,请考虑以避免删除行的方式使用表。另一种可能性是OPTIMIZE TABLE在您从表中删除大量行后运行以对表进行碎片整理。concurrent_insert通过设置变量可以改变此行为 。您可以强制追加新行(因此允许并发插入),即使在已删除行的表中也是如此。请参阅第 8.11.3 节,“并发插入”

  • 对于MyISAM经常更改的表,尽量避免使用所有可变长度列(VARCHARBLOBTEXT)。如果该表甚至包含单个可变长度列,则该表使用动态行格式。请参阅第 16 章,替代存储引擎

  • 仅仅因为行变大就将一个表拆分成不同的表通常是没有用的。在访问一行时,最大的性能损失是找到该行的第一个字节所需的磁盘查找。找到数据后,大多数现代磁盘都可以足够快地读取整行以供大多数应用程序使用。拆分表会产生明显差异的唯一情况是,如果它是一个 MyISAM使用动态行格式的表,您可以将其更改为固定行大小,或者如果您经常需要扫描表但不需要大部分列. 请参阅第 16 章,替代存储引擎

  • 如果您通常按顺序检索行, 请使用。通过在对表进行大量更改后使用此选项,您可以获得更高的性能。 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表产生碎片。请参阅 第 16.2.3 节,“MyISAM 表存储格式”

  • MyISAM使用 table 选项 声明一个表DELAY_KEY_WRITE=1可以使索引更新更快,因为它们在表关闭之前不会刷新到磁盘。myisam_recover_options 缺点是如果在打开这样的表时有什么东西杀死了服务器,您必须通过运行带有系统变量集的服务器或通过 在重新启动服务器之前运行myisamchk来确保该表正常 。(但是,即使在这种情况下,使用 也不应该丢失任何内容DELAY_KEY_WRITE,因为关键信息始终可以从数据行中生成。)

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

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