запрос выполняется слишком медленно - PullRequest
5 голосов
/ 23 сентября 2019

Приведена таблица mySQL с именем "user_posts" со следующими соответствующими полями:

  • user_id
  • user_status
  • influenr_status

индексируется во всех трех полях

Мой медленный запрос здесь, а также я создал dbFiddle .Вывод объяснения находится в dbfiddle :

SELECT 
   P.user_post_id,     
   P.user_id_fk,P.post_type,
   P.who_can_see_post,
   P.post_image_id,P.post_video_id, 
   U.user_name, U.user_fullname,U.influencer_status 
 FROM user_posts P FORCE INDEX (ix_user_posts_post_id_post_type)
   INNER JOIN users U FORCE INDEX (ix_status_istatus)
   ON P.user_id_fk = U.user_id 
 WHERE 
   U.user_status='1' AND 
   U.influencer_status = '1' AND 
   (P.who_can_see_post IN('everyone','influencer','friends')) AND 
   (P.post_type IN('image','video'))
   AND p.user_post_id > 30
 ORDER BY 
    P.user_post_id 
 DESC LIMIT 30

Запрос занимает очень много времени, около 6-15 секунд.В противном случае база данных не очень загружена и хорошо справляется с другими запросами.

Мне, очевидно, интересно, почему запрос такой медленный.

Есть ли способ точно сказать, что так долго занимает mySQL?Или мне нужно внести изменения, чтобы запрос выполнялся быстрее?

Ответы [ 2 ]

5 голосов
/ 23 сентября 2019

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

ALTER TABLE `users`
  ADD PRIMARY KEY (`user_id`),
  ADD KEY ix_status_istatus (user_status, influencer_status);

позволяет использовать его и должно ускорить ваш запрос, изменив поиск на users, чтобы использовать index вместо temporary and filesort.

Демонстрация по dbfiddle

Обновление

Дальнейший анализ dbfiddle показывает, что также лучше удалить FORCE INDEXиз таблицы P, поскольку в этом нет необходимости (требуется только ключ PRIMARY), и измените JOIN на STRAIGHT_JOIN, то есть запишите JOIN как:

FROM user_posts P 
STRAIGHT_JOIN users U FORCE INDEX (ix_status_istatus)
ON P.user_id_fk = U.user_id
1 голос
/ 23 сентября 2019

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

Это все равно что выполнять фильтрацию во время объединения вместо объединения, а затем фильтрации.

Я проверил план запроса, которыйпоказывает полное использование индексов.

SELECT 
   P.user_post_id,     
   P.user_id_fk,P.post_type,
   P.who_can_see_post,
   P.post_image_id,
   P.post_video_id, 
   U.user_name, 
   U.user_fullname,
   U.influencer_status 

 FROM user_posts P

 INNER JOIN 
   users U 
       FORCE INDEX (
         users_user_status_index, 
         users_influencer_status_index
       )
   ON 
     U.user_id = P.user_id_fk AND 
     U.user_status='1' AND 
     U.influencer_status='1'

 WHERE 
   P.who_can_see_post IN('everyone','influencer','friends') AND 
   P.post_type IN('image','video') AND 
   P.user_post_id > 30

 ORDER BY 
    P.user_post_id DESC

 LIMIT 30

Созданные мной индексы:

ALTER TABLE `users`
  ADD PRIMARY KEY (`user_id`),
  ADD KEY users_user_status_index(user_status),
  ADD KEY users_influencer_status_index(influencer_status);

dbfiddle

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