表值参数:以小块发送数据

时间:2012-09-17 21:33:11

标签: .net sql-server-2008 stored-procedures table-variable

我正在读取csv文件并将数据作为表变量发送到存储过程。从我到目前为止测试,我能够在3分30秒内处理300k记录。该文件可能包含多达数百万条记录。我想知道将所有这些记录一次性发送到存储过程是否是一个好主意,还是应该分批发送500k?我已将命令超时设置为1800。

1 个答案:

答案 0 :(得分:1)

使用IEnumerable SqlDataRecord的示例 它有点像反向数据加载器

注意我排序。这是由聚集索引。索引碎片绝对会降低加载速度。第一个实现使用了Insert Values(未排序),在12小时的运行中,这个版本的速度提高了100倍。我还在加载结束时禁用PK以外的索引和reindex。从长远来看,我得到大约500行/秒。你的样品是1400 /秒那么棒。如果你开始看到退化,那就要看看了。

public class DocFTSinXsCollection : List<DocFTSinX>, IEnumerable<SqlDataRecord>
{
    // used by TVP for fast insert
    private int sID;
    private IEnumerable<DocFTSinX> docFTSinXs;
    IEnumerator<SqlDataRecord> IEnumerable<SqlDataRecord>.GetEnumerator()
    {
        //todo fix the order in 3 to sID, wordID1, workID2
        var sdr = new SqlDataRecord(
        new SqlMetaData("wordID1", System.Data.SqlDbType.Int),
        new SqlMetaData("wordID2", System.Data.SqlDbType.Int),
        new SqlMetaData("sID", System.Data.SqlDbType.Int),
        new SqlMetaData("Delta", System.Data.SqlDbType.Int));
        foreach (DocFTSinX oh in docFTSinXs.OrderBy(x => x.Word1).ThenBy(x => x.Word2))
        {
            sdr.SetInt32(0, oh.Word1);
            sdr.SetInt32(1, oh.Word2);
            sdr.SetInt32(2, sID);
            sdr.SetInt32(3, (Int32)oh.Delta);
            yield return sdr;
        }
    }

    public DocFTSinXsCollection(int SID, IEnumerable<DocFTSinX> DocFTSinXs)
    {
        sID = SID;
        docFTSinXs = DocFTSinXs;
        //Debug.WriteLine("DocFTSinXsCollection DocFTSinXs " + DocFTSinXs.Count().ToString());
    }
}

需要考虑的其他工具是SQLBulkCopy .NET类和Drapper。

OP询问如何批量执行。

 while (true)
 {
     // if no more break;
     // fill list or datatable with next 100000
     // send list or datatable to db
 }