Как я могу ускорить этот запрос SQL - PullRequest
0 голосов
/ 20 декабря 2018

У меня следующий запрос:

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

, и это занимает около 4 секунд на моем экземпляре mysql с index(b, a) (15M строк).Есть ли способ ускорить его?

Объясните:

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

Указатель индекса:

create index replays_game_date_parsed_id_index on replays (game_date, parsed_id);

Ответы [ 3 ]

0 голосов
/ 20 декабря 2018

Эта версия быстрее?

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

Я подозреваю, что это не будет иметь большого значения, но я не уверен, что происходит под капотом с такой большой функцией агрегирования, работающей над индексом.

0 голосов
/ 23 декабря 2018

Это может или не может помочь: измените запрос и добавьте индекс:

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

INDEX(a, b)

Затем , если совпадение b произойдет достаточно скоро в таблице, это будетБыть быстрее, чем другие предложения.

С другой стороны, если единственное совпадение b ближе к концу таблицы, это должно будет сканировать почти весь индекс и работать медленнее, чем другие варианты.

a должен быть первым в индексе.Имея оба столбца в индексе, он становится индексом «покрытия», следовательно, немного быстрее.

Это может быть тем, что использует мой SELECT вместе с two индексов даст Оптимизатору достаточно, чтобы выбрать лучший подход:

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

Схема

Добавление одного (или обоих) составных индексов должно помочь.

Уменьшение размера таблицы может помочь ...

  • INT занимает 4 байта.Подумайте, подойдет ли меньший тип данных для любого из этих столбцов.
  • Есть 3 даты (DATETIME, TIMESTAMP);Вам все они нужны?
  • * * fingerprint varchar(36) UUID / GUID?Если это так, он может быть упакован в BINARY(16).

640MB плотно - проверьте графики, чтобы убедиться в отсутствии «замены».(Обмен был бы очень плох для производительности.)

0 голосов
/ 20 декабря 2018

Я думаю, что индекс, используемый MySQL, является правильным.Запрос должен быть мгновенным, так как одно чтение из индекса должно вернуть желаемый результат.Я предполагаю, что для этого запроса оптимизатор SQL MySQL работает очень плохо.

Возможно, вы могли бы перефразировать ваш запрос, чтобы обмануть оптимизатор SQL, используя другую стратегию.Может быть, вы можете попробовать:

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