question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Proposal: give SqlBulkCopy a way to specify the ORDER hint

See original GitHub issue

The bulk insert functionality of SQL Server supports an ORDER hint to speed up inserting of already ordered data into a table with a clustered index. Without this hint, SQL Server forces an intermediate sort of the incoming data before inserting, which can add significant overhead (think tempdb spills). Existing unmanaged ways to bulk copy (bcp.exe, BULK INSERT, OPENROWSET(BULK, ...)) all offer ways to specify this hint, but SqlBulkCopy does not, leaving managed code out in the cold.

Proposed API

public class SqlBulkCopy 
{
    // Existing members left out
    
    public SqlBulkCopyOrderHintColumnCollection OrderHintColumns { get; }
}

// New class
public sealed class SqlBulkCopyOrderHintColumn {
    public SqlBulkCopyOrderHintColumn(string column, System.Data.SqlClient.SortOrder sortOrder);
    
    public string Column { get; set; }
    public SortOrder SortOrder { get; set; }    // throws ArgumentException on SortOrder.Unspecified
}

// New class, same shape as SqlBulkCopyColumnMappingCollection
public class SqlBulkCopyOrderHintColumnCollection : System.Collections.CollectionBase {
    public SqlBulkCopyOrderHintColumn Add(SqlBulkCopyOrderHintColumn bulkCopyOrderHintColumn);
    
    // throws ArgumentException on SortOrder.Unspecified
    public SqlBulkCopyOrderHintColumn Add(string column, SortOrder sortOrder);
    
    public void Clear();
    public bool Contains(SqlBulkCopyOrderHintColumn value);
    public void CopyTo(SqlBulkCopyOrderHintColumn[] array, int index);
    public System.Collections.IEnumerator GetEnumerator();
    public int IndexOf(SqlBulkCopyOrderHintColumn value);
    public void Insert(int index, SqlBulkCopyOrderHintColumn value);
    public void Remove(SqlBulkCopyOrderHintColumn value);
    public void RemoveAt(int index);
}

Sample use

using (var sqlBulkCopy = new SqlBulkCopy(connection)) {
    // leaving out other options
    
    sqlBulkCopy.OrderHintColumns.Add("Column1", SortOrder.Descending);
    sqlBulkCopy.OrderHintColumns.Add("Column2", SortOrder.Ascending);
    sqlBulkCopy.OrderHintColumns.Add("Column3", SortOrder.Descending);
    sqlBulkCopy.DestinationTableName = "Table1";
    sqlBulkCopy.WriteToServer();
}

This should result in SqlBulkCopy issuing a statement of the form

insert bulk Table1 (...) with (ORDER ([Column1] DESC, [Column2] ASC, [Column3] DESC))

Ensuring the input rows are actually ordered according to the hint is the programmer’s responsibility; SQL Server will either ignore the hint (if the table is a heap) or produce an error (if the table is clustered) and SqlBulkCopy need not further verify this.

Open questions

  • Should we make SqlBulkCopyOrderHintColumnCollection a strongly typed collection to get with the times, or maintain consistency with the existing ColumnMapping property and use a non-generic collection?
  • Should SqlBulkCopyOrderHintColumn be immutable, again, mostly getting with the times? SqlBulkCopyColumnMapping is very much the opposite; it even has a parameterless constructor, which seems quite undesirable.

Background

See #5114 for previous discussion.

Issue Analytics

  • State:closed
  • Created 5 years ago
  • Reactions:5
  • Comments:7 (2 by maintainers)

github_iconTop GitHub Comments

4reactions
cheenamalhotracommented, Jun 10, 2020

Closing the issue as https://github.com/dotnet/SqlClient/pull/540 is now merged. This feature will be available starting Microsoft.Data.SqlClient v2.0.0

1reaction
Dean-NCcommented, Feb 12, 2020

Yes, this is a needed feature for me…without it, I drop the clustered index and re-create it afterwards. It’s reasonable for a bulk-load tool to have this option.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Order hints for bulk copy operations - SQL Server
A SqlBulkCopyColumnOrderHint object is created to define the sort order for the ProductNumber column in the destination table. The order hint is ...
Read more >
SqlBulkCopy is not inserting rows in same order from the . ...
Typically there is no guaranteed order for bulk insert operations. Besides inserting each row individually (neither fun nor efficient), ...
Read more >
Using SqlBulkCopy in .NET for Faster Bulk Data Loading
SqlClient namespace that allows you to load data into SQL Server in a very efficient manner. SqlBulkCopy gives you similar functionality ...
Read more >
Improve Data loading performance using Bulk Insert ...
After filling the DataTable, we're creating an instance of SqlBulkCopy with the connection string we want (we don't give it any other parameters ......
Read more >
SqlBulkCopy for large sets of modified objects
I've been working on CustomCommitChanges logic to use an alternate method of updating my SQL Server database when there are a large number ......
Read more >

github_iconTop Related Medium Post

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found