Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/video/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java Hibernate SQL In子句使CPU使用率达到100%_Java_Sql Server_Performance_Hibernate_Ejb - Fatal编程技术网

Java Hibernate SQL In子句使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

在我的java应用程序中,我将SQL server和Hibernate3与EJB一起使用。当我尝试使用In子句执行select查询时,DB服务器CPU使用率达到100%。但是,当我尝试在
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
。这些信息已经包含在索引中。不过,请谨慎使用覆盖索引,因为它们:

  • 占用更多空间,特别是像您这样的中型桌子
  • 只有当您的查询仅限于真正包含的列时,才能很好地工作,而在您的情况下,这种情况不太可能持续下去
  • 如何使用SQL Server Management Studio识别此问题? SQLServerManagementStudio中实际上有一个非常好的特性。当您打开执行计划(您应该这样做)时,您将获得有关查询的以下附加信息:

    右键单击该信息并选择“缺少索引详细信息…”以获取与此信息类似的信息:

    /*
    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问题(有那么多行)

    执行查询时,看起来并非从hibernate获得所有记录,而是在代码中将查询执行的所有记录放入集合中。

    要回答“为什么在hibernate中运行缓慢”的问题,您需要查看服务器在运行hibernate代码时使用的实际执行计划,不是从SSMS运行查询时服务器使用的执行计划。问题中包含的执行计划的屏幕截图与运行hibernate代码时得到的实际计划不一样。一旦你有了这个计划,你就可以将它与你从SSMS得到的计划进行比较,这种差异很可能会解释为什么它在一种情况下慢,在另一种情况下快

    作者有一篇非常好的文章,重点介绍了所谓的“参数”
    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