简体   繁体   中英

How do I speed up this SQL query

I have the following query:

select min(a) from tbl where b > ?;

and it takes about 4 seconds on my mysql instance with index(b, a) (15M rows). Is there a way to speed it up?

Explain:

explain select min(parsed_id) from replays where game_date > '2016-10-01';

id:            1
select_type:   SIMPLE
table:         replays
partitions:    NULL
type:          range
possible_keys: replays_game_date_index,replays_game_date_parsed_id_index
key:           replays_game_date_parsed_id_index
key_len:       6
ref:           NULL
rows:          6854021
filtered:      100.00
Extra:         Using where; Using index

Index statement:

create index replays_game_date_parsed_id_index on replays (game_date, parsed_id);

I think the index MySQL is using is the right one. The query should be instantaneous since a SINGLE read from the index should return the result you want. I guess for this query MySQL's SQL optimizer is doing a very poor job.

Maybe you could rephrase your query to trick the SQL optimizer onto using a different strategy. Maybe you can try:

select parsed_id 
from replays
where game_date > '2016-10-01'
order by parsed_id
limit 1

Is this version any faster?

select @mina
fro (select (@mina := least(@mina, a)) as mina
     from tbl cross join
          (select @mina := 999999) params
     where b > ?
    ) t
limit 1;

I suspect this won't make much difference, but I'm not sure what happens under the hood with such a large aggregation function running over an index.

This may or may not help: Change the query and add an index:

SELECT a FROM tbl WHERE b > ? ORDER BY a LIMIT 1;

INDEX(a, b)

Then, if a matching b occurs soon enough in the table, this will be faster than the other suggestions.

On the other hand, if the only matching b is near the end of the table, this will have to scan nearly all the index and be slower than the other options.

a needs to be first in the index. By having both columns in the index, it becomes a "covering" index, hence a bit faster.

It may be that using my SELECT , together with two indexes will give the Optimizer enough to pick the better approach:

INDEX(a,b)
INDEX(b,a)

Schema

Adding either (or both) composite indexes should help.

Shrinking the table size is likely to help...

  • INT takes 4 bytes. Consider whether a smaller datatype would suffice for any of those columns.
  • There are 3 dates ( DATETIME , TIMESTAMP ); do you need all of them?
  • Is fingerprint varchar(36) a UUID/GUID? If so, it could be packed into BINARY(16) .

640MB is tight -- check the graphs to make sure there is no "swapping". (Swapping would be really bad for performance.)

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