none
用微软提供的JDBC执行存储过程时为什么会执行sp_sproc_columns RRS feed

  • 问题

  • 当数据库的连接数到在350以上时,CPU就会很高,根据监控发现在执行用户存储过程时会首先执行 "exec sp_sproc_columns @procedure_owner=dbo, @procedure_name=proc_name, @ODBCVer=3" 并且很消耗时间,这是怎么回事

        CallableStatement cstmt = con.prepareCall("{call proc_name(?, ?)}");
                cstmt.setInt(para1name, 5);
                cstmt.registerOutParameter(para2name, java.sql.Types.INTEGER);
                cstmt.execute();

    执行到    "CallableStatement cstmt = con.prepareCall("{call proc_name(?, ?)}"); " 数据库就会执行  "exec sp_sproc_columns @procedure_owner=dbo, @procedure_name=proc_name, @ODBCVer=3"这条语句,返回的是存储过程参数的信息.可是我已经通过cstmt.setInt(para1name, 5); 设置了参数名和值,为什么还要从数据库调用参数信息呢?


    我是天生我怕谁?
    2010年3月30日 7:21

答案

  • 一个原因是CallableStatement需要支持named parameter,在设定参数或者取结果时候,可能需要做name -- index转换。作为对比,PreparedStatement就只能用index设定参数。

    另外一个原因是,sp可以有很多参数并有默认值;这样对于程序里面没有指定的参数,它可以自动使用默认值。

    2010年4月1日 7:44
  • 根据我测试的结果这个版本的driver不使用名字参数可以避免调用sp_sproc_columns。这些地方包括: setXXX()/registerOutParameter()调用,getXXX()取返回结果。

    • 已标记为答案 pengzi 2010年5月6日 3:49
    2010年4月6日 6:11

全部回复

  • 一个原因是CallableStatement需要支持named parameter,在设定参数或者取结果时候,可能需要做name -- index转换。作为对比,PreparedStatement就只能用index设定参数。

    另外一个原因是,sp可以有很多参数并有默认值;这样对于程序里面没有指定的参数,它可以自动使用默认值。

    2010年4月1日 7:44
  • 看起来应该是在执行cstmt.setInt(para1name,5)这个语句之后,你才会在服务端看到exec sp_sproc_columns。不知道你用的jdbc driver是什么版本?

    作为性能优化,你可以考虑使用位置参数来避免这个开销。
    cstmt.setInt (1, 5);
    cstmt.registerOutParameter (2, java.sql.Types.INTEGER);

    2010年4月2日 5:31
  • 看起来应该是在执行cstmt.setInt(para1name,5)这个语句之后,你才会在服务端看到exec sp_sproc_columns。不知道你用的jdbc driver是什么版本?

    作为性能优化,你可以考虑使用位置参数来避免这个开销。
    cstmt.setInt (1, 5);
    cstmt.registerOutParameter (2, java.sql.Types.INTEGER);


    用的是: Microsoft SQL Server JDBC Driver 2.0

    是在   执行CallableStatement cstmt = con.prepareCall("{call proc_name(?, ?)}"); 之后就有exec sp_sproc_columns了.不是在cstmt.setInt(para1name,5)这个语句之后


    我是天生我怕谁?
    2010年4月2日 5:41
  • 根据我测试的结果这个版本的driver不使用名字参数可以避免调用sp_sproc_columns。这些地方包括: setXXX()/registerOutParameter()调用,getXXX()取返回结果。

    • 已标记为答案 pengzi 2010年5月6日 3:49
    2010年4月6日 6:11
  • 请问你用的是那一版本的driver


    我是天生我怕谁?
    2010年4月10日 6:54