@maksam07

Как оптимизировать запрос с подзапросами с COUNT?

Добрый день. В плагине для вордпресса есть запрос такого характера:
SELECT *
  ,(SELECT COUNT(comment_system.id) FROM comment_system WHERE itemtype='qqq' AND item_id = ebids.id) AS has_qqq_comment 
  ,(SELECT COUNT(comment_system.id) FROM comment_system WHERE itemtype='www' AND item_id = ebids.id) AS has_www_comment 
  ,(SELECT COUNT(comment_system.id) FROM comment_system WHERE itemtype='eee' AND item_id = ebids.id) AS has_eee_comment
FROM ebids
WHERE status != 'auto'
ORDER BY id DESC
LIMIT 0, 100


Когда используются подзапросы: (SELECT COUNT(comment_system.id) FROM ... ) AS has_qqq_comment
То весь запрос выполняется на 2-4 секунды дольше
В таблице comment_system всего около 50к записей. Индексы на itemtype и item_id стоят вместе и по отдельности.
Можно это как-то оптимизировать?
Без подзапросов запрос выполняется считай моментально

explain
62e13fe913954693404664.png
  • Вопрос задан
  • 226 просмотров
Пригласить эксперта
Ответы на вопрос 3
Rsa97
@Rsa97
Для правильного вопроса надо знать половину ответа
DEPENDENT SUBQUERY - это очень плохо. Это значит, что подзапрос вызывается заново для каждой строки из основной таблицы.
SELECT `ebids`.*, IFNULL(`c`.`qqq`, 0) AS `has_qqq_comment`,
       IFNULL(`c`.`www`, 0) AS `has_www_comment`, IFNULL(`c`.`eee`, 0) AS `has_eee_comment`
  FROM `ebids`
  LEFT JOIN (
    SELECT `item_id`, SUM(`itemtype` = 'qqq') AS 'qqq',
           SUM(`itemtype` = 'www') AS 'www', SUM(`itemtype` = 'eee') AS 'eee'
      FROM `comment_system`
      GROUP BY `item_id`
  ) AS `c` ON `c`.`item_id` = `ebids`.`id`
  WHERE `ebids`.`status` != 'auto'
  ORDER BY `ebids`.`id` DESC
  LIMIT 0, 100
Ответ написан
Комментировать
@Akina
Сетевой и системный админ, SQL-программист.
SELECT ebids.*
     , SUM(comment_system.itemtype='qqq') AS has_qqq_comment 
     , SUM(comment_system.itemtype='www') AS has_www_comment 
     , SUM(comment_system.itemtype='eee') AS has_eee_comment 
FROM ebids
JOIN comment_system ON comment_system.item_id = ebids.id
WHERE ebids.status != 'auto'
GROUP BY ebids.id
ORDER BY ebids.id DESC
LIMIT 0, 100
Ответ написан
Комментировать
mayton2019
@mayton2019
Bigdata Engineer
Вот эта колбаса - по смыслу - group-by с фильтрацией. Попробуй сделать из 3 запросов 1.
,(SELECT COUNT(comment_system.id) FROM comment_system WHERE itemtype='qqq' AND item_id = ebids.id) AS has_qqq_comment 
  ,(SELECT COUNT(comment_system.id) FROM comment_system WHERE itemtype='www' AND item_id = ebids.id) AS has_www_comment 
  ,(SELECT COUNT(comment_system.id) FROM comment_system WHERE itemtype='eee' AND item_id = ebids.id) AS has_eee_comment
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы