SQL服务器如何快速保存15000条记录?

How to save 15,000 records quickly in SQL Server?

我在 SQL 服务器中有一个 table 如下所示:

我有一个 API 每 10 秒接收 15,000 条记录以保存在上面的 table 中。如果 userid 存在更新该行,如果不存在用户标识插入记录。我使用下面的代码用pyodbc写入每个用户的记录(在python)这意味着我运行下面的代码15,000次:

update Mytable 
set buy = ?, model = ?, price = ?, color = ?, number = ?,
    balance = ?, time = ?, type = ?, 
where userid = ?

if @@ROWCOUNT = 0
    insert into Mytable (userid, buy, model, price, color, 
                         number, balance, time, type)
    values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)

以上代码工作正常,但 15,000 条记录需要 700 秒。我只有这个 API,我没有关于用户数量和...

的其他信息

如何在不到 7 秒的时间内保存 15,000 条记录?

How can I save 15,000 records in less than seven seconds?

最重要的事情(按重要性排序)是:

  1. 不要将 15,000 个单独的批次或 RPC 发送到 SQL 服务器

  2. 不要 运行 15,000 个单独的交易

  1. 不要 运行 15,000 个单独的 DML 语句。

从 Python 执行此操作的最简单方法是将数据作为 JSON 文档发送,并 insert/update 使用批处理 update/insert 或合并发送数据。

您可以发送全部 15,000 个,也可以分成几批发送。参见例如 Trying to insert pandas dataframe to temporary table

在服务器上获得数据后,您可以使用 TSQL 的 MERGE,或者对整个批处理使用单个 UPDATE 和单个 INSERT 语句。

感谢@David Browne 和 This tutorial 在 SQL 服务器中使用 OPENJSON。 我使用 OPENJSON 并在 1 秒内使用以下代码(在 pyodbc 中)写入 15000 行,然后使用 1 个查询删除重复的旧记录。

写入 1500 行:

import pyodbc 
conn = pyodbc.connect('Driver={SQL Server};'
                      'Server=server_name;'
                      'Database=database_name;'
                      'Trusted_Connection=yes;')

cursor = conn.cursor()
 SqlSave=   DECLARE @json NVARCHAR(max) = ' [ 
          
                { "userid" : 14F2G34, "buyV":"pen" ,"modelM" : "Bic", "color" : "red","numberB" : 4000,"balanceVal" : 750,"timeBuy" : 1631303488,"type":"simple" },
                { "userid" : 14F2G35, "buyV":"pen" ,"modelM" : "blueBic", "color" : "blue","numberB" : 1000,"balanceVal" : 150,"timeBuy" : 1631303488,"type":"coly" },
                { "userid" : 14F2G36, "buyV":"pen" ,"modelM" : "oli", "color" : "yellow","numberB" : 6000,"balanceVal" : 200,"timeBuy" : 1631303488,"type":"ni" },
            
      ...
    
    
        ]';
    
    INSERT INTO Mytable 
    SELECT * 
    FROM OPENJSON(@json, '$')
    WITH  (
            useruserid      int   '$.userid',  
            buy   varchar(60)     '$.buyV', 
            model   varchar(60)     '$.modelM', 
            color   varchar(60)     '$.color', 
            number   varchar(60)     '$.numberB', 
            balance   varchar(60)     '$.balanceVal', 
            time   varchar(60)     '$.timeBuy', 
            type   varchar(60)     '$.type', 
            
            
         
        );
cursor.execute(SqlSave)
cursor.commit()

注意:如果您上面的字符串长度超过 4000,请使用 NVARCHAR(max)

为了更新存在的行,我删除了旧行,我有自动增量的 ID 列,我删除了 userid 列的所有重复行,但具有最大 ID 的重复行除外,代码如下:

delete FROM mytable
WHERE ID NOT IN
(   SELECT max(ID)
FROM mytable
GROUP BY userid
)