0

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

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

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

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

我尝试使用 SQL_NO_CACHE,它仍然给我相同的结果。

DB引擎是innoDB,DB是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;
4

1 回答 1

1

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

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

的价值是innodb_buffer_pool_size多少?

我怀疑 buffer_pool 比 table(s) 小很多,而且还有很多事情要做。因此,查询的块被撞出 RAM,需要几十次读取才能将它们带回。

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

更多(基于CREATE TABLE

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

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

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

于 2016-03-11T04:45:56.973 回答