C# .NET 6 - 简单的 SQL 查询读取单个(大)记录,当运行时是 K8S pod 时,需要很长时间,在 IIS 中运行时是即时的

C# .NET 6 - simple SQL query to read one single (large) record takes forever when run is K8S pod, instantaneous when run in IIS

提问人:Cristiano Ghersi 提问时间:8/18/2023 最后编辑:halferCristiano Ghersi 更新时间:9/11/2023 访问量:333

问:

我在SQL Server中有一个简单的表:

CREATE TABLE [dbo].[MyTable]
(
    [Ticket] [uniqueidentifier] NOT NULL,
    [UserID] [int] NOT NULL,
    [Progress] [int] NOT NULL,
    [Created] [datetime2](7) NOT NULL,
    [KeepRes] [bit] NOT NULL,
    [Result] [nvarchar](max) NULL,
    [ResultFetched] [datetime2](7) NULL,
    [CorrelationID] [varchar](100) NULL,

    CONSTRAINT [PK_MyTable] 
        PRIMARY KEY CLUSTERED ([Ticket] ASC)
                    WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, 
                          IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, 
                          ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
)

请注意,此表的行可能有一个相当大的列(300 MB 左右)。
我从我的应用程序中查询此表。Net6/C# 使用带有主键的简单键。
Resultselect

我使用 Entity Framework Core:

public void QueryTable(Guid ticket)
{
    using (MyDBContext db = new MyDBContext)
    {
        var res = db.MyTable.Find(ticket);
        Console.Write("Res found:" + (res != null));
    }
}

此代码是我的应用程序的一部分,部署在两个环境中:

  1. 在 Windows Server 2014 下运行的 IIS
  2. 一个 K8S 吊舱

这两个环境都指向同一个数据库实例,即 SQL Server 2014。

现在是有趣的部分:

当要检索的记录具有大于 500KB 的列时,该语句在环境 #1 中运行时不到一秒,在环境 #2 中运行时花费一分钟以上。Resultdb.MyTable.Find(ticket);

我执行的另一个测试是,如果检索到的记录的列小于 500KB(大约 10KB 或更少),则查询在两种环境中花费的时间相当(不到一秒)。Result

为什么两个环境之间存在这种性能差异,仅适用于检索到大量记录的特定查询?

环境网络化

有一个金属服务器托管所有这些环境。金属服务器操作系统是 Windows Server 2012 Data Center R2。知识产权 .金属服务器还运行 SQL Server DB。10.0.1.1

IIS在VM上运行(假设使用IP)。此 VM 使用 VMWare Workstation 15 Player 在金属服务器上运行。VM OS 是 Windows Server 2016 Datacenter。10.0.1.2

K8S 环境使用 VMWare Workstation 15 Player 部署在金属服务器上运行的 3 个虚拟机上。这 3 个 VM 的操作系统是 Linux Ubuntu Server 20.04。

一个 VM 是主节点。其他 2 个 VM 是运行 Pod 的工作节点。VM 的 IP 是 (master) 和 (workers)。10.0.1.1010.0.1.1110.0.1.12

现在,K8S 有一个内部 IP 分配的内部机制,它将其他内部地址(如 192.168.1.X)提供给不同的 pod(不确定这是否与此对话相关......无论如何,在我们的连接字符串中,我们使用地址(运行 SQL Server 的金属服务器)来引用 SQL Server。10.0.1.1

附加实验 1

我们在测试中添加了第三个环境,即另一个 K8S 集群,该应用版本在完全相同的 Pod 配置上运行(在集群上部署资源的相同 YAML)。

注意:但是,在这种情况下,数据库的实例是不同的:它具有完全相同的模式、资源、DBMS 版本、网络配置等,只是不同的实例。

查询的结果与在 IIS 上运行的环境 #1 相当。

附加实验 2

我们尝试使用独立的命令行 SQL 客户端 (Python) 执行相同的查询。

    sudo apt install python3-pip
    pip install mssql-cli
    python3.8 -m mssqlcli.main -S 10.0.1.1 -U <username> -d mydb -P <mypsw>

如果我们从工作节点(即 K8S pod 外部)的命令行执行这些行,查询速度很快,只需不到一秒钟。如果我们将这些行作为 K8S pod 的一部分执行,则还需要 1 分钟左右的时间。

因此,最重要的是,我们与 python 客户端与 EF Core 的结果相当,目前罪魁祸首似乎是 pod(网络)。我是否正确阅读了这些结果?

C# SQL-Server Kubernetes 实体框架核心 net-6.0

评论

2赞 Guru Stron 8/18/2023
k8s 的结果是否一致?即,如果多次运行端点。
1赞 David Browne - Microsoft 8/18/2023
比较两个环境的会话等待统计信息。learn.microsoft.com/en-us/sql/relational-databases/......
1赞 Cristiano Ghersi 8/18/2023
@GuruStron是的,我们进行了几次测试。非常一致且可确定地复制。
2赞 siggemannen 8/18/2023
我记得 EF 在大列和异步获取方面遇到了问题,也许这就是问题所在
4赞 AlwaysLearning 8/18/2023
k8s pod 是否与 IIS 服务器和 SQL Server 位于同一局域网上?延迟材料。SQL Server 使用的 TDS 客户端-服务器协议是 30+ 年前为低延迟 LAN 环境编写的,并且非常健谈,在开放的 Internet 上表现得很糟糕。更糟糕的是,当通过任何类型的 VPN (例如从 AWS/GCP 服务传回本地实例)进行隧道传输时。

答: 暂无答案