我需要创建一个桌面应用程序来将数据从oracle数据库复制到SQL server数据库(客户端明确希望这样做- ETL软件、DTS等都已输出-它必须是桌面*.exe)。
当数据达到数百万(通常是数千万或数亿)行时,我不能使用sqlbulkcopy( dataTable ),因为dataTable的大小很快就会占用所有可用内存。
我使用的是sqlbulkCopy(dataReader),但它仍在消耗本地内存。
如何在不使用大量本地内存的情况下,将数据从读取器流式传输到sql表?
(跳过try-catches等,只跳过核心代码):
Dim dr As OleDb.OleDbDataReader
Dim connString As String = "Provider=MSDAORA.1;User ID=X;password=X;Data Source=X;Persist Security Info=False"
Dim cnn As OleDb.OleDbConnection = New OleDb.OleDbConnection(connString)
Dim cmd As OleDb.OleDbCommand = New OleDb.OleDbCommand("SELECT * FROM Table", cnn)
cnn.open
dr = cmd.ExecuteReader
Dim sqlCnn As SqlClient.SqlConnection = New SqlClient.SqlConnection("Server=X;Database=X;Trusted_Connection=True;Connection Timeout=60")
sqlCnn.Open()
Dim bk As SqlClient.SqlBulkCopy = New SqlClient.SqlBulkCopy(sqlCnn)
bk.DestinationTableName = "TABLE_NAME"
bk.EnableStreaming = True
bk.BatchSize = 100
bk.BulkCopyTimeout = 0
bk.WriteToServer(dr)
无论批处理大小如何,都会在本地计算机上引发内存不足异常。在消亡之前,页面文件的使用率会上升。需要将datareader流式传输到sql server,因此不会使用太多本地内存。
发布于 2019-06-26 15:35:02
感谢Jeroen提出了使用Oracle本机提供程序而不是OLE的想法。
“官方Oracle ODP.NET托管驱动程序”
数据现在流得很快(大约每秒10,000行),并且不会过度消耗本地内存,这正是我正在寻找的。
新代码(缺少try-catch等,只有代码):
'Oracle connection using ODP.Net Managed Driver
Dim factory As Common.DbProviderFactory = Common.DbProviderFactories.GetFactory("Oracle.DataAccess.Client")
Dim dbconn As Common.DbConnection = factory.CreateConnection()
Dim connString As String = "User ID=X;password=X;Data Source=X;"
dbconn.ConnectionString = connString
dbconn.Open()
'Retrieval of data from oracle
Dim dbcommand = factory.CreateCommand
dbcommand.Connection = dbconn
dbcommand.CommandText = "SELECT * FROM Table"
Dim dr As Common.DbDataReader
dr = dbcommand.ExecuteReader
'Stream to SQL
Dim sqlCnn As SqlClient.SqlConnection = New
SqlClient.SqlConnection("Server=X;Database=X;Trusted_Connection=True;Connection Timeout=60")
sqlCnn.Open()
Dim bk As SqlClient.SqlBulkCopy = New SqlClient.SqlBulkCopy(sqlCnn)
bk.DestinationTableName = "TABLE_NAME"
bk.EnableStreaming = True
bk.BatchSize = 5000
bk.BulkCopyTimeout = 0
bk.WriteToServer(dr)
https://stackoverflow.com/questions/56755039
复制相似问题