我遇到这个简单的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
"发送"是(收件人,状态)的多列索引。 有没有人有任何想法解决这个问题?
谢谢。
已添加(来自评论)
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;
答案 0 :(得分:0)
这些症状指向缓存问题。我不是指“查询缓存”,而是指引擎的缓存。
桌子有多大?所有活动表有多大?
innodb_buffer_pool_size
的价值是什么?
我怀疑buffer_pool比表格小很多,而且很多东西正在进行中。因此,查询的块会从RAM中突然出现,需要几十次读取才能将它们带回来。
innodb_buffer_pool_size
应设置为可用内存的70%左右。
更多(基于CREATE TABLE
)
“覆盖”INDEX(status, recipient, sender)
会更快 - 它不会反弹到数据;查询可以完全在索引中完成。
PRIMARY KEY
是密钥,因此INDEX(id)
是多余的,可以是DROPped
。
作为另一个密钥的前缀的KEY
是多余的。我指的是您当前(status)
中的CREATE TABLE
。