首页 > 解决方案 > Npgsql 在高负载场景下使用 Redshift 的低数据检索性能

问题描述

应用程序使用 Npgsql 4.1.5 和 .NET 框架 4.6.2。此应用程序对 Redshift DB具有只读访问模式。

应用程序托管在 IIS 7.5 windows server 2016 上,位于私有云中的 16 个 CPU 内核 256 GB RAM 实例上,通过 VPC 访问 AWS Redshift。

与 Redshift 查询执行统计数据相比,主要问题是应用程序端的数据检索时间较长。在高负载情况下,每分钟 3K 查询。在此期间,使用了 100 个 DB 连接,CPU 利用率为 80-100%。每个查询通常检索 1K-50K 行,最多包含 10 个字段。

Redshift 查询总执行时间(按百分位),秒

p50  | p80 |  p90 | p99
0,16 | 0,3 | 0,59 | 5,31

NpgSQL 命令执行时间(按百分位),秒

p50  | p80  | p90  | p99
1,23 | 4,92 | 9,81 | 18,13

NpgSQL 命令执行时间是通过文档中描述的记录器实现来收集。“开始用户操作”和“最终用户操作”之间的时间。

以下是连接字符串演示的最佳结果:

Minimum Pool Size=5; Maximum Pool Size=100; Connection Idle Lifetime=300; Command Timeout=0; Timeout=120; Keepalive = disabled; Max Auto Prepare = 5000; Auto Prepare Min Usages=5; Enlist=false; No Reset On Close = true

典型的访问模式:

using (DbConnection connection = NpgsqlFactory.Instance.CreateConnection())
{
    connection.ConnectionString = connectionString;
    if (connection.State != ConnectionState.Open)
        connection.Open();

    using (DbCommand command = connection.CreateCommand())
    {
        command.CommandText = query;
        using (var dataReader = command.ExecuteReader())
        {
            while (dataReader.Read())
            {
                object[] values = new object[dataReader.FieldCount];
                for (int i = 0; i < dataReader.FieldCount; i++)
                {
                    values[i] = dataReader.GetFieldValue<object>(i);
                }
            }
        }
    }
}

感谢有关如何针对这种情况改进 npgsql 性能的任何建议。

UPD: 经过API profiling可以确认API端延迟的实际原因是网络读取操作。通常从套接字读取查询结果需要 50-200 毫秒,但在负载下,它会达到 3-15 秒的峰值。

从网络流中读取发生在这里: https ://github.com/npgsql/npgsql/blob/main/src/Npgsql/NpgsqlReadBuffer.cs line 179 buffer.Underlying.Read(...)

标签: .netperformanceamazon-redshiftnpgsql

解决方案


推荐阅读