【发布时间】:2016-07-29 07:29:22
【问题描述】:
我的应用程序:我在 Go 中编写了一个脚本,该脚本通过 FTP 获取大量 (>10k) JSON 文件并将内容写入本地 SQL Server 2016 实例中的表。导入一个文件夹后,它会触发一个 T-SQL 过程来处理进一步的数据处理。 总的来说,这个解决方案似乎运作良好。但是,我需要高度的并行操作才能有足够的性能。通常,每个文件有大约 2,000 个条目,我需要在每个文件夹中导入大约 5,000 个文件。 SQL Server 在本地运行,语句的性能不是问题。
执行结构: 通过 FTP 检索文件列表,并将每个文件名交给 Goroutine。 go-routine 获取文件(也通过 FTP),解析它并触发 SQL 插入。在应用程序开始时准备一个简单的插入语句 ("INSERT INTO tbl (val1,val2,val3) SELECT $1,$2,$3"),然后在 Goroutine 中执行 (stmt .Exec(var1,var2,var3)) 为每个条目。 我使用通道变量(make(chan bool,MAXPAR),其中 MAXPAR=10 但应该为 30)控制运行例程的最大数量。
问题:每当我启动超过 ~15 个并行例程(30 个最好)时,我会在片刻后收到以下错误(~1k 个文件)
在 127.0.0.1:1433 建立与 SQL Server 的连接时发生与网络相关或特定于实例的错误。每个套接字地址(协议/网络地址/端口)通常只允许使用一次。
我可以在网上找到这可能表明 TCP/IP 堆栈已耗尽(?),但还没有找到解决我的问题的方法。由于代码的结构,只有 30 条语句(当 MAXPAR 设置为 30 时)会同时执行,所以问题不应该是连接数。据我了解,可能不是并行度,而是每秒执行次数是这里的限制因素。
我的想法:目前,我可以想到三种可能会有所帮助的方案:
- 将 MAXPAR 限制为 10。但是,这会导致性能下降,我不知道该设置最终是否也会出现问题
- 在程序开始时建立更多连接,并随机分配每个 go-routine 一个连接。这会降低执行/连接的数量,但如果每秒的执行总数有问题,我不确定它是否能解决我的问题。
- 使用一种批量语句形式为每个文件发送一个插入语句,而不是每个条目一个。
最后一个选项是目前唯一一个我确信它可以工作的选项。但是,由于我有类似的插入脚本(到目前为止还没有出现问题),我宁愿了解潜在的问题,以及在我去更改所有应用程序之前是否有办法阻止它。
问题:我的问题是,是否有人在出现此问题时有经验(即它是否可预测),以及上述解决方案之一(或其他解决方案)是否可以根据您的经验工作。如果只是一个脚本,我会尝试所有解决方案,但由于还有其他脚本我不确定他们是否会遇到类似问题,我想找到一个我可以合理确定的解决方案这个问题解决了。
系统
- Windows 10 x64
- SQL Server 2016 开发人员版 (x64)
- 转到 1.6
- 库:github.com/denisenkom/go-mssql
谢谢
【问题讨论】:
-
这不只是一些“SQL Server Developer Edition”的特定限制吗?
-
根据微软 (microsoft.com/en-gb/server-cloud/products/sql-server-editions/…) 的说法,开发者版应该具有相同的功能(至少是数据库引擎),除了在生产中使用它的权利。这正是我在这里使用它的原因,因为在我们花钱购买昂贵的许可证之前,我首先想看看服务器是否能够可靠地处理大量数据。
标签: sql-server go sql-server-2016