java - Hibernate SQL In 子句使 CPU 使用率达到 100%

标签 java sql-server performance hibernate ejb

在我的 java 应用程序中,我使用 SQL 服务器和带 EJB 的 Hibernate3。当我尝试使用 In 子句执行选择查询 时,数据库服务器 CPU 使用率达到 100%。但是,当我尝试在 SQL management studio 中运行相同的查询时,查询运行时没有任何 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;

有什么问题为什么会这样。如果通过 Management Studio 运行相同的查询,则检索结果时不会出现任何尖峰,并且会在 1 秒内检索到结果。有什么解决办法吗???

编辑1: 我的 hibernate 生成查询是,

select this_.Student_Id as y0_ from student_table this_ where this_.Roll_No in (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?,?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)

编辑2: 我的执行计划 这是在索引 roll_no 之后

CREATE INDEX i_student_roll_no ON student_table (Roll_No) 

My execution plan ,

最佳答案

您从控制台运行的查询很容易缓存,这就是为什么响应是即时的。如果您查看查询,您会看到所有参数都嵌入到查询中,因此查询规划器可以检测到没有变化,并且所有执行将始终转到相同的计划和相同的缓存结果。

您使用 Hibernate 运行的查询,即使它是 native 查询,它也使用 PreparedStatement 并且参数在查询执行时绑定(bind)并且 to quote one of the best author on indexing :

What has that to do with bind parameters?

The shared execution plan caches of DB2, Oracle and SQL Server use a hash value of the literal SQL string as key to the cache. Cached plans are not found if the SQL contains literal values that vary with each execution.

Place holders (bind parameters) unify the statement so that the SQL string is identical when executed with different values—thus, increasing the cache-hit rate.

为了解决这个问题,您需要在 (Roll_No, Student_Id) 列上添加索引,以便查询成为仅索引扫描。

SQL Server 默认为 cluster indexes ,这将您限制为每个表一个聚簇索引,因此您可能需要 turn this table into a heap table instead并专注于仅索引扫描。

关于java - Hibernate SQL In 子句使 CPU 使用率达到 100%,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29814090/

相关文章:

java - 框架.添加(游戏);不工作

java - 帮助 Project Euler #200?

sql - 一对多关系不存在的地方

sql-server - 由 CROSS APPLY 触发时的顺序 SQL 插入

performance - 编程语言的速度对 Web 应用程序重要吗?

java - 无法将 List<Object[]> 值分配给特定类型的 ArrayList

java - 安卓 : SMSManager - Attempt to get length of null array

sql - MSSQL : Disable triggers for one INSERT

sql - 当连接更改时,MySQL SELECT 将永远运行

performance - Node.js 比 Apache 慢