如何处理大表上的左联接?发生意外行为

时间:2019-01-31 11:11:25

标签: php mysql sql symfony

我有我的SQL查询的问题:

表价格数百万行,必须正确查询。一切运行良好,并且页面花费了约400ms的加载时间,直到我对数据库进行了更新(使用Prod数据库中的新数据库对其进行了更新),并且一切都中断了。现在加载页面需要120秒。

它的运行就好在我们的督促和预督促环境,但在我的dev的包膜超慢。我正在使用相同的mysql版本和php版本。将Symfony 4与教义2 ORM结合使用。

我正在处理的查询如下:

SELECT 
c0_.id AS id_0, 
c0_.ticker AS ticker_1, 
c0_.name AS name_2, 
p1_.id AS id_3, 
p1_.rank AS rank_4, 
p1_.price_usd AS price_usd_5, 
p1_.1d_volume_usd AS 1d_volume_usd_6, 
p1_.change_1h AS change_1h_7, 
p1_.change_1d AS change_1d_8, 
p1_.change_7d AS change_7d_9, 
c2_.id AS id_10, 
c2_.market_cap AS market_cap_11, 
s3_.id AS id_12, 
s3_.score_buzz AS score_buzz_13, 
s3_.score_average AS score_average_14 
FROM coins c0_ 
LEFT JOIN prices p1_ ON c0_.id = p1_.ticker_id 
AND (p1_.last_updated >= ?) LEFT JOIN cmc c2_ ON c0_.id = c2_.ticker_id 
AND (c2_.last_updated >= ?) LEFT JOIN scores s3_ ON c0_.id = s3_.ticker_id 
AND (s3_.to_datetime >= ?) 
WHERE c0_.is_active = 1 ORDER BY c0_.rank_cmc ASC, p1_.last_updated DESC, c2_.last_updated DESC, s3_.to_datetime DESC

问题出在那部分:

LEFT JOIN prices p1_ ON c0_.id = p1_.ticker_id AND (p1_.last_updated >= ?)

如果我删除了这部分它工作得很好。 铅从哪里来?为什么同一查询有2个不同的行为(prod和dev)? 通常如何处理大表上的左联接?

谢谢

编辑: 这是DEV中查询的说明: enter image description here

这是PROD中查询的解释: enter image description here

EDIT2: 开发价格指数: enter image description here

2 个答案:

答案 0 :(得分:1)

在“键”列的p1_行上查看prod和dev解释查询: 在开发中为NULL 在产品中是search_idx。

结论:如果在prod和dev环境中运行“ bin / console d:s:u --dump-sql”,则需要在dB模式中找到一些差异。

答案 1 :(得分:1)

可能有很多原因。您会在开发服务器上看到快速的结果,因为记录较少,而实时服务器包含大量记录(请参阅explait语句中的rows列)。

我建议检查所有键和您的join列类型。与“ on”子句结合使用的每一列都应具有相似的类型,否则将会减慢速度。因此,请确保列为int+unsignedvarchar等。

在输出中查找possible_key, key and extra列,并尝试从以下链接中了解,这将帮助您找到合适的解决方案

https://dev.mysql.com/doc/refman/8.0/en/explain-output.html

另请参见上面链接中的“解释输出解释”部分。