Json 如何用不同的机制替换SQL Server游标
我正在使用SQLServer2008。我必须从两个具有一对多关系的表中创建json。这些表是Json 如何用不同的机制替换SQL Server游标,json,sql-server,Json,Sql Server,我正在使用SQLServer2008。我必须从两个具有一对多关系的表中创建json。这些表是客户和订单 每个客户可能有一个或多个订单。json的构造方法是首先从customer表中获取数据,然后附加他们所购买的所有商品 以下是我的疑问。我还附上了查询的json输出。它工作并创建有效的JSON。问题是它太慢了,因为我使用光标在Customer表中循环。通过使用for xml path,我成功地避免了游标从Orders表中获取数据。因为我必须处理数百万行,所以我必须用其他机制替换光标 DECLARE
客户
和订单
每个客户可能有一个或多个订单。json的构造方法是首先从customer表中获取数据,然后附加他们所购买的所有商品
以下是我的疑问。我还附上了查询的json输出。它工作并创建有效的JSON。问题是它太慢了,因为我使用光标在Customer
表中循环。通过使用for xml path,我成功地避免了游标从Orders
表中获取数据。因为我必须处理数百万行,所以我必须用其他机制替换光标
DECLARE @PaymentType VARCHAR(50),
@Email VARCHAR(100),
@OrderId INT
DECLARE CustomerCursor CURSOR FAST_FORWARD FOR
SELECT TOP 10
PaymentType, Email, OrderId
FROM
CUSTOMER
OPEN CustomerCursor
FETCH NEXT FROM CustomerCursor INTO @PaymentType, @Email, @OrderId
WHILE (@@FETCH_STATUS = 0)
BEGIN
DECLARE @customer VARCHAR(MAX)
DECLARE @order VARCHAR(MAX)
DECLARE @customer_with_order VARCHAR(MAX)
-- construct order json
SET @order = '[' + STUFF((SELECT ',{"orderProductID":' + CAST(orderProductID AS VARCHAR) +
',"productType":"' + ProductType + '"' +
',"productName":"' + ProductName + '"' +
',"categoryName":"' + CategoryName + '"' + '}'
FROM ORDERS
WHERE orderid = @OrderId
FOR XML PAT(''), TYPE).value('.', 'VARCHAR(MAX)'), 1, 1, '') + ']'
-- construct customer json
SET @customer = '{"email":"' + CASE WHEN @Email IS NULL THEN '' ELSE
@Email END + '"'
+ ',"eventName": "ChristmasSale", "dataFields": {'
+ '"orderId":' + CAST(CASE WHEN @OrderId IS NULL THEN 0 ELSE
@OrderId END AS VARCHAR)
+ ',"paymentType":"' + CASE WHEN @PaymentType IS NULL THEN
'' ELSE @PaymentType END + '"'
+ ',"products": '
-- combine these two
SET @customer_with_order = @customer + @order + '}}'
-- insert into CUSTOMER_ORDER_DATA
INSERT INTO CUSTOMER_ORDER_DATA(email, order_id, orders)
VALUES (@Email, @OrderId, @customer_with_order)
FETCH NEXT FROM CustomerCursor INTO @PaymentType, @Email, @OrderId
END
CLOSE CustomerCursor
DEALLOCATE CustomerCursor
我无法测试这一点,但我怀疑您可以将上述内容重写为基于集合的方法,如下所示(因为我无法测试这一点,我无法确定这是否可行,如果不行,您可能需要对其进行一点故障排除):
考虑到OP有500万行,那么对于一个批次来说这可能有点多。将其分为批量(比如10000)可能对整体性能更好。不幸的是,OP仍在使用2008,因此他们无法访问
OFFSET
子句。我无法测试这一点,但我怀疑您可以将上述内容重写为基于集合的方法,如下所示(因为我无法测试这一点,我无法确定这是否可行,如果不行,您可能需要对其进行一点故障排除):
考虑到OP有500万行,那么对于一个批次来说这可能有点多。将其分为批量(比如10000)可能对整体性能更好。不幸的是,OP仍在使用2008,因此他们无法访问
OFFSET
子句。define slow-here——您预计生成100万个json文件需要多快?可能是你的存储速度不够快。我必须处理500万条记录。对于1000个JSON,上述查询耗时5分钟。按照这个速度,需要400小时!将值保留为关系数据并在SQL Server之外创建JSON不是更快吗?嗨,Luis,我在C#中尝试过,它也需要类似的时间,因为它还涉及到循环记录。我不是说一次转换所有内容,只是根据需要转换为JSON。您还向存储中添加了不必要的数据,这最终会给您带来不好的影响。存储的每一行都有超过200字节的冗余数据。所有这些看起来都是糟糕的设计。在这里定义慢——您希望以多快的速度生成100万个json文件?可能是你的存储速度不够快。我必须处理500万条记录。对于1000个JSON,上述查询耗时5分钟。按照这个速度,需要400小时!将值保留为关系数据并在SQL Server之外创建JSON不是更快吗?嗨,Luis,我在C#中尝试过,它也需要类似的时间,因为它还涉及到循环记录。我不是说一次转换所有内容,只是根据需要转换为JSON。您还向存储中添加了不必要的数据,这最终会给您带来不好的影响。存储的每一行都有超过200字节的冗余数据。所有这些看起来都是糟糕的设计。嗨,Larnu,经过一些小的修改,它工作得非常完美。这比使用光标的方法至少快600%。非常感谢。嗨,Larnu,经过一些小的修改,它工作得非常好。这比使用光标的方法至少快600%。非常感谢。
INSERT INTO CUSTOMER_ORDER_DATA(email, order_id, orders)
SELECT C.Email,
C.orderid,
'{"email":"' + CASE WHEN @Email IS NULL THEN '' ELSE
@Email END + '"'
+ ',"eventName": "ChristmasSale", "dataFields": {'
+ '"orderId":' + CAST(CASE WHEN @OrderId IS NULL THEN 0 ELSE
@OrderId END AS varchar)
+ ',"paymentType":"' + CASE WHEN @PaymentType IS NULL THEN
'' ELSE @PaymentType END + '"'
+ ',"products": ' +
('[' + STUFF((
SELECT
',{"orderProductID":' + CAST(orderProductID AS varchar)
+ ',"productType":"' + ProductType + '"'
+ ',"productName":"' + ProductName + '"'
+ ',"categoryName":"' + CategoryName + '"'
+'}'
FROM ORDERS AS O
WHERE O.orderid = C.orderid
FOR XML PATH(''),TYPE).value('.', 'varchar(max)'), 1, 1, '') + ']')
FROM CUSTOMER AS C