Laravel с медленным запросом subSelect (MySQL) - PullRequest
0 голосов
/ 22 января 2019

При выполнении запроса на веб-сайте (запрос ajax, Laravel 5.7) он выполняется на 99% быстрее (где-то около 800 мс), но на 1% общее выполнение запроса может составлять до 50 секунд.

Чтопроблема такого поведения, есть ли какое-то кеширование?Кроме того, что-то должно быть оптимизировано?

Вот запрос (@numbers -> здесь идет массив до 250 чисел):

SELECT
var.g_id,
var.title,
lm_object.title AS ht_title,
lm_object.image_checked_at,
var.cot,
var.cca,
var.cot_cca,
var.rating,
var.lm_object_id AS var_id,
lm_object.id AS hot_id,
(SELECT link FROM lm_images WHERE typ = 1 AND thumb = 1 AND 
( id = var.id OR cot _cca = var.cot _cca ) LIMIT 1 ) AS th,
(SELECT link FROM lm_images WHERE typ = 2 AND thumb = 1 AND 
( id = var.id OR cot_cca = var.cot _cca ) LIMIT 1 ) AS th_1 
FROM lm_object
INNER JOIN lm_object_sar AS var ON lm_ object.id = var.lm_object_id 
WHERE
var.id IN ( @numbers...) 
AND lm_object.deleted_at IS NULL

EXPLAIN SELECT:

<table width="973" border="1"><thead><tr><td width="88"><p><strong>id</strong></p></td><td width="88"><p><strong>select_type</strong></p></td><td width="89"><p><strong>table</strong></p></td><td width="88"><p><strong>type</strong></p></td><td width="109"><p><strong>possible_keys</strong></p></td><td width="68"><p><strong>key</strong></p></td><td width="88"><p><strong>key_len</strong></p></td><td width="88"><p><strong>ref</strong></p></td><td width="89"><p><strong>rows</strong></p></td><td width="88"><p><strong>Extra</strong></p></td><td width="89">&nbsp;</td></tr></thead><tbody><tr><td width="88"><p>1</p></td><td width="88"><p>PRIMARY</p></td><td width="89"><p>var</p></td><td width="88"><p>range</p></td><td width="109"><p>g_id_cot_cca,g_id,lm_objects_id</p></td><td width="68"><p>g_id_cot_cca</p></td><td width="88"><p>5</p></td><td width="88"><p><em>NULL</em></p></td><td width="89"><p>246</p></td><td width="88"><p>Using index condition; Using where</p></td><td width="89">&nbsp;</td></tr><tr><td width="88"><p>1</p></td><td width="88"><p>PRIMARY</p></td><td width="89"><p>lm_objects</p></td><td width="88"><p>eq_ref</p></td><td width="109"><p>PRIMARY</p></td><td width="68"><p>PRIMARY</p></td><td width="88"><p>4</p></td><td width="88"><p>mydb.var.lm_objects_id</p></td><td width="89"><p>1</p></td><td width="88"><p>Using where</p></td><td width="89">&nbsp;</td></tr><tr><td width="88"><p>3</p></td><td width="88"><p>DEPENDENT SUBQUERY</p></td><td width="89"><p>lm_images</p></td><td width="88"><p>ALL</p></td><td width="109"><p>g_id,cot</p></td><td width="68"><p><em>NULL</em></p></td><td width="88"><p><em>NULL</em></p></td><td width="88"><p><em>NULL</em></p></td><td width="89"><p>119603</p></td><td width="88"><p>Using where</p></td><td width="89">&nbsp;</td></tr><tr><td width="88"><p>2</p></td><td width="88"><p>DEPENDENT SUBQUERY</p></td><td width="89"><p>lm_images</p></td><td width="88"><p>ALL</p></td><td width="109"><p>g_id,cot</p></td><td width="68"><p><em>NULL</em></p></td><td width="88"><p><em>NULL</em></p></td><td width="88"><p><em>NULL</em></p></td><td width="89"><p>119603</p></td><td width="88"><p>Using where</p></td><td width="89">&nbsp;</td></tr></tbody></table>

Ответы [ 2 ]

0 голосов
/ 22 января 2019

Прежде всего попробуйте и посмотрите, как выглядит ваш план запроса. Вы можете проверить это с помощью команды EXPLAIN. Он покажет вам, где вы можете повысить производительность, добавив индексы, где это необходимо.

Во-вторых, я всегда предпочитаю избегать подселектов. Вы можете переписать вышеупомянутый запрос, используя дополнительные объединения на внешнем выделении, и отфильтровать их, как только сможете. Вы можете попробовать следующее и посмотреть, как оно сравнивается:

SELECT *
FROM lm_object
INNER JOIN lm_object_sar var
  ON lm_object.id = var.lm_object_id
LEFT JOIN lm_images img1
  ON img1.typ = 1
  AND img1.thumb = 1
  AND (
    img1.id = var.id
    OR img1.cot_cca = var.cot_cca
  )
LEFT JOIN lm_images img2
  ON img2.typ = 2
  AND img2.thumb = 1
  AND (
    img2.id = var.id
    OR img2.cot_cca = var.cot_cca
  )
WHERE var.id IN (@numbers...)
AND lm_object.deleted_at IS NULL

Обратите внимание, что приведенное выше вернет несколько строк, если вы можете иметь больше записей img1 и img2; Я вижу, вы применили LIMIT 1, что заставляет меня думать, что в результате этих фильтров вы можете получить больше строк.

Если это так, то, вероятно, лучше просто запросить их по отдельности в вашем коде, чем пытаться втиснуть его в один "большой" запрос.

Также рассмотрите возможность мониторинга вашего приложения с помощью службы, такой как newRelic; это может дать вам представление о том, что именно послужило причиной задержки в 50 секунд. Вы уверены, что это ваш запрос к базе данных?

0 голосов
/ 22 января 2019

Вы можете удалить эти запросы как часть этого большого запроса

(SELECT link FROM lm_images WHERE typ = 1 AND thumb = 1 AND 
( id = var.id OR cot _cca = var.cot _cca ) LIMIT 1 ) AS th,
(SELECT link FROM lm_images WHERE typ = 2 AND thumb = 1 AND 
( id = var.id OR cot_cca = var.cot _cca ) LIMIT 1 ) AS th_1 

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

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