我有一个.csv
文件,其中包含6亿行。我需要将其上传到数据库中。它将有3列被分配为主键。
我使用pandas
读取1000行的文件。
在每次块迭代中,我都使用
INSERT INTO db_name.dbo.table_name("col1", "col2", "col3", "col4")
VALUES (?,?,?,?)
cursor.executemany(query, df.values.tolist())
在python中使用pyodbc
的语法可上传1000行数据。
不幸的是,显然存在一些重复的行。遇到重复的行时,上传将停止,并出现来自SQL Server的错误。
问题:我如何上传数据,以便每当遇到重复而不是停止重复时,都将跳过该行并上传其余内容?我在insert into table from another table
或insert into table from variables declared
上发现了一些问题和答案,但是从文件中读取并使用insert into table col_names values()
命令却没有发现任何问题和答案。
基于这些答案,一个想法可能是:
每次大块迭代:
但是,这么大的文件每秒很重要,我一直在寻找效率更高的答案。
我也尝试使用python处理重复项,但是,由于文件太大而无法容纳到内存中,所以我找不到解决方法。
问题2:如果我使用bulk insert
,我将如何跳过重复项?
谢谢
答案 0 :(得分:0)
您可以尝试使用CTE和INSERT ... SELECT ... WHERE NOT EXISTS
。
WITH cte
AS
(
SELECT ? col1,
? col2,
? col3,
? col4
)
INSERT INTO db_name.dbo.table_name
(col1,
col2,
col3,
col4)
SELECT col1,
col2,
col3,
col4
FROM cte
WHERE NOT EXISTS (SELECT *
FROM db_name.dbo.table_name
WHERE table_name.col1 = cte.col1
AND table_name.col2 = cte.col2
AND table_name.col3 = cte.col3
AND table_name.col4 = cte.col4);
如果该列不是主键的一部分,则可能删除一些table_name.col<n> = cte.col<n>
。
答案 1 :(得分:0)
我总是总是首先加载到临时加载表中,该表在这些列上没有任何唯一性或PK约束。这样,您始终可以看到整个文件已加载,这在任何ETL工作中都是非常宝贵的检查,对于源数据的任何其他简单分析也是如此。
然后,使用前面的答案中建议的插入内容,或者,如果您知道目标表为空,则只需
INSERT INTO db_name.dbo.table_name(col1,col2,col3,col4)
SELECT distinct col1,col2,col3,col4 from load_table
答案 2 :(得分:0)
最好的方法是使用临时表并执行 MERGE-INSERT 语句。您可以执行以下操作(未经测试):
CREATE TABLE #MyTempTable (col1 VARCHAR(50), col2, col3...);
INSERT INTO #MyTempTable(col1, col2, col3, col4)
VALUES (?,?,?,?)
CREATE CLUSTERED INDEX ix_tempCol1 ON #MyTempTable (col1);
MERGE INTO db_name.dbo.table_name AS TARGET
USING #MyTempTable AS SOURCE ON TARGET.COL1 = SOURCE.COL1 AND TARGET.COL2 = SOURCE.COL2 ...
WHEN NOT MATCHED THEN
INSERT(col1, col2, col3, col4)
VALUES(source.col1, source.col2, source.col3, source.col4);
您需要为临时表考虑最佳索引,以使 MERGE 更快。使用未匹配时语句,可以根据 ON子句避免重复。
答案 3 :(得分:0)
SQL Server Integration Services提供了一种方法,该方法可以从源中读取数据(通过Dataflow任务),然后使用其排序控件(用于删除重复项的复选框)删除重复项。
https://www.mssqltips.com/sqlservertip/3036/removing-duplicates-rows-with-ssis-sort-transformation/
当然,必须对数据进行排序,并且6000万以上的行不会很快。
如果要使用纯SQL Server,则需要一个临时表(无pk约束)。将数据导入到暂存中之后,您将使用过滤组合PK组合的方式插入目标表。例如,
Insert into dbo.RealTable (KeyCol1, KeyCol2, KeyCol3, Col4)
Select Col1, Col2, Col3, Col4
from dbo.Staging S
where not exists (Select *
from dbo.RealTable RT
where RT.KeyCol1 = S.Col1
AND RT.KeyCol2 = S.Col2
AND RT.KeyCol3 = S.Col3
)
理论上,您还可以使用集合运算符EXCEPT,因为它从两个表中获取不同的值。例如:
INSERT INTO RealTable
SELECT * FROM Staging
EXCEPT
SELECT * FROM RealTable
将从暂存中插入不同的行到RealTable(RealTable中尚不存在)。此方法未考虑在多行上使用不同值的复合PK,因此插入错误将指示将不同的值分配给csv中的同一PK复合键。