Java 针对在Hyper-V VM中运行的SQL Server诊断慢速JDBC select语句

Java 针对在Hyper-V VM中运行的SQL Server诊断慢速JDBC select语句,java,sql-server,jdbc,hyper-v,Java,Sql Server,Jdbc,Hyper V,我们刚刚构建了一个新的Hyper-V虚拟机来承载Java应用程序和Microsoft SQL Server。当从Java JDBC应用程序运行SQL select查询时,数据库的响应速度非常慢。从SQLServerManagementStudio运行时,同样的查询会快速执行 我们在裸机和VMware虚拟机上运行了相同的Java应用程序和SQL Server数据库,没有任何性能问题 我们的问题: 其他开发人员是否在Hyper-V虚拟机中遇到过类似的性能问题 我们如何诊断导致JDBC应用程序性能瓶

我们刚刚构建了一个新的Hyper-V虚拟机来承载Java应用程序和Microsoft SQL Server。当从Java JDBC应用程序运行SQL select查询时,数据库的响应速度非常慢。从SQLServerManagementStudio运行时,同样的查询会快速执行

我们在裸机和VMware虚拟机上运行了相同的Java应用程序和SQL Server数据库,没有任何性能问题

我们的问题:

  • 其他开发人员是否在Hyper-V虚拟机中遇到过类似的性能问题
  • 我们如何诊断导致JDBC应用程序性能瓶颈的原因
查询示例:

select * from view1 where app_id in (
    select app_id from app_table where app_id % 1000 = 0)
order by app_id
响应时间:

  • SQL Server:根据RAM、CPU等的不同,在9到36秒内完成45k行
  • Java应用程序:超过4小时
Hyper-V虚拟机

  • Windows Server 2019主机
  • Hyper-V配置9,第2代
app_表只有两列

create table app_table (
  app_id [numeric](18,0) not null,
  col_2 [varchar] (75)
)
app_视图也很简单

create view app_view as select app_id from app_table
我们尝试了Java应用程序、JDBC驱动程序和SQL Server的各种组合

应用程序:

  • 我们的定制Java应用程序
  • SQuirreL客户端(4.0.0)
JDBC驱动程序:

  • sqljdbc4
  • sqljdbc_8.2.0.jre
SQL Server版本:

  • SQL Server 2017
  • SQL Server 2019
Java版本:8_241

编辑:SQL探查器结果 我不确定报告SQL分析结果的最佳方法,所以我只总结一下SQL分析器报告的内容。SSMS客户端在23秒内执行视图查询。JDBC客户端花了100多秒才在完成之前取消查询

对于SSMS客户端 SQL:BatchStarting“从应用程序视图中选择*,其中…”2020-02-26 20:04:22

审核登录/注销
RPC:已完成“执行sp重置连接”
BatchStarting/Completed“设置事务隔离级别读取…”
**SQL:BatchCompleted“从应用程序视图中选择*,其中…”2020-02-26 20:04:45

对于JDBC客户端(SQuirreL) SQL:BatchStarting“从应用程序视图中选择*,其中…”2020-02-26 19:55:39

审核登录/注销
RPC:已完成“执行sp重置连接”
BatchStarting/Completed“设置事务隔离级别读取…”

查询于19:57:26取消

编辑2:更多SQL探查器结果 我在SSMS和JDBC客户机中分析了更简单的查询“从app_表a中选择top 5000 a.app_id”。令人惊讶的是,这两种方法都能在不到1秒的时间内快速执行

对于SSMS客户端 SQL:BatchStarting“应用程序表a中的前5000个应用程序id”2020-02-27 10:27:55.740
SQL:BatchCompleted“应用程序表a中的前5000个应用程序id”2020-02-27 10:27:55.810

对于JDBC客户端(SQuirreL) SQL:BatchStarting“应用程序表a中的前5000个应用程序id”2020-02-27 10:25:45.063

SQL:BatchCompleted“app_表a中的top 5000 a.app_id”2020-02-27 10:25:45.843

首先,让我们看看问题是否确实是SQL Server、应用程序或其他问题。 打开SQL探查器并启动跟踪

在跟踪运行时,执行以下查询:

  • 从dbo.app_表a中选择TOP 5000 a.app_id(运行此SSMS)
  • 从dbo.app_表a中选择TOP 5000 a.app_id(在应用程序/JDBC客户端中运行此代码)
(为了更彻底,您可以针对视图重复上面的
SELECT
语句。)


停止跟踪并记下各个应用程序的执行时间(持续时间)。

好的,因此我们得到了这些结果

编辑:

这个问题的简短回答是:客户端不应该对Hyper-V与裸机、裸机赢(假设您的磁盘是虚拟化的)有太大影响(即:SSM与.Net与JDBC之间不应该有太大的差异),原因显而易见。您可以在VM中运行一些I/O测试来证明这一点,而不是在类似规范的裸机环境中使用DiskSpd()

然而-我还不相信这两个因素都是问题所在。根据您的跟踪结果,两个客户机在基本表上都表现良好。这两个客户端在视图中的表现都相对较差(Java客户端比SSMS差)。因此,我仍然建议,至少:

  • 刷新视图(如前所述)
  • 尝试从dbo.app_视图(从两个客户端)简单地选择TOP 5000*——不带任何WHERE子句——比较结果
  • 检查SSMS中基础表上的索引碎片(右键单击表下的索引“文件夹”,单击“全部重建”,查看对话框中的数字)。甚至PK索引也可能碎片化,这可能导致性能不稳定

  • 尝试原始查询的其他版本,例如:

    挑选* 从dbo.app_视图 其中应用程序id%1000=0

  • (不带选择…,其中在…)


    最后,实际视图的输出中有多少列?(如果视图很宽,则会由于网络流量以及数据的客户端呈现而对客户端性能产生负面影响。)

    您真的想知道“其他开发人员是否在Hyper-V虚拟机中看到过类似的性能问题?”你真的只对如何修复它感兴趣吗?谢谢你的建议。我已经编辑了我的问题,以包含一些SQL分析器结果。针对Shane建议的更简单的“TOP 5000”查询发布了更多SQL分析器结果。Shane--该表在app_id上已经有一个主键,但我没有在DDL中显示它。我知道表需要主键,索引可以改进