简体   繁体   中英

MySQL query sometimes run slow, sometimes fast

I am having problem with this simple MySQL query:

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

where sender table has multi millions of rows.

When I run this on SequelPro, it runs really slow for the first time, ~4 seconds or more, and the next execution it run really fast, ~0.018 seconds. However, if I run again after couple of minutes, it will do the same thing again.

I tried to use SQL_NO_CACHE, and it still gives me the same result.

The DB engine is innoDB, and the DB is MySQL Percona XtraDB cluster. Here is the explain results:

|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" is an index of multi-column of (recipient, status). Does anyone has any idea to fix this problem?

Thank you.

Added (from comment)

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;

Those symptoms point to caching issues. I don't mean the "Query cache", but rather the Engine's cache.

How big is the table? How big are all the the active tables?

What is the value of innodb_buffer_pool_size ?

I suspect the buffer_pool is a lot smaller than the table(s), and a lot of stuff is going on. Hence, the query's blocks get bumped out of RAM, necessitating a few dozen reads to bring them back in.

innodb_buffer_pool_size should be set to about 70% of available RAM.

More (based on CREATE TABLE )

The "covering" INDEX(status, recipient, sender) will be faster -- it won't have to bounce over to the data; the query can be done entirely in the index.

A PRIMARY KEY is a key, so INDEX(id) is redundant and can be DROPped .

A KEY that is a prefix of another key is redundant. I am referring to (status) in your current CREATE TABLE .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM