除了很小的数据集之外,您将很难超越 NpgSql 实现 copy 的性能,这可以通过您的 NpgSqlConnection 对象的 BeginTextImport 方法来完成。
因此,无论您的数据如何存在于您的应用程序中,如果您通过文本导入(复制)转储输出,它应该非常紧凑。这是一个如何使用数据表执行此操作的示例。请记住,数据表中的列和表中的列必须对齐 - 如果不是,您需要以一种或另一种方式进行管理。
这以 NpgSql 3.1.9 或更高版本为前提。
object[] outRow = new object[dt.Columns.Count];
using (var writer = conn.BeginTextImport("copy <table> from STDIN WITH NULL AS '' CSV"))
{
foreach (DataRow rw in dt.Rows)
{
for (int col = 0; col < dt.Columns.Count; col++)
outRow[col] = rw[col];
writer.WriteLine(string.Join(",", outRow));
}
}
至于重复...哇,这真的取决于。定义“重复”。如果它只是“选择不同的”,那么它还取决于您期望的重复次数。如果数量很少,List.Exists<> 可能就足够了,但如果你有大量的欺骗,一个 Dictionary 对象将使每次查找更有效率。典型的列表查找是 O(n),而字典查找是 O(1)。
对于上述示例,这是一个非常强力的字典不同插入示例:
object[] outRow = new object[dt.Columns.Count];
Dictionary<string, bool> already = new Dictionary<string, bool>();
bool test;
using (var writer = conn.BeginTextImport("copy <table> from STDIN WITH NULL AS '' CSV"))
{
foreach (DataRow rw in dt.Rows)
{
for (int col = 0; col < dt.Columns.Count; col++)
outRow[col] = rw[col];
string output = string.Join(",", outRow);
if (!already.TryGetValue(output, out test))
{
writer.WriteLine(output);
already.Add(output, true);
}
}
}
免责声明:这是一个记忆猪。如果您可以通过任何其他方式管理欺骗,或保证数据的顺序,还有许多其他选择。
如果您不能(或不会)使用批量复制插入,有助于提高性能的方法是将您的插入包装到事务中 (NpgSqlTransaction),但是对于数十万行,我可以'不明白你为什么会这样做。