SQL Server循环openrowset性能

时间:2016-05-20 08:26:32

标签: sql sql-server json sql-server-2016

我有以下存储过程来遍历每天下载到服务器的数百个不同的JSON文件。

问题是查询需要15分钟才能运行,我需要尽快为大量的JSON文件创建类似的东西,是否有人能够指出我在提高性能方面的正确方向查询?

DECLARE @json VARCHAR(MAX) = ''
DECLARE @Int INT = 1
DECLARE @Union INT = 0
DECLARE @sql NVARCHAR(max)
DECLARE @PageNo INT = 300

WHILE (@Int < @PageNo)
BEGIN
    SET @sql = (
    'SELECT 
        @cnt = value
    FROM 
        OPENROWSET (BULK ''C:\JSON\tickets' + CONVERT(varchar(10), @Int)  + '.json'', SINGLE_CLOB) as j
        CROSS APPLY OPENJSON(BulkColumn)
    WHERE
        [key] = ''tickets''
    ')
EXECUTE sp_executesql @sql, N'@cnt nvarchar(max) OUTPUT', @cnt=@json OUTPUT

IF NOT EXISTS (SELECT * FROM OPENJSON(@json) WITH ([id] int) j JOIN tickets t on t.id = j.id)
BEGIN
    INSERT INTO
        tickets (id, Field1)
    SELECT
        *
    FROM OPENJSON(@json)
         WITH ([id] int, Field1 int) 
END

END

2 个答案:

答案 0 :(得分:0)

看起来循环中的BULK INSERT是瓶颈。通常,BULK INSERT是检索数据的最快方法。无论如何,这里似乎文件的数量是你的问题。

为了加快速度,您需要并行读取JSON文件。您可以首先为所有文件创建完整的动态SQL查询,也可以为某些文件组创建并同时读取。

我建议将Integration Services与脚本组件一起用作并行数据流任务中的源。首先从目标文件夹中读取所有文件,例如将它们拆分为4组,因为每个组都有一个并行运行的循环容器。根据您的执行机器,您可以使用尽可能多的并行流。 Allready 2数据流应该弥补集成服务的开销。

另一种选择是编写CLR (common language runtime) stored procedure并使用C#并行反序列化JSON。

这还取决于机器完成工作。您可能希望有足够的随机存取内存和免费的CPU功率,因此在机器不忙时应考虑进行导入。

答案 1 :(得分:0)

因此,在将数据从大量单个XML文件加载到表中时,我可以成功地使用SQL服务器的FileTable功能,这是一种成功的方法。

它的工作方式是在数据库中设置文件表,然后允许访问在服务器上为上载XML文件的进程创建的FileStream共享。然后将XML文件放入共享中,并立即在数据库中使用,以便使用xPath进行查询。

然后运行一个进程xPath查询会将所需的数据从XML加载到所需的表中,并跟踪已加载的文件,然后在下一个计划出现时,只加载来自最新文件的数据。

计算机上的计划任务将在不再需要时删除文件。

在这里阅读FileTable:

FileTables (SQL Server)

它可用于所有SQL Server版本。