Java Hibernate SQL In子句使CPU使用率达到100%
在我的java应用程序中,我将SQL server和Hibernate3与EJB一起使用。当我尝试使用In子句执行select查询时,DB服务器CPU使用率达到100%。但是,当我尝试在Java Hibernate SQL In子句使CPU使用率达到100%,java,sql-server,performance,hibernate,ejb,Java,Sql Server,Performance,Hibernate,Ejb,在我的java应用程序中,我将SQL server和Hibernate3与EJB一起使用。当我尝试使用In子句执行select查询时,DB服务器CPU使用率达到100%。但是,当我尝试在sqlmanagementstudio中运行相同的查询时,查询运行时没有任何CPU峰值。应用服务器和数据库服务器是两台不同的机器。我的表具有以下架构 CREATE TABLE student_table ( Student_Id BIGINT NOT NULL IDENTITY , Cla
sqlmanagementstudio
中运行相同的查询时,查询运行时没有任何CPU峰值。应用服务器和数据库服务器是两台不同的机器。我的表具有以下架构
CREATE TABLE student_table (
Student_Id BIGINT NOT NULL IDENTITY
, Class_Id BIGINT NOT NULL
, Student_First_Name VARCHAR(100) NOT NULL
, Student_Last_Name VARCHAR(100)
, Roll_No VARCHAR(100) NOT NULL
, PRIMARY KEY (Student_Id)
, CONSTRAINT UK_StudentUnique_1 UNIQUE (Class_Id, Roll_No)
);
该表包含约1000k条记录。我的问题是
select Student_Id from student_table where Roll_No in ('A101','A102','A103',.....'A250');
In子句包含250个值,当我尝试在SQL management studio中运行上述查询时,结果将在1秒内检索,并且不会出现任何CPU峰值。但当我试图通过hibernate运行相同的查询时,CPU峰值达到100%并持续60秒左右,结果在60秒左右被检索。hibernate查询是
Criteria studentCriteria = session.createCriteria(StudentTO.class);
studentCriteria.add(Restrictions.in("rollNo", rollNoLists)); //rollNoLists is an Arraylist contains 250 Strings
studentCriteria.setProjection(Projections.projectionList().add(Projections.property("studentId")));
List<Long> studentIds = new ArrayList<Long>();
List<Long> results = (ArrayList<Long>) studentCriteria.list();
if (results != null && results.size() > 0) {
studentIds.addAll(results);
}
return studentIds;
select this_.Student_Id as y0_ from student_table this_ where this_.Roll_No in (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?,?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
Edit2:
我的执行计划
这是在索引卷号之后
CREATE INDEX i_student_roll_no ON student_table (Roll_No)
,在hibernate级别检查查询中使用的所有字段的数据类型,并确保它与表定义匹配。hibernate等框架使用Unicode支持的数据类型(例如nvarchar)。尝试在任意一侧更改数据类型 或者,您可以在连接字符串中添加名为SendStringParametersUnicode的参数。它将强制hibernate使用varchar而不是nvarchar
试试看,让我们知道 从控制台运行的查询很容易缓存,这就是为什么响应是即时的。如果查看查询,您将看到所有参数都嵌入到查询中,因此查询计划器可以检测到没有变化,并且所有执行都将始终转到相同的计划和相同的缓存结果 使用Hibernate运行的查询,即使是本机查询,也会使用
PreparedStatement
,并且在查询执行时绑定参数,并且:
这与绑定参数有什么关系
DB2、Oracle和SQL Server的共享执行计划缓存使用文本SQL字符串的哈希值作为缓存的键。缓存
如果SQL包含随时间变化的文本值,则找不到计划
每次执行
占位符(bind参数)统一了语句,使得SQL字符串在使用不同的值执行时是相同的,因此,
提高缓存命中率
要解决此问题,需要在(Roll\u No
,Student\u Id
)列上添加索引,以便查询成为仅索引扫描
SQL Server默认设置为,这将每个表限制为一个聚集索引,因此您可能希望只进行索引扫描。您可能认为,由于慢速查询需要60秒,“快速”查询需要1秒,因此实际上是快速的。事实并非如此。这种执行速度的差异使您无法理解此处的实际问题 另一个问题(可能不是实际问题) 如果您在
Roll\u No
上有索引,那么您正在运行的非常简单的查询类型应该在不到一毫秒的时间内返回结果,无论您使用的是绑定变量还是内联值
我只是假设除了从表中的约束生成的索引之外,没有任何索引。因此,您应该在Roll\u No
上添加一个简单索引:
在student_表(roll_no)上创建索引i_student_roll_no;
或者,您可以在上述索引中添加一列,使其成为此查询的“覆盖索引”()
在student_表上创建索引i_student_roll_No 2(roll_No,student_Id);
这将使这个特定的查询更快,因为执行计划不需要再次点击磁盘来从表中获取Student\u Id
。这些信息已经包含在索引中。不过,请谨慎使用覆盖索引,因为它们:
/*
Missing Index Details from SQLQuery1.sql -
LUKAS-ENVY\SQLEXPRESS.test (LUKAS-ENVY\Lukas (52))
The Query Processor estimates that implementing the
following index could improve the query cost by 87.5035%.
*/
/*
USE [test]
GO
CREATE NONCLUSTERED INDEX [<Name of Missing Index, sysname,>]
ON [dbo].[student_table] ([Roll_No])
INCLUDE ([Student_Id])
GO
*/
/*
SQLQuery1.sql中缺少索引详细信息-
LUKAS-ENVY\SQLEXPRESS.test(LUKAS-ENVY\LUKAS(52))
查询处理器估计实现
以下指标可以将查询成本提高87.5035%。
*/
/*
使用[测试]
去
创建非聚集索引[]
在[dbo].[student_table]([Roll_No])
包括([学生Id])
去
*/
为什么SQL Server Mgmt Studio和Hibernate之间存在差异?
你原来的问题还没有得到回答。也许,附加索引修复了它,但也许您没有提供所有信息。你可以:
- 绑定变量窥视问题
- Hibernate中的N+1问题(有那么多行)
CREATE TABLE RollNumbers (
Roll_No VARCHAR(100) NOT NULL
,PRIMARY KEY (Roll_No)
);
SELECT Student_Id
FROM
student_table
INNER JOIN RollNumbers ON RollNumbers.Roll_No = student_table.Roll_No