Почему целочисленное сравнение MySQL выполняется медленнее, чем сравнение null и datetime? - PullRequest
0 голосов
/ 28 мая 2020

Я использую MySQL 5.7.

Существует таблица с именем transactions с более чем 3 миллионами записей. Схема таблицы выглядит следующим образом:

  1. id - INT (автоинкременты)
  2. deleted_at (DATETIME, допускается NULL)
  3. record_status (TINYINT , Значение DEFAULT равно 1)
  4. Другие столбцы, относящиеся к этой таблице ...

record_status - это целочисленная версия deleted_at. При удалении записи устанавливается значение 0. Для этого столбца также создается индекс.

Для выполнения запроса DATETIME на основе NULL требуется 740 ms:

select transactions.id from transactions where transactions.deleted_at is null

Для выполнения запроса на основе TINYINT требуется 15.1 s:

select transactions.id from transactions where transactions.record_status = 1

Разве проверка столбца TINYINT (с индексом) не должна выполняться быстрее? Почему это происходит?

[РЕДАКТИРОВАТЬ]

Добавлена ​​информация о производительности таблицы

Чтобы продолжить эксперимент, все ненужные столбцы были удалены из Таблица. Сохраняется только следующее.

  1. id - INT (автоинкременты)
  2. deleted_at (DATETIME, допускается NULL)
  3. record_status (TINYINT, DEFAULT значение равно 1)
  4. transaction_time (DATETIME)

Запрос 1: занимает 2,3 мс

select transactions.id from transactions
where transactions.record_status = 1 limit 1000000;

Запрос 2: занимает 2,1 мс

select transactions.id from transactions 
where transactions.deleted_at is null limit 1000000;

Запрос 3: занимает 20 секунд

select transactions.id from transactions 
where transactions.record_status = 1 
and transaction_time > '2020-04-01' limit 1000;

Запрос 4: занимает 500 мс

select transactions.id from transactions 
where transactions.deleted_at is null 
and transaction_time > '2020-04-01' limit 1000;

Запрос 5: 394 мс

select transactions.id from transactions
where transaction_time > '2020-04-01' limit 1000000;

Я не могу понять, почему Query 3 занимает так много времени.

Ответы [ 2 ]

0 голосов
/ 30 мая 2020
select transactions.id from transactions 
where transactions.record_status = 1 
and transaction_time > '2020-04-01' limit 1000;

невозможно оптимизировать без такого составного индекса - в таком порядке:

INDEX(record_status, transaction_time)

(Нет, два отдельных индекса с одним столбцом тоже не будут работать.)

0 голосов
/ 28 мая 2020

Проблема устранена путем добавления составного индекса.

Оба следующих результата теперь обеспечивают высокую производительность.

  1. Составной ключ для transaction_time и deleted_at.
  2. Составной ключ на transaction_time и record_status.

Спасибо @Gordon Linoff и @jarlh. Их предложения привели к такому выводу.

...