【问题标题】:MySQL query sometimes run slow, sometimes fastMySQL查询有时运行缓慢,有时快速
【发布时间】:2016-03-11 04:17:34
【问题描述】:

我对这个简单的 MySQL 查询有疑问:

select sender as id from message where status=1 and recipient=1

其中发件人表有数百万行。

当我在 SequelPro 上运行它时,它第一次运行很慢,大约 4 秒或更长时间,而下一次运行它运行得非常快,大约 0.018 秒。但是,如果我在几分钟后再次运行,它会再次执行相同的操作。

我尝试使用 SQL_NO_CACHE,但结果仍然相同。

数据库引擎为innoDB,数据库为MySQL Percona XtraDB集群。 解释结果如下:

|id|select_type|table  |type|possible_keys         |key |key_len|ref            |row   |Extra
| 1|SIMPLE     |message|ref |recipient,status, sent|sent|12     |const,const    |2989   |NULL

“sent”是(recipient,status)多列的索引。 有没有人有解决这个问题的想法?

谢谢。

添加(来自评论)

CREATE TABLE 'message' (
    'id' int(20) NOT NULL AUTO_INCREMENT, 
    'sender' bigint(20) NOT NULL, 
    'recipient' bigint(20) NOT NULL, 
    'status' int(5) NOT NULL, 
    'date' timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, 
    PRIMARY KEY ('id'), 
    KEY 'id' ('id'), 
    KEY 'recipient' ('recipient'), 
    KEY 'sender' ('sender'), 
    KEY 'date' ('date'), 
    KEY 'status' ('status'), 
    KEY 'sent' ('status','recipient')
) ENGINE=InnoDB AUTO_INCREMENT=90224500 DEFAULT CHARSET=latin1;

【问题讨论】:

  • 您可以在 mysql 查询中使用限制。例如select sender as id from message where status=1 and recipient=1 LIMIT 10 或者你也可以使用select sender as id from message where status=1 and recipient=1 LIMIT 10 OFFSET 15等偏移量
  • @SanjayChaudhari 感谢您的回复。但是,我想从表中获取所有结果。这就是我不使用 LIMIT 的原因。但我会尝试每 100 条记录循环一次查询,看看它是否有什么不同,即使这不是一个好的解决方案,因为将来记录会增长。
  • 看看你的索引是否使用得当。此外,备份表并重新创建它。然后从转储中导入记录一次。分散的记录可能会聚集在一起并稍微提高性能。

标签: php mysql innodb percona xtradb


【解决方案1】:

这些症状表明存在缓存问题。我指的不是“查询缓存”,而是引擎的缓存。

桌子有多大?所有活动表有多大?

innodb_buffer_pool_size 的值是多少?

我怀疑 buffer_pool 比 table(s) 小很多,并且正在发生很多事情。因此,查询的块被撞出 RAM,需要进行几十次读取才能将它们带回。

innodb_buffer_pool_size 应设置为可用 RAM 的 70% 左右。

更多(基于CREATE TABLE

“覆盖”INDEX(status, recipient, sender) 会更快——它不必反弹到数据;查询可以完全在索引中完成。

PRIMARY KEY 是一个键,所以INDEX(id) 是多余的,可以是DROPped

作为另一个键前缀的KEY 是多余的。我指的是您当前的CREATE TABLE 中的(status)

【讨论】:

  • 该表大约有 8000 万行。 innodb_buffer_pool_size 的值 = 2GB,RAM 大小为 8GB。以前我把innodb_buffer_pool_size配置为5GB,但是当我测试了很多查询请求,大概1000个请求/秒左右,MySQL突然死掉了。但是当我将其更改为 2GB 时,我从未体验过 MySQL 会自行死亡。
  • 不要一次画出一大堆。当查询太快,多次时,您经常会看到 MySQL server go away 错误。第二次立即查询可能会运行得更快,这可能是由于硬盘性能,其中 HDD 磁头非常靠近接下来要读取的数据。
  • @BimalPoudel 我尝试在这样的查询中使用 LIMIT:select sender as id from message where status=1 and recipient=1 LIMIT 0,100,但我仍然遇到同样的问题。
  • 请提供SHOW CREATE TABLE;我错过了一些微妙的东西。
  • INDEX(a), INDEX(a,b) -- 不需要前者,因为后者可以处理,比如WHERE a = 123,即使没有提到b
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-01-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-04-22
  • 1970-01-01
相关资源
最近更新 更多