我在Azure上有一个Sql Server数据库,用于处理传入的EDI文档。基本上,它接收数据,并将其保存到表的一行中。 “ edi_data”列的大小可以高达7 Meg。
我们已经使用了两年左右,没有任何问题。但是,在过去的两天内,insert语句已超过30秒超时,因此引发错误。
此数据库的DTU已从15增加到100。提高DTU确实有助于处理更多的传输,但是今天再次发生此错误。增加之后,最大DTU不会超过35%。
这是由EntityFramework 6生成的插入内容:
(@0 int,@1 int,@2 datetime2(7),@3 nvarchar(max),@4 nvarchar(max),@5
nvarchar(max),@6 nvarchar(max),@7 nvarchar(max),@8 nvarchar(max),@9
nvarchar(max),@10 nvarchar(max),@11 nvarchar(max),@12 nvarchar(max),@13
nvarchar(max),@14 nvarchar(max),@15 nvarchar(max),@16 nvarchar(max),@17
bit,@18 int)INSERT [dbo].[transmission]([transmission_status_id],
[transmission_attempts], [transmission_date], [edi_data], [originator_num],
[recipient_num], [error_message], [encryption_type], [gisb_version],
[receipt_signing_protocol], [receipt_type], [http_request],
[request_headers], [http_response], [response_headers], [edi_type],
[original_file_name], [file_name], [archive_flag], [group_control_code],
[orig_transmission_id], [direction])
VALUES (@0, @1, @2, @3, @4, @5, @6, @7, @8, @9, @10, @11, @12, NULL, @13, @14, @15, @16, @17, NULL, NULL, @18)
除了增加DTU以外,还有其他解决方法吗? (我知道我可以将“命令超时”增加到30秒以上,但如果可能的话,我想解决速度问题。)
答案 0 :(得分:2)
nvarchar(max)
和varbinary(max)
类型用于存储CLOB和BLOB。尽管可以直接保存相对较小的缓冲区或字符串,但使用流API将大量数据复制到服务器要高效得多。
这也可以为客户端节省大量内存,因为它不必一次分配整个7MB字符串,这不可避免地会带来垃圾回收损失。
实体框架不直接提供任何流功能。 ADO.NET,特别是SqlClient提供程序。文档中的SqlClient Streaming Support文章介绍了如何使用流技术将大文件加载或存储到BLOB字段中。
文本类型为NVarChar
的SqlParameter可以接受TextReader作为值而不是字符串。 SqlClient将从读取器读取数据并将其发送到数据库。
针对此表,存储doc示例:
CREATE TABLE [TextStreams] (
[id] INT PRIMARY KEY IDENTITY(1, 1),
[textdata] NVARCHAR(MAX)
)
以下方法会将数据从源流复制到服务器:
private static async Task StreamTextToServer() {
using (SqlConnection conn = new SqlConnection(connectionString)) {
await conn.OpenAsync();
using (SqlCommand cmd = new SqlCommand("INSERT INTO [TextStreams] (textdata) VALUES (@textdata)", conn)) {
using (StreamReader file = File.OpenText("textdata.txt")) {
// Add a parameter which uses the StreamReader we just opened
// Size is set to -1 to indicate "MAX"
cmd.Parameters.Add("@textdata", SqlDbType.NVarChar, -1).Value = file;
// Send the data to the server asynchronously
await cmd.ExecuteNonQueryAsync();
}
}
}
}