主题
面试速答(先看这里)
**一句话结论:**很多人应该都见过这种写法,就是在for循环中去不断地调用数据库,其实这么做是不好的,不建议大家这么干,主要有几个问题。
60秒标准回答:
很多人应该都见过这种写法,就是在for循环中去不断地调用数据库,其实这么做是不好的,不建议大家这么干,主要有几个问题
有些数据库的调用方式,会创建数据库链接,然后再关闭数据库链接, 如果在for循环中不断地进行数据库调用,就会导致大量的链接创建和关闭,会增加很多额外的网络开销
就算是共用同一个connection,但是在每次执行CRUD的时候,都需要和数据库做一次网络交互,而这个过程也是有网络开销的,会使得整个方法的耗时比较长
**答题顺序:**结论 → 原理/机制 → 关键流程 → 场景与取舍 → 易错点
回答主线:
- **要点1:**有些数据库的调用方式,会创建数据库链接,然后再关闭数据库链接, 如果在for循环中不断地进行数据库调用,就会导致大量的链接创建和关闭,会增加很多额外的网络开销。
- **要点2:**另外, 如果是写操作的话,在for循环中进行的话,如何做事务管理是个比较大的风险, 如果在方法外加了个整体的大事务,那么for循环执行到最后的时候,如果失败了,导致整体回滚,那么也是有很多成本在的。
- **要点3:**所以,应该尽量的避免在for循环中做数据库操作,尤其是写操作。
- **要点4:**替代的方式有以下几个,首先 如果是读操作,那么可以通过in来代替for循环查询 , SELECT*FROMtableWHERE id IN (1, 2, 3, 4); 这样就能通过一条SQL进行查询,只需要和数据库建立一次链接和通信。
- **要点5:**还有就是 如果是写操作,那么可以借助批量操作的方法 ,如mybatis中的SqlSession中的batchInsert、batchUpdate等,实现多条数据进行批量的写入和更新。
**记忆锚点:**for → FROMtableWHERE → batchInsert → batchUpdate → connection → 外加了个整体的大事务
易错提醒:
- 很多人应该都见过这种写法,就是在for循环中去不断地调用数据库,其实这么做是不好的,不建议大家这么干,主要有几个问题。
- 另外, 如果是写操作的话,在for循环中进行的话,如何做事务管理是个比较大的风险, 如果在方法外加了个整体的大事务,那么for循环执行到最后的时候,如果失败了,导致整体回滚,那么也是有很多成本在的。
加分表达:
- 有些数据库的调用方式,会创建数据库链接,然后再关闭数据库链接, 如果在for循环中不断地进行数据库调用,就会导致大量的链接创建和关闭,会增加很多额外的网络开销。
追问准备:
- 围绕「for」:底层原理是什么?使用时有哪些边界和常见坑?
- 围绕「FROMtableWHERE」:底层原理是什么?使用时有哪些边界和常见坑?
- 围绕「batchInsert」:底层原理是什么?使用时有哪些边界和常见坑?
- 如果线上出现异常,你会如何定位、验证并规避?
典型回答
很多人应该都见过这种写法,就是在for循环中去不断地调用数据库,其实这么做是不好的,不建议大家这么干,主要有几个问题。
有些数据库的调用方式,会创建数据库链接,然后再关闭数据库链接,如果在for循环中不断地进行数据库调用,就会导致大量的链接创建和关闭,会增加很多额外的网络开销。
就算是共用同一个connection,但是在每次执行CRUD的时候,都需要和数据库做一次网络交互,而这个过程也是有网络开销的,会使得整个方法的耗时比较长。
另外,**如果是写操作的话,在for循环中进行的话,如何做事务管理是个比较大的风险,**如果在方法外加了个整体的大事务,那么for循环执行到最后的时候,如果失败了,导致整体回滚,那么也是有很多成本在的。
所以,应该尽量的避免在for循环中做数据库操作,尤其是写操作。
替代的方式有以下几个,首先如果是读操作,那么可以通过in来代替for循环查询,SELECT*FROMtableWHERE id IN (1, 2, 3, 4); 这样就能通过一条SQL进行查询,只需要和数据库建立一次链接和通信。
还有就是如果是写操作,那么可以借助批量操作的方法,如mybatis中的SqlSession中的batchInsert、batchUpdate等,实现多条数据进行批量的写入和更新。
还有就是其实,很多操作,是可以考虑异步进行的,尤其是一些流水、记账等操作,往往都需要批量执行,这些都可以放到异步链路上去执行。具体的方案可以是通过扫表,或者线程池来实现。