SQL 在将 Base64 转换为二进制的视图上执行 reader 超时

SQL timeouts executing reader on view that converts Base64 to binary

我们将文件以 Base64 编码存储在 SQL 服务器 table 中。我们需要将文件作为二进制数据进行流式传输,因此我们查询一个将 Base64 列转换为 varbinary:

的视图
CREATE VIEW [dbo].[FilesView]
AS      
    SELECT
        f.Id,
        CAST(N'' AS XML).value('xs:base64Binary(sql:column("f.FileContents"))', 'varbinary(max)') AS FileContents,
    FROM [Files] f

FileContents 在文件 table 中,定义为 varchar(max).

我们使用 ADO.NET 查询此列并使用 SqlDataReader 流式传输内容:

private async Task<Stream> FileStream(Guid id)
{
    string commandText = "SELECT FileContents FROM FilesView WHERE Id = @id";

    using (SqlCommand cmd = new SqlCommand(commandText, (SqlConnection)context.Database.GetDbConnection()))
    {
        cmd.Parameters.Add(new SqlParameter("@id", id));

        if (cmd.Connection.State != ConnectionState.Open)
        {
            await cmd.Connection.OpenAsync();
        }

        SqlDataReader reader = await cmd.ExecuteReaderAsync(CommandBehavior.SequentialAccess);

        if (await reader.ReadAsync())
        {
            return reader.GetStream(0);
        }
    }

    return null;
}

这对我们来说效果很好,文件下载会立即开始,但是在发货后,我们有少数客户在 cmd.ExecuteReaderAsync 行遇到异常:

Execution Timeout Expired. The timeout period elapsed prior to completion of the operation or the server is not responding.

根据他们的说法,这些文件也不是很大,不到 1 MB。在我们的测试中,我们使用了更大的文件并且没有超时问题。我们让他们将命令超时时间增加到 60 秒或更多,并且大部分时间都得到了纠正,但花了很长时间,问题仍然存在。由于打开 reader 时出现异常,我的假设是 Base64 到二进制转换是导致超时的原因。

为什么只有一些实例? SQL 服务器中是否有特定的 feature/option 我们应该检查或更改可能导致此问题的原因?我不知道他们的数据库服务器的硬件规格,但我想这可能只是转换动力不足的情况?

事实证明,此特定客户端使用的是 SQL Server 2017,但其兼容性级别设置为 SQL Server 2012 (110)。将其移至 130,查询现在 运行 毫秒。