在一个简单的测试程序中,我开始一个事务,创建一个#temp表和两个索引,在表中插入一堆行,然后提交。
看着任务管理器I / O Writes for Sql Server,我看到每个表插入有1个磁盘写操作。这让我感到惊讶,因为#temp表不可恢复,因此除非有内存压力,否则无需进行写入或日志记录,即使需要对其进行日志记录,我也希望日志记录写入操作的次数最少,而不是每个插入操作一次。相反,使用20,000个插入,我得到20,000个I / O。
该引擎具有大量内存,没有其他应用程序的压力。
是否可以减少此处的I / O数量?
这是代码的要点(为简洁起见,删除了处置等)
var conn = new SqlConnection("my connection string");
conn.Open();
tran = conn.BeginTransaction();
var cmd = new SqlCommand("create table #sqltt(Context int, intValue int, stringValue varchar(100))", conn, tran))
cmd.ExecuteNonQuery();
// repeat the above sqlcmd pattern to create two indexes on the table
// then
cmd = new SqlCommand("INSERT INTO #sqltt (Context, intValue) VALUES ('-1', @intValue)", conn, tran))
var parm = cmd.CreateParameter();
parm.DbType = DbType.Int32;
parm.Direction = ParameterDirection.Input;
parm.ParameterName = "intValue";
for (var i = 0; i < HOWMANY; i++)
{
parm.Value = i;
cmd.ExecuteNonQuery();
}
tran.Commit();
conn.Close();
最佳答案
是的,通过在单个事务中批量处理多个插入。每个事务至少需要写入一个日志文件-tempdb和其他任何数据库都这样,因为尽管无法恢复,但对tempdb的操作在需要的时间内仍需要一致性和持久性。人们通常会误认为tempdb是“全部在内存中”或“不需要I / O”。 SQL Server确实进行了一些优化以减少tempdb I / O(例如缓存临时表,因此不需要经常重新创建它们),但是事务性I / O的基础仍然适用。
通过在单个事务中批量处理多个插入,可以减少需要等待的顺序写入次数。如果要真正减少日志记录,请使用批量插入。顺便说一句,通过在所有插入之后而不是之前创建索引,您还将获得更好的性能(除非插入以某种方式依赖于并且需要查找)。
关于sql-server - 为什么每个临时表插入一个I/O? sql服务器,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/26473686/