Индекс Mysql плохо себя ведет в рельсах - PullRequest
0 голосов
/ 29 июня 2019

У меня есть приложение rails, размещенное на Mysql, есть таблица reservations с индексом, установленным в столбце rescheduled_reservation_id (обнуляемый).

В моем приложении rails есть две части для запроса резервирования с помощью полей rescheduled_reservation_id, как показано ниже:

Transit::Reservation.find_by(rescheduled_reservation_id: 25805)

и создайте следующий вывод журнала:

Transit::Reservation Load (60.3ms)  SELECT  `transit_reservations`.* FROM `transit_reservations` WHERE `transit_reservations`.`deleted_at` IS NULL AND `transit_reservations`.`rescheduled_reservation_id` = 25805 LIMIT 1

Однако другая часть приложения:

Transit::Reservation.where(rescheduled_reservation_id: 25805).last

с выводом журнала ниже

Transit::Reservation Load (2.3ms)  SELECT  `transit_reservations`.* FROM `transit_reservations` WHERE `transit_reservations`.`deleted_at` IS NULL AND `transit_reservations`.`rescheduled_reservation_id` = 25805  ORDER BY `transit_reservations`.`id` DESC LIMIT 1

Как хорошо видно первый запрос

Transit::Reservation Load (60.3ms)  SELECT  `transit_reservations`.* FROM `transit_reservations` WHERE `transit_reservations`.`deleted_at` IS NULL AND `transit_reservations`.`rescheduled_reservation_id` = 25805 LIMIT 1

заняло до 60 мсек, индекс, возможно, не использовался должным образом по сравнению с 2 мс в этом

Transit::Reservation Load (2.3ms)  SELECT  `transit_reservations`.* FROM `transit_reservations` WHERE `transit_reservations`.`deleted_at` IS NULL AND `transit_reservations`.`rescheduled_reservation_id` = 25805  ORDER BY `transit_reservations`.`id` DESC LIMIT 1

enter image description here

Я также пытался продолжить отладку, выполнив объяснение для обоих запросов, я получил тот же результат, т. Е. Использовался индекс rescheduled_reservation_id

enter image description here

Кто-нибудь сталкивался с этой проблемой? Мне интересно, может ли соединение MySQL с rails (я использую mysql2 gem) вызвать то, что сервер Mysql не выбрал правильный индекс

1 Ответ

2 голосов
/ 29 июня 2019

Это Редко, но Нормально.

Вероятный ответ: первое вхождение не нашло кешируемых блоков в нужном буфере.Таким образом, он должен был извлечь их с диска.На обычном жестком диске правило большого пальца составляет 10 мс на каждое обращение к диску.Таким образом, возможно, нужно было извлечь 6 блоков, что привело к 60,3 мс.

Другая возможность заключается в том, что другие действия мешали, тем самым замедляя эту операцию.

2,3 мс является разумным дляпростой запрос, подобный этому, может быть выполнен полностью с кэшированными блоками в оперативной памяти.

Был ли сервер недавно перезапущен?После перезагрузки в кеше ничего нет.Таблица больше innodb_buffer_pool_size?Если это так, то это приведет к тому, что время от времени будет происходить 60 мс - блоки будут выбиты.(Предостережение: буфер_пул не должен быть настолько большим, чтобы происходил «обмен».)

Блок занимает 16 КБ;он содержит несколько строк данных или строк индекса или узлов BTree.В зависимости от размера таблицы, даже этот «точечный запрос» может потребоваться для просмотра 6 или более блоков.

Если вы не получите 2.3ms в большинстве случаев времени,мы должны копать глубже.(Я намекнул на размеры, чтобы исследовать.)

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