Sql server 如何将大型Spark数据帧(1.2 GB 14M行)写入MSSQL服务器tbl?我目前的解决方案大约需要10个小时
问题: 1.2 GB(1400万条记录)存储在apache spark数据帧中。计算耗时不到1分钟,但写入MSSQL服务器表(无索引)的时间超过10小时硬件:(1-VM 8-VCPU,64 GB内存,SSD)。问题:以下几点尝试都没有成功,你有什么好的想法、建议或者简单的建议可以帮助你吗?谢谢Sql server 如何将大型Spark数据帧(1.2 GB 14M行)写入MSSQL服务器tbl?我目前的解决方案大约需要10个小时,sql-server,apache-spark,apache-spark-sql,azure-databricks,sql-server-2019,Sql Server,Apache Spark,Apache Spark Sql,Azure Databricks,Sql Server 2019,问题: 1.2 GB(1400万条记录)存储在apache spark数据帧中。计算耗时不到1分钟,但写入MSSQL服务器表(无索引)的时间超过10小时硬件:(1-VM 8-VCPU,64 GB内存,SSD)。问题:以下几点尝试都没有成功,你有什么好的想法、建议或者简单的建议可以帮助你吗?谢谢 def FUNC_A1(df): start = time.time() jdbc_url = f"jdbc:sqlserver://{config.get('mydb',
def FUNC_A1(df):
start = time.time()
jdbc_url = f"jdbc:sqlserver://{config.get('mydb',
'host')}:1434;database={config.get('mydb', 'database')}"
df.select("F1", "F2", "F3", "F4", "F5", "F6", "F7", "F8", "F9")\
.write.format("jdbc").mode("overwrite") \
.option("driver", "com.microsoft.sqlserver.jdbc.SQLServerDriver")\
.option("url", jdbc_url) \
.option("dbtable", "dbo.tblAFS") \
.option("user", config.get('mydb', 'username'))\
.option("password", config.get('mydb', 'password'))\
.save()
前面的代码创建了表,但在尝试插入记录时失败,并生成以下错误消息
选项#1(此代码需要9到10个小时才能完成,它正在将实际结果(数据帧)写入表中
选项2花费的时间与选项1相同_ 已经考虑了以下想法,但尚未在显著缩短处理时间的情况下实施。
- 在这种情况下不应使用rdd.collect(),因为它将收集所有 数据作为一个数组存储在驱动程序中,这是获取数据的最简单方法 记忆
- 还不应将rdd.coalesce(1).saveAsTextFile()用作 上游阶段的并行性将丢失,无法在一个平台上执行 单节点,从中存储数据
- coalesce(1,shuffle=true).saveAsTextFile()是最简单的 选项,因为它将保持上游任务的并行处理和 然后只对一个节点执行洗牌 (rdd.repartition(1).saveAsTextFile()是一个确切的同义词)
- 下面提供的rdd.saveAsSingleTextFile()还允许 使用特定名称将rdd存储在单个文件中,同时保留 coalesce(1,shuffle)的并行性= true)。保存ASTEXTFILE()
有两种方法。首先,删除索引、主键和外键,使用spark作业在该表中插入日期。作业完成后,重新创建反索引、主键和外键 或者,您可以创建一个新表,比如说,表temp与原始表具有相同的结构,但没有任何约束。在表temp中插入数据,并使用表temp更新原始表
使用第一种方法,几天前我在40分钟内插入了一个Oracle DB 500-800百万行。有两种方法。首先,删除索引、主键和外键,使用spark作业在该表中插入日期。作业完成后,重新创建反索引、主键和外键 或者,您可以创建一个新表,比如说,表temp与原始表具有相同的结构,但没有任何约束。在表temp中插入数据,并使用表temp更新原始表
使用第一种方法,几天前,我在40分钟内插入了一个Oracle DB 500-800百万行。您声明的数字相当于大约每秒插入389行,这太低了。如果您在虚拟机上,可能您的邻居吵闹?SQL Server是否在主机上设置了内存保留?它应该……您声明的数字是相当于大约每秒插入389行,这太低了。如果您在虚拟机上,可能有吵闹的邻居?SQL Server是否在主机上设置了内存保留?它应该……不要出于明显的原因删除PK或FK(另外,您可能会将PK与群集键混淆)这取决于DB中的目标表是空表还是已经包含数据。如果目标表已经包含日期,正确的方法是使用临时表。在SQL数据库中插入数据不受群集键的影响。它受Spark executors建立的连接数、该表使用的约束数的影响根据批量大小,“在SQL数据库中插入数据不受群集密钥的影响”-这是不正确的。为什么“在SQL数据库中插入数据不受群集密钥的影响”是不正确的?不要出于明显的原因删除PK或FK(另外,您可能会将PK与群集密钥混淆)这取决于DB中的目标表是空表还是已经包含数据。如果目标表已经包含日期,正确的方法是使用临时表。在SQL数据库中插入数据不受群集键的影响。它受Spark executors建立的连接数、该表使用的约束数的影响根据批量大小,“在SQL数据库中插入数据不受群集键的影响”-这是不正确的。为什么“在SQL数据库中插入数据不受群集键的影响”是不正确的?
# Execute insert into tblAFS for each row in dataframe
# Using fast execute
start = time.time()
df = df.select("F1", "F2", "F3", "F4", "F5",
"F6", "F7", "F8", "F9").na.fill(0)
conn = pyodbc.connect(shared.get_odbcconn(config))
cursor = conn.cursor()
cursor.fast_executemany = True
collected = df.rdd.toLocalIterator()
counter = 1
for row in collected:
cursor.execute("""
INSERT INTO dbo.tblAFS
([F1],[F2],[F3],[F4],[F5],[F6],[F7],[F8],[F9])
VALUES (?,?,?,?,?,?,?,?,?)""",
row["F1"], row["F2"], row["F3"], row["F4"], row["F5"],
row["F6"], row["F7"], row["F8"], row["F9"])
counter = counter + 1
conn.commit()
conn.close()
def FUNC_C1(df):
# 1. Create csv file for each F2 partition
# 2. Bulk insert all files generated in table tblAFS
start = time.time()
file_path = config.get('action', 'stats_results')
df = df.select("F1", "F2", "F3", "F4", "F5",
"F6", "F7", "F8", "F70").na.fill(0)
df.write.mode("overwrite").options(header=True).csv(file_path)
conn = pyodbc.connect(shared.get_odbcconn(config))
cursor = conn.cursor()
cursor.fast_executemany = True
files = glob(f"{file_path}/*.csv")
counter = 1
for file in files:
cursor.execute(f"BULK INSERT dbo.tblAFS FROM '{getcwd()}/{file}'
WITH (FORMAT = 'CSV', FIRSTROW = 2)")
counter = counter+1
conn.commit()
conn.close()