Home >Backend Development >PHP Tutorial >symfon2中生成的sql语句带有DISTINCT,效率很慢?

symfon2中生成的sql语句带有DISTINCT,效率很慢?

WBOY
WBOYOriginal
2016-06-06 20:18:451315browse

用 sonata-project/admin-bundle 做的后台,上线2个月左右,出现了一个性能问题,把调试工具打开发现在查询列表的时候 有2条SQL语句执行特别慢
symfon2中生成的sql语句带有DISTINCT,效率很慢?

以上两条SQL随着项目的增大,执行时间越来越长。目前150W左右数据执行时间需要 18058.10 ms

我猜想是 knplabs/knp-paginator-bundle 在分页和查询总数的时候 总数带上了关键字 "DISTINCT"

我把这两条语句的关键字 DISTINCT 去掉以后,直接拿到数据库执行只需要 5ms 。所以我去查找 symfony2、sonata-project/admin-bundle、knplabs/knp-paginator-bundle 对于这个关键字的处理或者配置,但是持续查找了快一个礼拜都没有结果。

希望有知道这个问题的大神能够帮助我分析分析

回复内容:

用 sonata-project/admin-bundle 做的后台,上线2个月左右,出现了一个性能问题,把调试工具打开发现在查询列表的时候 有2条SQL语句执行特别慢
symfon2中生成的sql语句带有DISTINCT,效率很慢?

以上两条SQL随着项目的增大,执行时间越来越长。目前150W左右数据执行时间需要 18058.10 ms

我猜想是 knplabs/knp-paginator-bundle 在分页和查询总数的时候 总数带上了关键字 "DISTINCT"

我把这两条语句的关键字 DISTINCT 去掉以后,直接拿到数据库执行只需要 5ms 。所以我去查找 symfony2、sonata-project/admin-bundle、knplabs/knp-paginator-bundle 对于这个关键字的处理或者配置,但是持续查找了快一个礼拜都没有结果。

希望有知道这个问题的大神能够帮助我分析分析

tuser_recharge.user_id 看上去必是 user.id 的子集,你在tuser_recharge(1.5m)上做DISTINCT,再怎么JOIN也没什么用,况且两个语句并不从user表关联取值,所以JOIN是多余的。

但真正的问题还是在tuser_recharge的数据量,1.5m数据作DISTINCT,哪怕user_id有索引也不影响DISTINC的执行,mysql会遍历整个索引,1.5m记录,假设索引里单记录执行花费0.00001秒,光遍历索引就需要大概0.000001x1500000=1.5秒,你画出的第一条语句的执行结果就在这个数量级上。

这你可以直接跑

<code>SELECT DISTINCT user_id 
FROM tuser_recharge
</code>

来验证,速度会在一个数量级上。

第二条语句要慢很多,是因为除了遍历整个1.5m的索引,还需要产生临时表做SORT(因为ORDER BY),慢是可想而知的。

优化的思路,第一是看你是否有用WHERE的可能,即避免让DISTINCT遍历整个索引,而用WHER先缩小范围。

<code>SELECT DISTINCT user_id
FROM tuser_recharge
WHERE col = xxx
</code>

如果业务不允许,那么最好的办法不是优化DINSTINCT,而是优化你的架构。通常操作思路是把前端代码和慢SQL语句解耦,做一个MYSQL SLAVE,用一个后台程序定时执行慢语句,把结果存入某个地方,前端语句直接读取这个结果,不经过mysql。这样的好处是前端不会再有伸缩性问题,坏处是牺牲了一定的实时性。如果你控制后台语句每一分钟执行一次,对一般业务也不至于产生什么问题。通常用户前端有一分钟或者几分钟的延迟并不是什么大问题。

这样做你在架构上的收益是最大的,因为一个慢语句的成本不只是这个慢语句本身,还会BLOCK其他语句的执行,这是在线系统数据库最应该避免的。

Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn