在网站上运行查询时(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"> </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"> </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"> </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"> </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"> </td></tr></tbody></table>
答案 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秒延迟的确切原因。您确定是您的数据库查询吗?