Очень похожие запросы MySQL приводят к значительному изменению длительности запросов (ГДЕ на промежутках времени) - PullRequest
0 голосов
/ 08 октября 2018

У меня есть таблица MySQL с 600 строками в ней (Engine: InnoDB).MySQL работает на виртуальной машине с Ubuntu 16.04 LTS.Версия сервера MySQL 5.7.23, если это актуально.

Столбцы в предложениях WHERE (open_time и close_time) оба проиндексированы и оба являются столбцами DATETIME.

Столбец, в котором я беру сумму (объем), является двойным.

Этот запрос возвращает мгновенно (0,000 секунд):

SELECT *
FROM klines
WHERE (open_time between '2018-01-01 00:00:00' AND '2018-01-01 12:00:00')
;

EXPLAIN output: enter image description here

В то время как этот запрос занимает почти секунду, чтобыfetch (варьируется от 0,640 до 0,703 секунд между 10 попытками):

SELECT SUM(volume)
FROM klines
WHERE open_time >= '2018-01-01 00:00:00' AND close_time <= '2018-01-01 12:00:00'
;

EXPLAIN output: enter image description here

Помните, что оба запроса возвращают примерно одинаковые строки (720 для первого, 721 для второго. Второй запрос возвращает те же 720 строк, которые возвращает первая, плюс еще одна).

Итак, если я хочу получить только строки, не имеет значения, использую ли я предложение WHERE для двух столбцов или одного.Но если я хочу получить СУММУ столбца, запрос становится значительно медленнее, когда я использую предложение WHERE для двух столбцов.Однако, если я использую один столбец, он снова мгновенно возвращается.

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

Итак, что может быть причиной этого?

1 Ответ

0 голосов
/ 09 октября 2018
open_time between '2018-01-01 00:00:00'
              AND '2018-01-01 12:00:00'

может легко использовать INDEX(open_time), чтобы касаться только интересных строк.Но для этого невозможно иметь индекс, который останавливается внезапно:

     open_time >= '2018-01-01 00:00:00'
AND close_time <= '2018-01-01 12:00:00'

INDEX(open_time) можно использовать, но последняя половина таблицы будет сканироваться.INDEX(close_time), аналогично, будет сканировать первую половину таблицы.И теперь есть способ сделать и то и другое.

У вас , вероятно, есть дополнительное ограничение, которое нигде не видно:

  • [open..close] диапазоны времени don'overlap?
  • open is всегда

Они не могут быть заданы в стандартном SQL, и при этом не существует какой-либо формулировки индекса, которая могла бы использовать любое из ограничений.

Вот две строки, которые могут испортить любую попытку оптимизации:

INSERT INTO klines (open_time,             close_time)
            VALUES ('2018-01-01 06:00:00', '2037-12-31'),
                   ('1971-01-01',          '2018-01-01 06:00:00')
                   ('2037-01-01',          '1971-01-01')

Существуют исправления, но они требуют либо предположения, что они не перекрываются, то игра с запросами является серьезным способом;или играя с ведрами.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...