Jdbc preparedStatement.setString比硬编码参数长5秒以上
我通过JavaJDBC连接到MicrosoftSQLServer数据库,遇到了一个非常奇怪的问题。每当我在where子句中的查询中使用占位符参数(?),然后执行preparedStatement.setString(..)方法时,我的简单查询运行时间从4800毫秒到5800毫秒不等。当我在查询本身内部硬编码where子句时,运行需要1到36毫秒。这对我来说没有意义,因为我认为使用占位符应该更快 这个表确实有很多行(800万左右),但是我传入的参数只有几个字符,我只传入2个参数,语句总是返回1(或0)行,它返回的数据不是很大。表上的索引没有帮助。为什么会有这么大的时差?5-6秒对于这样的查询来说是一个非常长的时间。where子句中的两列都是字符串类型(varchar(20)),因此数据库端没有隐式类型转换(据我所知) 我尝试了不同版本的sqljdbc4.jar驱动程序,但它也在做同样的事情Jdbc preparedStatement.setString比硬编码参数长5秒以上,jdbc,prepared-statement,Jdbc,Prepared Statement,我通过JavaJDBC连接到MicrosoftSQLServer数据库,遇到了一个非常奇怪的问题。每当我在where子句中的查询中使用占位符参数(?),然后执行preparedStatement.setString(..)方法时,我的简单查询运行时间从4800毫秒到5800毫秒不等。当我在查询本身内部硬编码where子句时,运行需要1到36毫秒。这对我来说没有意义,因为我认为使用占位符应该更快 这个表确实有很多行(800万左右),但是我传入的参数只有几个字符,我只传入2个参数,语句总是返回1(或
package testdbconnection;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
public class Main {
public static void main(String[] args) throws SQLException
{
Connection con = getConnection();
PreparedStatement statement = con.prepareStatement("select col1 from tableName where username = ? and password = ?");
statement.setString(1, "UName");
statement.setString(2, "PWord");
long start = System.currentTimeMillis();
ResultSet rs = statement.executeQuery();
long stop = System.currentTimeMillis();
System.out.println("took: " + (stop - start));
rs.close();
con.close();
}// end main
private static Connection getConnection()
{
Connection connection = null;
try {
// Load the JDBC driver
String driverName = "com.microsoft.sqlserver.jdbc.SQLServerDriver";
Class.forName(driverName);
// Create a connection to the database
String url = "jdbc:sqlserver://DBSERVERNAME;databaseName=DBNAME;";
String username = "dbUname";
String password = "dbPword";
connection = DriverManager.getConnection(url, username, password);
}
catch (ClassNotFoundException e)
{
e.printStackTrace();
} catch (SQLException e)
{
e.printStackTrace();
}
return connection;
}// end getConnection()
}
输出:
运行:
电话:4891
生成成功(总时间:5秒)
现在如果我这样做:
package testdbconnection;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
public class Main {
public static void main(String[] args) throws SQLException
{
Connection con = getConnection();
PreparedStatement statement = con.prepareStatement("select col1 from tableName where username = 'UName' and password = 'PWord'");
long start = System.currentTimeMillis();
ResultSet rs = statement.executeQuery();
long stop = System.currentTimeMillis();
System.out.println("took: " + (stop - start));
rs.close();
con.close();
}// end main
private static Connection getConnection()
{
Connection connection = null;
try {
// Load the JDBC driver
String driverName = "com.microsoft.sqlserver.jdbc.SQLServerDriver";
Class.forName(driverName);
// Create a connection to the database
String url = "jdbc:sqlserver://DBSERVERNAME;databaseName=DBNAME;";
String username = "dbUname";
String password = "dbPword";
connection = DriverManager.getConnection(url, username, password);
}
catch (ClassNotFoundException e)
{
e.printStackTrace();
} catch (SQLException e)
{
e.printStackTrace();
}
return connection;
}// end getConnection()
}
输出:
运行:
日期:32
生成成功(总时间:2秒)一般来说,运行完全硬编码的语句将比等效的参数化语句快。其原因与数据库的执行计划有关。当您从一开始就提供所有信息时,数据库可以执行优化,并针对您提供的确切数据选择更短的路径。当您参数化语句时,它只能执行那些对可能插入的任何值都有帮助的优化
当您需要运行许多类似的查询并希望避免每次准备语句的开销时,参数化语句可能会很有用,但对于大型数据集上的单个查询(如在您的用例中),硬编码查询会更好 在这种情况下,您建议如何缩短时间并仍然使用参数化查询?我不愿意使用硬编码查询,因为where子句中的内容来自用户输入,而不使用参数,这使得应用程序更容易受到sql注入的影响。5-6秒对于这样一个小的查询来说是一个巨大的时间。甚至没有任何连接。在java方面还有什么可以提高性能的方法吗?一种可能的解决方案是使用硬编码查询,前提是您可以轻松地验证输入是否安全(例如,仅使用字母数字和空格),并保留参数化查询以供更可疑的输入使用。当然,只有当你期望的“正常”输入很容易识别时,这才有意义。