造价算量系统SQL优化,慢查询从9秒压到35毫秒‌

造价算量系统SQL优化,慢查询从9秒压到35毫秒‌

去年在合肥给一家建筑工程公司做造价算量系统升级的时候,我遇到了一个非常典型的工程类数据库性能难题。他们的广联达算量导出的工程数据全部存在MySQL库里,单张工程明细表的数据量突破2700万行,造价师打开一个大型项目的算量汇总页面,要等9秒才能加载出来,有时候数据量大一点直接浏览器超时,很多老员工为了等页面加载,中途都能去接杯水走一圈。之前团队试过给算量字段随便加了几个索引,结果不仅没解决问题,写入算量数据的时候还经常出现锁等待,整个系统的使用体验越来越差。最后我们没有盲目堆索引,而是从业务逻辑底层拆解,结合Explain逐行对比执行计划,用了不到一周的时间就把所有核心慢查询全部优化到了百毫秒以内,造价师的日常工作效率直接提升了好几倍。

一、故障现场:算量系统卡顿的真实痛点

当时我到现场的时候,技术团队给我演示了一遍完整的卡顿场景:打开一个总建筑面积20万平的大型商业综合体项目,点击"全部分部分项工程量汇总"按钮,页面的加载进度条转了9秒才出结果,要是同时有3个造价师打开不同的大项目,数据库服务器CPU直接冲到95%,其他人连基础的清单查询都点不动。

1、 我们第一时间登上数据库服务器,打开慢查询日志统计TOP 10慢SQL,发现占比最高的就是这条算量汇总SQL,单条执行时间9.2秒,一天之内被调用了1200多次,几乎占了整个库慢查询总耗时的70%。

2、 用Explain第一次跑这条SQL的执行计划,结果出来之后我们就找到了第一个大问题:执行计划的type字段是ALL,直接全表扫描2700万行数据,Extra里同时出现了Using where、Using temporary、Using filesort三个糟糕的标记,等于数据库要先把全表数据捞出来,创建临时表做分组聚合,最后还要做文件排序,性能自然差到离谱。

3、 接着我们排查索引体系,发现开发人员之前为了"优化"这条SQL,给清单编码字段单独建了一个普通索引,但是SQL里的查询条件写的是WHERE quantity > 0,这个条件根本走不到清单编码的索引,等于这个索引完全是白建的,一点作用都没发挥。更麻烦的是,他们还在这张表上建了5个完全重复的单列索引,每次导入广联达导出的上万条算量数据,写入耗时要花十几分钟,经常出现导入超时的问题。

二、逐层拆解:从执行计划到业务逻辑的全链路优化

我们没有一上来就直接建索引,而是先把这条SQL的业务逻辑从头到尾理清楚,再结合Explain的执行计划逐段优化,每一步都做前后对比,确保每一个改动都能实实在在提升性能。

1、 第一步先做冗余索引清理,我们用sys.schema_unused_indexes视图扫了全库所有索引,把5个从来没有被任何SQL调用过的死索引全部标记,分两批安全删除。清理完成之后,导入算量数据的写入耗时直接从15分钟降到了4分钟,写入性能提升了3倍多,全程没有影响任何在线业务。

2、 第二步重构核心覆盖索引,这条汇总SQL的查询条件是项目ID、分部分项编码,分组字段是清单编码、定额编号,返回的字段是工程量汇总、综合单价合价、材料总用量。我们直接把这些字段全部按顺序放进联合覆盖索引,让整条SQL不需要回表,不需要访问聚簇索引,直接通过索引就能拿到所有需要的数据:

sql

CREATE INDEX idx_cost_calc_cover ON project_detail(

project_id, sub_item_code,

list_code, quota_code,

quantity, total_price, material_total

);

索引创建完成之后,我们再跑Explain对比,type直接从ALL升级到了ref级别,rows预估值从2700万直接降到了12.6万,Extra里的Using temporary和Using filesort直接消失,变成了Using index,说明整条SQL完全通过索引就能完成查询,不需要任何额外的IO操作。

3、 第三步优化SQL本身的逻辑,原来的代码里写了很多完全没必要的子查询,先把全表数据查出来放到临时结果集,再做二次过滤,我们把嵌套子查询改写成了联合查询,把过滤条件下推到索引访问层,避免先拉大量无用数据再做过滤。优化完成之后,这条SQL的实际执行耗时从9.2秒直接降到了35毫秒,之前转9秒的页面现在点一下立刻就能出结果。

4、 第四步针对大型项目的历史汇总场景做预计算优化,很多造价师经常要反复查看同一个项目的汇总数据,我们写了一个轻量的定时任务,在项目算量完成提交的时候,自动触发一次汇总计算,把结果存入专门的预计算表。后续用户再打开汇总页面,直接查询预计算表,耗时不到5毫秒,完全不需要再扫描千万行明细表。

整个优化全部落地之后,我们做了一周的压力测试,同时模拟10个造价师打开不同的大型项目做汇总查询,数据库CPU使用率最高也没有超过30%,系统全程运行非常平稳,再也没有出现过之前的卡顿超时问题。

三、工程算量类数据库SQL优化的专属经验

做建筑工程领域的造价算量系统优化,和普通互联网系统有很大的区别,很多通用的调优经验在这里并不适用,我总结了几条踩过坑之后沉淀下来的实战经验。

1、 工程算量数据的特点是单项目数据量大、写入少查询多、聚合计算多,千万不要上来就用分库分表的方案,2000-3000万行的明细表,只要索引设计合理,完全可以在单库单表下跑到毫秒级响应,盲目分表只会给后续的跨项目汇总、数据导出带来无穷无尽的麻烦。

2、 造价系统里90%的慢查询都是汇总类SQL,这类SQL的优化优先级最高的就是做覆盖索引,把查询条件、分组字段、聚合返回字段全部放进索引,直接避免回表,这是性价比最高的优化手段,很多时候改完索引性能就能提升上百倍。

3、 绝对不要给定额编号、清单编码这类字符串字段单独建普通索引,这类字段的等值查询几乎永远会和项目ID绑定出现,把项目ID放在联合索引的最前面,过滤掉当前项目之外的所有数据,查询性能会比单列索引好一个量级。

4、 高频访问的大型项目汇总数据,一定要做预计算缓存,造价师修改算量数据的频率很低,大部分时间都是查看数据,预计算的更新频率完全可以跟上业务的修改节奏,同时能把查询性能做到极致,完全没必要每次打开页面都全量扫描明细表重新计算。

这次优化完成之后,这套算量系统平稳运行了两年多,期间接入了十几个大型市政项目的算量数据,总数据量突破4000万行,核心汇总查询依然能稳定在100毫秒以内,没有出现过性能倒退的问题,一线造价师的工作效率提升非常明显,再也不用坐在电脑前等着页面转圈加载。

💡注意:本文所介绍的软件及功能均基于公开信息整理,仅供用户参考。在使用任何软件时,请务必遵守相关法律法规及软件使用协议。同时,本文不涉及任何商业推广或引流行为,仅为用户提供一个了解和使用该工具的渠道。

你在生活中时遇到了哪些问题?你是如何解决的?欢迎在评论区分享你的经验和心得!

希望这篇文章能够满足您的需求,如果您有任何修改意见或需要进一步的帮助,请随时告诉我!

感谢各位支持,可以关注我的个人主页,找到你所需要的宝贝。

博文入口:山峰哥-CSDN博客 复制到【浏览器】打开即可,宝贝入口:夸克网盘分享 宝贝:夸克网盘分享

作者郑重声明,本文内容为本人原创文章,纯净无利益纠葛,如有不妥之处,请及时联系修改或删除。诚邀各位读者秉持理性态度交流,共筑和谐讨论氛围~

相关推荐
遇见小修修44 分钟前
打印机连不上电脑无法打印
大数据·运维·python·电脑
金立基胶粘1 小时前
纸袋热封胶是什么?它的特点与应用有哪些?
大数据·安全
AC赳赳老秦1 小时前
电力能源公开数据采集实操:用 OpenClaw 合规抓取电网电价与发电量数据,生成区域能源供需分析报告
大数据·数据库·人工智能·python·php·deepseek·openclaw
一切皆是因缘际会1 小时前
资源的适配
大数据·人工智能·算法
IT毕设实战小研1 小时前
基于大数据的WTA职业网球赛事演变与竞技格局数据可视化分析
大数据·后端·爬虫·python·信息可视化·课程设计
StarRocks_labs1 小时前
StarRocks 如何查询 Paimon 半结构化数据?Variant、Shredding 与 SQL 实践
starrocks·sql·paimon·variant·shredding
财迅通Ai1 小时前
光智科技战略升级:“影像、传感、链接”三重架构
大数据·科技·光智科技
生态学者1 小时前
香港理工大学Nature Communications:沿海塑料际古菌组特征及生态影响
大数据·人工智能·算法·r语言·微信公众平台
Discipline~Hai2 小时前
Linux网络编程05-sqlite3数据库
linux·c语言·网络·数据库·sqlite·linux应用软件编程