Laravel与慢的subSelect查询(MySQL)

时间:2019-01-22 18:30:39

标签: mysql laravel subquery

在网站上运行查询时(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

解释选择:

<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 :(得分:0)

您可以在这些大查询中删除这些查询

(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 

,因为它们对结果的贡献不大。分别添加这两列。

答案 1 :(得分:0)

首先,尝试看看您的查询计划是什么样的。您可以使用EXPLAIN命令进行检查。它将向您显示可以通过在需要的地方添加索引来提高性能的地方。

第二,我总是喜欢避免子选择。您可以使用外部select上的其他联接重写上述查询,并尽快将其过滤掉。您可以尝试以下方法并查看其比较结果:

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秒延迟的确切原因。您确定是您的数据库查询吗?