Here is the table data
id | time | amount |
---|---|---|
1 | 20221104 | 15 |
2 | 20221104 | 10 |
3 | 20221105 | 7 |
4 | 20221105 | 19 |
5 | 20221106 | 10 |
The id and time field is asc, but time can be same.
The rows are very large, so we don’t want to use page limit offset method, but with cursor id.
first query:
select * from t where time > xxx and time < yyy order by id asc limit 10;
get the biggest id zzz, then
next query:
select * from t where time > xxx and time < yyy and id > zzz order by id asc limit 10;
How should I build the index?
If I use id as index, the time range will cause huge scan if time is far away.
And If I use time as index, seek id will not be effective.
4
Answers
The following index should be enough for both queries:
Note, use proper date/datetime data types , will save a lot of pain in the future
The key is composite index by leftmost prefixing principle. But both queries here start with
range expression. So I suppose that simply creating index on
(a, b)
is unable to optimize effectivelybecause indexing process stops after range condition. It is enough to create index like this:
More can be referenced here:
First I agree with @ErgestBasha Suggestion:
If you follow the general performance rules:
As you can see, It uses the indexes defined (time,id) and uses the range scan access method. Also Extra column you can see that index is used during operation!
See this for iterating through a compound key:
http://mysql.rjweb.org/doc.php/deletebig#iterating_through_a_compound_key
It cannot be done with two
ANDs
; tt needs oneAND
and oneOR
.See this for why
OFFSET
should be avoided when Paginating