我有一个java Web应用程序,从表中选择一列(有600万行),需要大量的CPU时间。在查询浏览器中执行此选择(SELECT id FROM mytable WHERE filename ='unique_filename')所花费的时间要少得多。
导致这种情况的原因是什么? 我应该从哪里开始寻找瓶颈?
数据库是MSSQL 2005标准版 Java容器是Tomcat 5.5(带有sqljdbc 1.2)
更多细节:
1.Java代码
ResultSet rs = null;
PreparedStatement stmt = null;
Connection conn = null;
Integer myId=null;
String myVeryUniqueFileName = strFromSomeWhere;
try
{
conn = Database.getConnection();
stmt = conn.prepareStatement("SELECT id FROM mytable WHERE filename = ?");
stmt.setString(1, myVeryUniqueFileName);
rs = stmt.executeQuery();
if (rs.next())
{
myId= new Integer(rs.getInt(1));
} }
if (rs.next())
{
throw new DBException("Duplicate myId: " + myId);
}
return myId;
} catch (Exception e) {
// handle this
}
Database对象使用DriverManager接收连接对象。
2.SQL表有大约30列。
CREATE TABLE [dbo].[calls](
[id] [int] NOT NULL,
...
[filename] [varchar](50) NOT NULL,
...
CONSTRAINT [PK_xxxxxxxxxxxx] PRIMARY KEY CLUSTERED
(
[id] ASC
)WITH (IGNORE_DUP_KEY = OFF) ON [PRIMARY],
CONSTRAINT [UQ_xxxxxxxxxxxx] UNIQUE NONCLUSTERED
(
[filename] ASC
)WITH (IGNORE_DUP_KEY = OFF) ON [PRIMARY]
) ON [PRIMARY]
filename列是唯一的,因此结果集是allways 1或null。
答案 0 :(得分:2)
借助智能开发者的方式,我能够解决这个问题。结果我误用了PreparedStatement(aricle)。
基于此,我将java代码更改为:
ResultSet rs = null;
Statement stmt = null;
Connection conn = null;
Integer myId=null;
String myVeryUniqueFileName = strFromSomeWhere;
try
{
conn = Database.getConnection();
stmt = conn.createStatement()
//
rs = stmt.executeQuery("SELECT id FROM mytable WHERE filename = '"
+ myVeryUniqueFileName + "'");
if (rs.next())
{
myId= new Integer(rs.getInt(1));
}
if (rs.next())
{
throw new DBException("Duplicate myId: " + myId);
}
return myId;
} catch (Exception e) {
// handle this
}
此dababase负载从平均70%下降到13%
答案 1 :(得分:1)
您可以将Java代码发布到执行此查询并检索结果的位置吗?
导致出现的Java代码需要更长时间的可能因素是:
答案 2 :(得分:1)
我不能特别谈到MSSQL 2005,但是在使用绑定变量的预准备语句和嵌入值的等效语句之间的执行计划可能存在差异。
要测试此理论,请删除bind参数,而是将Java中的SQL查询与实际文件名(引号)连接起来。这样你就可以比较苹果和苹果。
此外,它还可用于指示您遇到的CPU时间差异。是几个数量级还是低于100%。
答案 3 :(得分:0)
您描述的症状通常是由错误缓存的查询计划引起的。
重建索引或更新统计信息。
答案 4 :(得分:0)
您正在使用声明,而不是准备好的声明。语句不会被预编译和缓存,因此查询优化器必须每次都进行工作。如果您使用准备好的语句,它将尝试找到执行查询的最佳方式,它将存储它。下次你使用它时,它不会费心去尝试找到一个好的方法来获得你的结果它只是它已经有的执行计划。