将 UniDataSet 复制到 SQL 服务器的最有效方法是什么?
What is the most efficient way to copy UniDataSet to SQL Server?
我有一个 U2/UniVerse 数据库,需要将一个 table 中的数据复制到 SQL 服务器 table 中。有问题的 table 有大约 600,000 行和不到 200 列。我没有创建 table,也无法更改它。
对于其他 tables,我一次遍历 UniDataSet
一条记录并将其添加到 DataTable
,然后使用 SqlBulkCopy
来将记录复制到 SQL 服务器。这工作正常,但是对于大 table 我似乎 运行 在创建 DataTable
.
时内存不足
DataTable dt = new DataTable("myTempTable");
dt.Columns.Add("FirstColumn", typeof(string));
dt.Columns.Add("SecondColumn", typeof(string));
... //adding a bunch more columns here
dt.Columns.Add("LastColumn", typeof(string));
U2Connection con = GetU2Con();
UniSession us1 = con.UniSession;
UniSelectList s1 = us1.CreateUniSelectList(0);
UniFile f1 = us1.CreateUniFile("MyU2TableName")
s1.Select(f1);
UniDataSet uSet = f1.ReadRecords(s1.ReadListAsStringArray());
foreach (UniRecord uItem in uSet)
{
List<String> record = new List<String>(uItem.Record.ToString().Split(new string[] { "þ" }, StringSplitOptions.None));
DataRow row = dt.NewRow();
row[0] = uItem.RecordID;
row[1] = record[0];
row[2] = record[1];
... //add the rest of the record
row[50] = record[49]
dt.Rows.Add(row);
}
con.Close();
这样就可以将 UniDataSet
中的记录复制到 DataTable
中。然后,我把SqlBulkCopy
的DataTable
改成了SQLtable:
string SQLcon = GetSQLCon();
using (SqlBulkCopy sbc = new SqlBulkCopy(SQLcon))
{
sbc.DestinationTableName = "dbo.MySQLTableName";
sbc.BulkCopyTimeout = 0;
sbc.BatchSize = 1000; //I've tried anywhere from 50 to 50000
try
{
sbc.WriteToServer(dt);
}
catch
{
Console.WriteLine(ex.Message);
}
}
这对我的 U2 table 具有 50,000 行左右的效果很好,但是当 table 具有 500,000 行时,它基本上会使调试器 (VS Express 2012) 崩溃。我正在执行此操作的 PC 是 Windows 7 x64 和 4GB 内存。 VS 进程看起来在崩溃前最多使用了 3.5GB RAM。
我希望有一种方法可以使用 SqlBulkCopy 将 UniDataSet 直接写入 SQL,但我对 U2 .Net 工具包不太熟悉。
我面临的问题是 UniDataSet 记录是多值的,我需要先将它们分开才能写入 SQL。
谢谢!
DataTable 在插入到数据库之前在内存中变得太大了。
你为什么不拆分批量插入操作?例如,读取前 50.000 个结果并插入 Sql 服务器数据库,清除 DataTable 内存并从接下来的 50.000 行重新开始。
if (dt.Rows.Count > 50000)
{
//do SqlbulkCopy
dt.Rows.Clear();
}
在 U2 Toolkit for .NET v2.1.0 中,我们实现了 Native Access。现在您可以直接从 UniData/UniVerse 文件创建 DataSet/DataTable。您也可以指定 WHERE 和 SORT 子句。您将看到性能改进,因为它不会进行太多的服务器行程来获取 ID。例如,如果您有 1000 个记录 ID,则将进行 1000 次 Server Trip。而如果您使用 Native Access,它将进行一次服务器访问。
请下载 U2 Toolkit for .NET v2.2.0 Hot Fix 1 并尝试以下代码。欲了解更多信息,请联系 u2askus@rocketsoftware.com.
U2Connection con = GetU2Con();
U2Command cmd = lConn.CreateCommand();
cmd.CommandText = string.Format("Action=Select;File=MyU2TableName;Attributes=MyID,FirstColumn,SecondColumn,LastColumn;Where=MyID>0;Sort=MyID");
U2DataAdapter da = new U2DataAdapter(cmd);
DataSet ds = new DataSet();
da.Fill(ds);
DataTable dt = ds.Tables[0];
我有一个 U2/UniVerse 数据库,需要将一个 table 中的数据复制到 SQL 服务器 table 中。有问题的 table 有大约 600,000 行和不到 200 列。我没有创建 table,也无法更改它。
对于其他 tables,我一次遍历 UniDataSet
一条记录并将其添加到 DataTable
,然后使用 SqlBulkCopy
来将记录复制到 SQL 服务器。这工作正常,但是对于大 table 我似乎 运行 在创建 DataTable
.
DataTable dt = new DataTable("myTempTable");
dt.Columns.Add("FirstColumn", typeof(string));
dt.Columns.Add("SecondColumn", typeof(string));
... //adding a bunch more columns here
dt.Columns.Add("LastColumn", typeof(string));
U2Connection con = GetU2Con();
UniSession us1 = con.UniSession;
UniSelectList s1 = us1.CreateUniSelectList(0);
UniFile f1 = us1.CreateUniFile("MyU2TableName")
s1.Select(f1);
UniDataSet uSet = f1.ReadRecords(s1.ReadListAsStringArray());
foreach (UniRecord uItem in uSet)
{
List<String> record = new List<String>(uItem.Record.ToString().Split(new string[] { "þ" }, StringSplitOptions.None));
DataRow row = dt.NewRow();
row[0] = uItem.RecordID;
row[1] = record[0];
row[2] = record[1];
... //add the rest of the record
row[50] = record[49]
dt.Rows.Add(row);
}
con.Close();
这样就可以将 UniDataSet
中的记录复制到 DataTable
中。然后,我把SqlBulkCopy
的DataTable
改成了SQLtable:
string SQLcon = GetSQLCon();
using (SqlBulkCopy sbc = new SqlBulkCopy(SQLcon))
{
sbc.DestinationTableName = "dbo.MySQLTableName";
sbc.BulkCopyTimeout = 0;
sbc.BatchSize = 1000; //I've tried anywhere from 50 to 50000
try
{
sbc.WriteToServer(dt);
}
catch
{
Console.WriteLine(ex.Message);
}
}
这对我的 U2 table 具有 50,000 行左右的效果很好,但是当 table 具有 500,000 行时,它基本上会使调试器 (VS Express 2012) 崩溃。我正在执行此操作的 PC 是 Windows 7 x64 和 4GB 内存。 VS 进程看起来在崩溃前最多使用了 3.5GB RAM。
我希望有一种方法可以使用 SqlBulkCopy 将 UniDataSet 直接写入 SQL,但我对 U2 .Net 工具包不太熟悉。
我面临的问题是 UniDataSet 记录是多值的,我需要先将它们分开才能写入 SQL。
谢谢!
DataTable 在插入到数据库之前在内存中变得太大了。 你为什么不拆分批量插入操作?例如,读取前 50.000 个结果并插入 Sql 服务器数据库,清除 DataTable 内存并从接下来的 50.000 行重新开始。
if (dt.Rows.Count > 50000)
{
//do SqlbulkCopy
dt.Rows.Clear();
}
在 U2 Toolkit for .NET v2.1.0 中,我们实现了 Native Access。现在您可以直接从 UniData/UniVerse 文件创建 DataSet/DataTable。您也可以指定 WHERE 和 SORT 子句。您将看到性能改进,因为它不会进行太多的服务器行程来获取 ID。例如,如果您有 1000 个记录 ID,则将进行 1000 次 Server Trip。而如果您使用 Native Access,它将进行一次服务器访问。
请下载 U2 Toolkit for .NET v2.2.0 Hot Fix 1 并尝试以下代码。欲了解更多信息,请联系 u2askus@rocketsoftware.com.
U2Connection con = GetU2Con();
U2Command cmd = lConn.CreateCommand();
cmd.CommandText = string.Format("Action=Select;File=MyU2TableName;Attributes=MyID,FirstColumn,SecondColumn,LastColumn;Where=MyID>0;Sort=MyID");
U2DataAdapter da = new U2DataAdapter(cmd);
DataSet ds = new DataSet();
da.Fill(ds);
DataTable dt = ds.Tables[0];