8.6.1 优化 MyISAM 查询

一些加快MyISAMtable 查询速度的一般技巧:

  • 为了帮助 MySQL 更好地优化查询,请在对 table 加载数据后在 table 上使用ANALYZE TABLE或运行myisamchk --analyze。这将为每个索引部分更新一个值,该值指示具有相同值的平均行数。 (对于唯一索引,该值始终为 1.)当基于非恒定 table 达式联接两个 table 时,MySQL 使用它来决定选择哪个索引。您可以使用SHOW INDEX FROM tbl_name并检查Cardinality值来检查 table 分析的结果。 myisamchk-说明-详细显示索引分布信息。

  • 要根据索引对索引和数据进行排序,请使用myisamchk --sort-index --sort-records = 1(假设您要对索引 1 进行排序)。如果您有唯一的索引,要根据该索引按 Sequences 读取所有行,这是使查询更快的一种好方法。第一次以这种方式对大 table 进行排序可能会花费很长时间。

  • 尝试避免对频繁更新的MyISAMtable 进行复杂的SELECT查询,以避免由于读取器和写入器之间的争用而导致的 table 锁定问题。

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

  • 对于经常更改的MyISAMtable,请尝试避免使用所有可变长度列(VARCHARBLOBTEXT)。如果该 table 甚至包含单个可变长度列,则使用动态行格式。参见第 15 章,备用存储引擎

  • 通常,仅由于行变大而将 table 拆分为不同的 table 是没有用的。在访问一行时,最大的性能损失是找到该行第一个字节所需的磁盘搜索。找到数据后,大多数现代磁盘可以以足够快的速度读取整个行,以适合大多数应用程序。拆分 table 的唯一情况是,如果它是使用动态行格式的MyISAMtable,您可以将其更改为固定的行大小,或者经常需要扫描 table 但不需要大多数 table,列。参见第 15 章,备用存储引擎

  • 如果您通常以expr1, expr2, ...的 Sequences 检索行,请使用ALTER TABLE ... ORDER BY expr1, expr2, ...。通过在对该 table 进行大量更改之后使用此选项,您可能可以获得更高的性能。

  • 如果您经常需要基于许多行中的信息来计算结果(例如计数),则最好引入一个新 table 并实时更新计数器。以下 table 格的更新非常快:

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

当您使用仅具有 table 级锁定(多个读取器和单个写入器)的 MySQL 存储引擎(例如MyISAM)时,这非常重要。这也使大多数数据库系统具有更好的性能,因为在这种情况下,行锁定 Management 器的工作量减少了。

  • 定期使用OPTIMIZE TABLE以避免动态格式MyISAMtable 的碎片化。参见第 15.2.3 节“ MyISAMtable 存储格式”

  • 使用DELAY_KEY_WRITE=1 table 选项声明MyISAMtable 可以使索引更新更快,因为索引更新只有在关闭 table 后才会刷新到磁盘。不利的一面是,如果在打开此类 table 时某人杀死了服务器,则必须通过设置myisam_recover_options系统变量的服务器运行或通过myisamchk重启服务器之前,确保该 table 是可以的。 (但是,即使在这种情况下,也不要使用DELAY_KEY_WRITE丢失任何内容,因为密钥信息始终可以从数据行中生成.)

  • 字符串会自动在MyISAM索引中压缩前缀和结尾空间。参见第 13.1.14 节“ CREATE INDEX 语句”

  • 您可以通过在应用程序中缓存查询或答案,然后一起执行许多插入或更新操作来提高性能。在此操作期间锁定 table 可确保索引缓存在所有更新后仅刷新一次。您还可以利用 MySQL 的查询缓存来获得类似的结果。参见第 8.10.3 节“ MySQL 查询缓存”