8.6.1 优化 MyISAM 查询
一些加快MyISAM
table 查询速度的一般技巧:
-
为了帮助 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 进行排序可能会花费很长时间。
-
尝试避免对频繁更新的
MyISAM
table 进行复杂的SELECT查询,以避免由于读取器和写入器之间的争用而导致的 table 锁定问题。 -
MyISAM
支持并发插入:如果 table 在数据文件的中间没有空闲块,则可以在其他线程从 table 中读取数据的同时INSERT向其中_1 个新行。如果能够做到这一点很重要,请考虑以避免删除行的方式使用 table。另一种可能是从 table 中删除很多行后,运行OPTIMIZE TABLE对 table 进行碎片整理。通过设置concurrent_insert变量可以更改此行为。即使在已删除行的 table 中,也可以强制添加新行(并因此允许并发插入)。参见第 8.11.3 节“并发插入”。 -
对于经常更改的
MyISAM
table,请尝试避免使用所有可变长度列(VARCHAR,BLOB和TEXT)。如果该 table 甚至包含单个可变长度列,则使用动态行格式。参见第 15 章,备用存储引擎。 -
通常,仅由于行变大而将 table 拆分为不同的 table 是没有用的。在访问一行时,最大的性能损失是找到该行第一个字节所需的磁盘搜索。找到数据后,大多数现代磁盘可以以足够快的速度读取整个行,以适合大多数应用程序。拆分 table 的唯一情况是,如果它是使用动态行格式的
MyISAM
table,您可以将其更改为固定的行大小,或者经常需要扫描 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以避免动态格式
MyISAM
table 的碎片化。参见第 15.2.3 节“ MyISAMtable 存储格式”。 -
使用
DELAY_KEY_WRITE=1
table 选项声明MyISAM
table 可以使索引更新更快,因为索引更新只有在关闭 table 后才会刷新到磁盘。不利的一面是,如果在打开此类 table 时某人杀死了服务器,则必须通过设置myisam_recover_options系统变量的服务器运行或通过myisamchk重启服务器之前,确保该 table 是可以的。 (但是,即使在这种情况下,也不要使用DELAY_KEY_WRITE
丢失任何内容,因为密钥信息始终可以从数据行中生成.) -
字符串会自动在
MyISAM
索引中压缩前缀和结尾空间。参见第 13.1.14 节“ CREATE INDEX 语句”。 -
您可以通过在应用程序中缓存查询或答案,然后一起执行许多插入或更新操作来提高性能。在此操作期间锁定 table 可确保索引缓存在所有更新后仅刷新一次。您还可以利用 MySQL 的查询缓存来获得类似的结果。参见第 8.10.3 节“ MySQL 查询缓存”。