同一条sql同一个数据库,为什么在脚本上运行比在java应用运行快多了(springboot+mybatis+sqlserver)
java sql监考:
sqlserver脚本执行这条sql只需要1s不到,而java应用上要10s,执行该接口无其它业务,而且同环境下其它接口效率正常
使用相同的参数单独调用接口看下耗时,是不是有可能当时有别的SQL查询相关表导致。
select si.xm as name, si.xh, d.name as bjmc, si.xymc, i.chg_year as chgYear, i.chg_type as chgType,
i.account as payable, (isnull(fi.fact_account, 0) - isnull(rf.re_account, 0)) as payin,
(isnull(i.account, 0) - isnull(fi.fact_account, 0) + isnull(rf.re_account, 0)) as payout,
'--' as payMode
from (select xh, chg_year, chg_type, account from Stu_Chg_Info where chg_year > #{xn,jdbcType=VARCHAR}) i
left join Stu_Fact_Chg_Info fi on (i.xh = fi.xh and i.chg_type = fi.chg_type and i.chg_year = fi.chg_year and isnull(fi.djzt, 0) = 0)
left join Re_Fact_Chg rf on (i.xh = rf.xh and i.chg_type = rf.chg_type and i.chg_year = rf.chg_year and isnull(rf.djzt, 0) = 0)
left join Stu_Info si on (i.xh = si.xh and si.xn >= #{xn,jdbcType=VARCHAR})
left join department d on si.bjdm = d.code
<where>
<if test="zjh != null and zjh != ''">and (si.xh = #{zjh,jdbcType=VARCHAR} or si.xm = #{zjh,jdbcType=VARCHAR} or si.sfzh = #{zjh,jdbcType=VARCHAR})</if>
<if test="chgYear != null and chgYear != ''">and i.chg_year = #{chgYear,jdbcType=VARCHAR}</if>
<if test="chgType != null and chgType != ''">and i.chg_type = #{chgType,jdbcType=VARCHAR}</if>
<if test="payItems != null and payItems.length != 0">
and i.chg_type in
<foreach collection="payItems" open="(" close=")" item="item" separator=",">
#{item,jdbcType=VARCHAR}
</foreach>
</if>
<if test="startDate != null">fi.datetime >= #{startDate,jdbcType=TIMESTAMP}</if>
<if test="endDate != null">fi.datetime <= #{endDate,jdbcType=TIMESTAMP}</if>
</where>
order by si.xymc, si.bjdm, si.xh, i.chg_year desc, i.chg_type
应用上的SQL日志贴下
数据库有自己的缓存机制吧,mybatis解析xml中的逻辑判断也要时间,网络等问题也会影响java连接数据库的速度,理论上来说应该不会有十倍这么大的差异,你可以把where后边条件都给去掉,看看是不是还得十多秒
可能的原因有:
网络延迟:Java应用和数据库之间的网络延迟比脚本执行的本地数据库要高,这可能导致Java应用的执行速度变慢。
数据库链接池:Java应用使用的数据库链接池可能不够优化,导致在执行查询时需要等待可用的链接,从而导致执行速度变慢。
SQL优化:脚本执行和Java应用执行的SQL语句可能不同,或者Java应用执行的SQL语句没有进行优化,导致执行速度变慢。
解决思路:
确认网络延迟问题是否存在,可以使用ping命令或者traceroute命令检查网络延迟情况。
确认数据库链接池是否优化,可以检查Java应用的数据源配置,例如是否开启了缓存,是否使用了连接池。
确认SQL语句是否优化,可以使用数据库的查询分析工具,例如SQL Server的查询分析器,来分析SQL语句的执行计划,找出性能瓶颈所在,并进行优化。例如添加索引、避免使用子查询等。
示例代码:
Runtime runtime = Runtime.getRuntime();
Process process = runtime.exec("ping -c 3 " + dbHost);
int exitValue = process.waitFor();
if (exitValue == 0) {
System.out.println("Ping成功");
} else {
System.out.println("Ping失败");
}
<!-- 数据源配置 -->
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
destroy-method="close">
<property name="driverClassName" value="com.mysql.jdbc.Driver" />
<property name="url" value="jdbc:mysql://localhost:3306/test" />
<property name="username" value="root" />
<property name="password" value="123456" />
<property name="maxActive" value="50" />
<property name="maxIdle" value="10" />
<property name="maxWait" value="5000" />
</bean>
-- 查询分析器
SET SHOWPLAN_TEXT ON;
SELECT * FROM table WHERE id = 1;
SET SHOWPLAN_TEXT OFF;