效果
优化之前,查询近一个月接口响应时间:20秒,优化之后,接口响应时间:3-4秒
背景
运维监控TiBD数据库运行情况,发现某些时段CPU过高,然后查看慢SQL日志,把慢SQL反馈给开发人员。SQL的业务背景,分页查询订单,并把符合查询条件的金额等数值进行统计
问题分析
1、该接口主要是分页查询+业务统计查询,分页查询用了插件,其中插件中的count()查询可在业务统计查询中所得
2、分页SQL查询慢,尝试能否优化
优化方案
1、取消分页插件,手动分页
2、从统计SQL中获取总条数(分页所需的数据),减少一次SQL查询
3、改造分页SQL,先根据查询条件得到id集合,再根据id集合查询最终所需的数据
SQL优化
优化前的SQL(提供参考)
分页
SELECT o.id AS id,
o.order_id AS orderId,
o.user_id AS userId,
o.merchant_id AS merchantId,
o.amount AS amount
FROM order o
<include refid="order_where_inside"/>
ORDER BY po.create_time DESC
LIMIT #{dto.limitBegin}, #{dto.pageSize}
统计
SELECT
/*+ read_from_storage(tiflash[o]) */
o.merchant_id AS merchantId,
sum(o.amount) AS amount
FROM
order o
<include refid="order_where_inside"/>
GROUP BY merchant_id
优化后的SQL(提供参考)
分页
SELECT o.id
FROM order o
<include refid="order_where_inside"/>
ORDER BY o.create_time DESC
LIMIT #{dto.limitBegin}, #{dto.pageSize}
SELECT o.id AS id,
o.order_id AS orderId,
o.user_id AS userId,
o.merchant_id AS merchantId,
o.amount AS amount
FROM order o
WHERE o.id IN
<foreach collection="ids" item="item" open="(" close=")" separator=",">
#{item}
</foreach>
ORDER BY o.create_time DESC
统计
SELECT
/*+ read_from_storage(tiflash[o]) */
o.merchant_id AS merchantId,
sum(o.amount) AS amount,
...
-- 分页所用的count
count(o.id) AS totalOrder
FROM
order o
<include refid="order_where_inside"/>
GROUP BY merchant_id
尝试过优化失败的方案
查询条件得到id集合当做子查询,整合成一条SQL,执行效率有点出乎意料,优化器反而没怎么使用上索引,导致效率低下
总结
1、SQL上线前需要看看执行效率,判断有没有优化的空间
2、分页插件需好用,也需要根据实际业务判断是否有影响
3、可以根据业务场景建立多个从库,比如用户版读库,商家版读库,不同的库用不同的索引