即使使用主索引并且良好的 EXPLAIN 计划,MySQL 查询也很慢

标签 mysql performance explain

我有一个包含 130 万行的高流量表,该表出现大量以下类型的缓慢查询:

UPDATE app_info SET data1=269223, data2=0, data3=164, last_update='2012-08-30'
WHERE slice_id=7636 AND app_id=375 AND user_id=21012286 AND mode_id=1;

但是,此查询的解释计划表明了最佳计划(我们使用主键):

explain select * from app_info
where slice_id=7636 and app_id=375 and user_id=21012286 and mode_id=1\G

*************************** 1. row ***************************
           id: 1
  select_type: SIMPLE
        table: app_info
         type: const
possible_keys: PRIMARY
          key: PRIMARY
      key_len: 18
          ref: const,const,const,const
         rows: 1
        Extra: 

这是慢查询日志:

 Time: 120830  3:23:37
# User@Host: rest_service[rest_service] @ app01.peak.mindjolt.com [10.0.0.174]
# Thread_id: 10091395  Schema: platform  Last_errno: 0  Killed: 0
# Query_time: 68.559347  Lock_time: 0.000045  Rows_sent: 0  Rows_examined: 1 Rows_affected: 1  Rows_read: 2
# Bytes_sent: 52  Tmp_tables: 0  Tmp_disk_tables: 0  Tmp_table_sizes: 0
# InnoDB_trx_id: 575CBF3B9
UPDATE app_info SET data1=269223, data2=0, data3=164, last_update='2012-08-30' WHERE slice_id=7636 AND app_id=375 AND user_id=21012286 AND mode_id=1;

大约 30% 的查询花费 >1 秒,大约 10% 的查询花费 >10 秒(!)

什么可能导致此查询运行缓慢?据我所知,该计划是完美的,只扫描了一行,并且没有花时间获取锁。那么,发生了什么?

更新:忘记包含服务器规范,这是在 64G Quad Xeon X5650 2.66GHz(24 核)、Mysql 5.1.52-rel11.6-log Percona 服务器 11.6、12 磁盘 PERC H700 RAID 阵列上。该服务器长期以来一直运行良好(正常运行时间为 565 天)。

更新2:该表只有一个索引,该索引是由元组(app_id, user_id, slice_id, mode_id)组成的主索引。此外,这是一个只写主服务器,其他三个从服务器处理所有读取。

最佳答案

我怀疑您正在更新的一个或多个列上有索引,并且对于这么大的索引,可能需要一些时间来刷新这些索引并重建必要的部分。我会对索引进行审核,并删除任何不能为您带来高值(value)的 select 性能提升的索引。快速搜索也出现了the delay-key-write option (仅限 MyISAM :-/),这可能会有所帮助。最后一个前沿(如果这实际上是问题)将是研究主写/从读架构,然后在写主服务器上执行显着更少的索引。

编辑 我搜索了一下 InnoDB 选项,发现 this SO question关于如何暂时禁用它们的键进行写入操作。

关于即使使用主索引并且良好的 EXPLAIN 计划,MySQL 查询也很慢,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12189752/

相关文章:

mysql - MySQL主从性能差异大

mysql - 为什么 "explain"返回的行不等于 count()?

mysql - 处理选择查询mysql上的空值

mysql - Unicode CSV 文件中未显示孟加拉语文本

c - 如何计算周期?

ruby - 如何发送响应但继续在 Sinatra 中执行?

python - for 循环中 for 循环的更快替代方案

php - mysql模式的mysqli版本

mysql - 使用 127.0.0.1 为特权 root 用户连接 mysql 时出错

Mysql:2个ID的主键内部连接给出 "Range checked for each record"