十年DBA老兵:警惕,重Java轻SQL乃性能大忌(2)
战战兢兢,如履薄冰 没有任何的注释,代码中的表呀,字段呀什么的,我一个也不认识,唯一亲切的就是 select from where join group 这些被标绿的 SQL 关键字。
看来我不能从这位同事这里得到更多有价值的信息了。 按下 F5 查看执行计划: 执行计划中,表访问方式基本上都是 index scan,而且也并无大成本的操作。奇怪了,问题处在哪里呢?我又回到 SQL 窗口,按下 F8,果然只见时间过,不见数据出来。 在长期与 SQL 相伴的日子里,我养成了一个习惯,喜欢在边看着 Oracle 执行,一边分析代码,大有“我忙着分析,你也别闲着偷懒”的“小人嘴脸”。 这个 SQL 有两个部分,第一部分是用 with 封装了一个结果集,第二部分是对第一部分的结果集进行 group by 处理。根据过往经验,我将 SQL 复制到了另一个 SQL 窗口,选中 with 子句单独执行,秒出呀。 排除了子查询的性能嫌疑,那么很显然问题是出在第二部分的 SQL。第二部分 SQL 包含了 group by,难道是 group by 产生了性能问题。要知道,group by 等聚合操作的性能对数据量是极其敏感的。难道是 with 子查询的数据量非常大? 我赶紧 count 了第一部分 SQL 的结果集,显示不到 20 万数据。那就不应该呀,20 万数据做 group by 也不至于慢成“蜗牛”呀。 继续分析第二部分 SQL 代码,在 select 子句中,惊现 wm_concat 函数。此时,我还是有些小激动的,因为在之前也遇到过由于 wm_concat 引发的性能问题。为了验证判断,我将 wm_concat 注释掉,按F8 运行,果然飞快,不到 1s 就出结果。 至此,通过排除法,病因是找到了:由 wm_conca t引发了性能问题。 顺藤摸瓜,顺手牵羊 原因已经找到,那么对症又该如何下药呢?显然,从 SQL 功能上,wm_concat 是必须的,我也尝试过用 listagg 来替代 wm_concat,但是会因超过 4000 字符而报错。 其实 wm_concat 函数之所以慢,就是因为以 task_name 为维度需要拼凑的数据量太大导致的。难道就无解了吗? 我转念一想,为什么要用 wm_concat 函数?应用程序在拿到这个字段后做什么用呢?在前端页面显示吗? 这种显示是没有多大意义的,因为 wm_concat 的结果可能非常大,根本就显示不了。既然显示不完整,那么为什么又要从 DB 中获取完整的内容呢? 带着这些疑惑,我与 SQL 开发人员进行了沟通,原来,应用程序拿到这个 SQL 的数据后,并不是在前端页面展现,而是在应用程序中继续加工处理,在经过若干复杂的逻辑处理后,以另一种形式在页面展现。 此时,多年的从业经验告诉我:既然可以用 Java 来实现的业务逻辑,那么肯定也能在 DB 中通过 SQL 来实现,这样就可以避开 wm_concat 函数。 于是我决心深入了解业务功能,希望能从业务方案上有所突破。这样就形成了一个初步的工作计划:了解整体业务功能及逻辑-->了解应用程序处理逻辑-->改写 SQL 语句-->功能性测试-->性能轮回调整。 在大约两个小时的一对一讲解后,我基本上掌握了整体业务功能及逻辑、应用技术架构及处理逻辑。 这个其实是一个报表展现功能,是按区域、里程碑展现两个相邻里程碑之间的时间间隔,包括计划间隔时间与实际间隔天数(平均)。 (编辑:ASP站长网) |