MyISAM索引缓存是否起作用应重点看Key_blocks_used和每秒Key_reads速率:若Key_blocks_used长期偏低(如

MyISAM索引缓存是否真在起作用?看Key_blocks_used比看比例更直接
只盯着Key_read_requests / Key_reads这个比值容易误判。比如Key_read_requests高达千万次,但Key_reads才几十次,比例看起来极好,可如果Key_blocks_used长期只有几十块(远低于key_buffer_size能容纳的总块数),说明缓存根本没被有效填充——索引访问压根没集中到少数几张表上,或者查询压根没走索引。
实操建议:
- 用
SHOW STATUS LIKE 'Key_blocks%'查三组值:Key_blocks_used(已用块)、Key_blocks_unused(空闲块)、Key_blocks_not_flushed(未刷盘脏块) -
Key_blocks_used持续低于 100,即使比例好看,也代表缓存闲置;应检查是否多数查询是全表扫描(Handler_read_rnd_next高)或压根没命中索引 -
Key_blocks_not_flushed > 0且缓慢上涨,说明delay_key_write开启但磁盘刷写跟不上,可能触发意外中断后索引损坏
单位时间内的Key_reads才是性能瓶颈信号
Key_reads本身是累计计数器,单看一个快照值毫无意义。真正影响响应的,是每秒从磁盘读取索引页的次数。如果每秒Key_reads稳定在 20+,而磁盘随机读延迟又高(比如 HDD),那索引查找就成了明显瓶颈。
实操建议:
- 用
mysqladmin ext -ri10 | grep Key_reads持续采样,跳过第一行(启动以来累计值),观察后续每10秒增量 - 把每10秒值除以10,换算成每秒速率;SSD环境超过 50/s、HDD 超过 15/s 就该警惕
- 别盲目调大
key_buffer_size:若Key_blocks_used没同步增长,说明不是缓存不够,而是访问模式太分散或SQL没走索引
Key_read_requests高但查询慢?先确认是不是真在读索引
Key_read_requests统计的是“请求读索引”的次数,但它不保证这次请求真的命中了有效索引数据。如果WHERE条件没用上索引、或用了LIKE '%abc'这类无法使用B-Tree索引的写法,MySQL仍会发起索引读请求(比如读索引头、读空范围),最终退化为全表扫描——这时Handler_read_rnd_next会飙升,而Key_read_requests只是虚高。
面向 CRM 系统的 MySQL 8 数据库模式设计。当用户需要为客户关系管理(CRM)系统设计、评审、优化或生成数据库模式时,应使用此项技能。
实操建议:
- 配合
EXPLAIN查具体慢查询:重点看type是否为range/ref,key列是否显示实际使用的索引名 - 监控
Handler_read_rnd_next和Key_read_requests的比值;若前者接近甚至超过后者,说明大量“索引请求”最后都fallback到全表扫描 - MyISAM表上避免
SELECT *+ORDER BY混合场景:它可能触发文件排序,绕过索引直接读数据文件,Key_read_requests完全不体现这部分开销
CHECK TABLE之后Key_reads突增?可能是索引文件已损坏
MyISAM的.MYI文件一旦损坏(比如异常断电、磁盘坏道),CHECK TABLE可能返回status: OK但内部结构错乱。此时MySQL仍会尝试读索引,但反复失败后降级为逐行读.MYD,导致Key_reads激增、Handler_read_rnd_next同步暴涨,性能断崖式下跌。
实操建议:
-
CHECK TABLE table_name EXTENDED比普通CHECK更严格,会校验索引树完整性;若返回error: record is crashed,必须REPAIR TABLE - 修复后立刻观察
Key_reads速率是否回落——若仍高,说明修复不彻底或磁盘底层有问题 - 生产环境禁用
delay_key_write=ON除非你有UPS且定期做FLUSH TABLES;否则断电后.MYI比.MYD更容易静默损坏
关键点在于:Key_read_requests只是“意图”,不是“结果”;真正决定MyISAM性能的,是这些请求背后是否真实复用内存中的索引块,以及磁盘是否被迫频繁参与。盯着数字跑,不如盯着Key_blocks_used和每秒Key_reads的实际节奏。










