我正在使用临时表批量插入数百万条记录,以两种方式检查性能-有无事务。首先,删除是否存在并在每次测试之前创建新表。
//Filling up data to insert, calling from constructor
private void FillData()
{
_insertData = new List<TransactionDto>();
for (var i = 1; i <= 1000000; i++)
{
_insertData.Add(new TransactionDto(i, $"Insert{i}"));
}
}
private void PrepareDbTables(NpgsqlConnection connection)
{
var query = @"DROP TABLE IF EXISTS TransactionTest;
CREATE TABLE TransactionTest(id integer,text varchar(24))";
connection.Query(query);
}
private void DropAndCreateTempTable(NpgsqlConnection connection)
{
var query = @"DROP TABLE IF EXISTS TmpTransactions";
connection.Execute(query);
query = @"CREATE TEMP TABLE TmpTransactions (id integer, text varchar(24));";
connection.Execute(query);
}
这是2个测试:
[Fact]
public void CheckInsertBulkSpeedWithOutTransaction()
{
var sw = new Stopwatch();
using (var con = new NpgsqlConnection(ConnectionString))
{
con.Open();
//Delete and create new table TransactionTest
PrepareDbTables(con);
DropAndCreateTempTable(con);
sw.Start();
InsertBulkWithTempTable(null, _insertData, con);
sw.Stop();
}
_output.WriteLine(
$"Test completed. InsertBulk without transaction {_insertData.Count} elements for: {sw.ElapsedMilliseconds} ms");
}
与交易相同的测试:
[Fact]
public void CheckInsertBulkSpeedWithTransaction()
{
var sw = new Stopwatch();
using (var con = new NpgsqlConnection(ConnectionString))
{
con.Open();
//Delete and create new table TransactionTest
PrepareDbTables(con);
DropAndCreateTempTable(con);
sw.Start();
using (var transaction = con.BeginTransaction(IsolationLevel.ReadUncommitted))
{
InsertBulkWithTempTable(transaction, _insertData, con);
transaction.Commit();
transaction.Dispose();
}
sw.Stop();
}
_output.WriteLine(
$"Test completed. InsertBulk with transaction {_insertData.Count} elements for: {sw.ElapsedMilliseconds} ms");
}
插入对象记录的主要方法:
private void InsertBulkWithTempTable(NpgsqlTransaction transaction, List<TransactionDto> data, NpgsqlConnection connection)
{
using (var writer =
connection.BeginBinaryImport(
"COPY TmpTransactions(id,text) FROM STDIN(Format BINARY)"))
{
foreach (var dto in data)
{
writer.WriteRow(dto.Id, dto.Text);
}
writer.Complete();
}
var query =
"INSERT INTO TransactionTest select * from TmpTransactions";
//connection.Query(query, transaction);
connection.Execute(query);
}
每次运行这些测试的结果总是不同的,并且无论我使用Execute()还是Query()都没关系。
Test completed. InsertBulk without transaction 1000000 elements for: 7451 ms
Test completed. InsertBulk with transaction 1000000 elements for: 4676 ms
Test completed. InsertBulk without transaction 1000000 elements for: 6336 ms
Test completed. InsertBulk with transaction 1000000 elements for: 8776 ms
我试图弄清楚它所依赖的是什么? 有任何想法吗?任何帮助表示赞赏。 谢谢。