繁体   English   中英

针对 Hyper-V VM 中运行的 SQL Server 诊断慢速 JDBC 选择语句

[英]Diagnose slow JDBC select statements against SQL Server running in a Hyper-V VM

我们刚刚构建了一个新的 Hyper-V 虚拟机来托管 Java 应用程序和 Microsoft SQL Server。 从 Java JDBC 应用程序运行 SQL 选择查询时,我们遇到了来自数据库的极其缓慢的响应。 从 SQL Server Management Studio 运行时,相同的查询会快速执行。

我们在裸机和 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:9 到 36 秒内处理 45k 行,具体取决于 RAM、CPU 等
  • Java应用:4小时以上

Hyper-V 虚拟机

  • Windows Server 2019 主机
  • Hyper-V 配置 9,第 2 代

app_table 表只有两列。

create table app_table (
  app_id [numeric](18,0) not null,
  col_2 [varchar] (75)
)

app_view 视图也很简单。

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 Profiler 报告的内容。 SSMS 客户端在 23 秒内执行视图查询。 JDBC 客户端用了 100 多秒的时间,查询在完成之前被取消。

对于 SSMS 客户端

SQL:BatchStarting "select * from app_view where ..." 2020-02-26 20:04:22
<一堆重复的东西>
审核登录/注销
RPC:已完成“exec sp_reset_connection”
BatchStarting/Completed "SET TRANSACTION ISOLATION LEVEL READ..."
</ 结束一堆重复的东西 > **SQL:BatchCompleted "select * from app_view where ..." 2020-02-26 20:04:45

对于 JDBC 客户端 (SQuirreL)

SQL:BatchStarting "select * from app_view where ..." 2020-02-26 19:55:39
<一堆重复的东西>
审核登录/注销
RPC:已完成“exec sp_reset_connection”
BatchStarting/Completed "SET TRANSACTION ISOLATION LEVEL READ..."
</结束一堆重复的东西>
查询在 19:57:26 取消

编辑 2:更多 SQL Profiler 结果

我在 SSMS 和 JDBC 客户端中分析了更简单的查询,“从 app_table a 中选择前 5000 个 a.app_id”。 令人惊讶的是,两者都执行得很快,不到 1 秒。

对于 SSMS 客户端

SQL:BatchStarting "top 5000 a.app_id from app_table a" 2020-02-27 10:27:55.740
SQL:BatchCompleted "来自 app_table a 的前 5000 个 a.app_id" 2020-02-27 10:27:55.810

对于 JDBC 客户端 (SQuirreL)

SQL:BatchStarting "top 5000 a.app_id from app_table a" 2020-02-27 10:25:45.063
SQL:BatchCompleted "来自 app_table a 的前 5000 个 a.app_id" 2020-02-27 10:25:45.843

首先,让我们看看问题实际上是 SQL Server、应用程序还是其他问题。 打开 SQL Profiler 并开始跟踪。

在跟踪运行的情况下,执行以下查询:

  • SELECT TOP 5000 a.app_id FROM dbo.app_table a; (运行这个 SSMS)
  • SELECT TOP 5000 a.app_id FROM dbo.app_table a; (在您的应用程序/JDBC 客户端中运行此程序)

(为了彻底,您可以针对您的观点重复上面的SELECT语句。)

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

好的,所以我们得到了这些结果。

编辑:

简短的回答这个问题:客户端不应该的问题那么多(即:不应该有SSMS与.NET与JDBC等之间的差异是很大的),至于的Hyper-V对于裸-metal,裸机获胜(假设您的磁盘已虚拟化),原因显而易见。 您可以在 VM 中使用 DiskSpd ( https://aka.ms/diskspd ) 与类似规范的裸机环境运行一些 I/O 测试来证明这一点。

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

  1. 刷新视图(如前所述)
  2. 尝试一个简单的 SELECT TOP 5000 * FROM dbo.app_view (来自两个客户端) - 没有任何 WHERE 子句 - 比较结果。
  3. 在 SSMS 中检查底层表上的索引碎片(右键单击表下的索引“文件夹”,单击“全部重建”,查看对话框中的数字。)甚至 PK 索引也可能变得碎片化,这会导致性能下降变得不稳定。

  4. 尝试不同版本的原始查询,例如:

    SELECT * FROM dbo.app_view 其中 app_id % 1000 = 0

(没有 SELECT ...WHERE IN ... )

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM