SqlClient: Implement optimized version of the new ADO.NET batching API
See original GitHub issueEdited by @divega on 2/6/2019
We want to add public and provider independent batching APIs to the base classes in ADO.NET. This has been described in detail at https://github.com/dotnet/corefx/issues/35135.
We plan for the batching API to include a “fallback implementation” that should work for most existing providers that simply support the DbCommand functionality. But the fallback implementation will be sub-optimal (it will just concatenate the contents from CommandText into a single string and execute it.
From now on, we are going to use this customer-reported issue to track implementing a SQL Server-optimized version of the batching APIs.
As this issue originally referred to, SqlClient already contain the general functionality necessary in System.Data.SqlClient.SqlCommandSet, but there is no public API to use it directly and the only way to leverage it is through DataSet and SqlDataAdapter.
Original issue contents
–
Command sets are a SQL Server / TDS facility that lets database clients send multiple batches in one round trip. This can be very beneficial for performance. This facility is currently only being used by the SqlDataAdapter
infrastructure. This infrastructure is not being used by modern apps anymore and it exposes only a very limited functionality (not arbitrary commands).
Command sets can help with this:
- Send multiple batches in one round trip
- Receive results independently
- Much enhanced performance for executing many small commands
- A clean API
SqlCommandSet
should be cleaned up and made public. There is great community interest and value in doing this (link to a well known post by Ayende, includes benchmarks, second post, Ayende’s hack to pry the class open).
Currently, people often concatenate their SQL commands into one batch. This is problematic:
- It can defeat plan caching
- It’s slower
- It’s tedious and error prone (especially since you need unique parameter names, and errors non-deterministically stop the batch or they don’t, and you can’t easily find out which command failed)
- It is subject to a total 2100 parameter limit (add by @roji, 2020-06-22)
I believe that command sets have great value. It looks like cleaning them up would not be too hard since they were written in a style that looks like they were meant to be exposed.
I also believe that the .NET community is not sufficiently aware that there is this super fast and clean way of submitting many small statements. Many applications and scenarios could benefit from this. When this is made public there should be a blog post on a Microsoft blog about it. It really is a secret ninja trick at this point. “Do this one special trick and get much better performance… DB consultants hate it.”
Entity Framework could send updates likes that. According to the measurements by Ayende (and my own) this would be a very nice performance boost. I believe EF sometimes sends multiple sub-queries for one query in case of includes. This could make use of command sets as well cutting away one round trip for each query.
In the age of cloud network latencies are typically higher. It becomes especially valuable to be able to cut out round-trips.
Issue Analytics
- State:
- Created 5 years ago
- Reactions:26
- Comments:57 (46 by maintainers)
Looks like this is going to get into NET6. I’ve still got my branch with the implementation in so I can rebase to current and get it posted as a draft.
Work that I know needs to be done:
@GSPP thanks for the detailed post. FYI, https://github.com/dotnet/corefx/issues/3688 is about adding command batching APIs in the ADO.NET provider model. I see this issue as a good complement for SQL Server support of whatever API we come up with.
Another relevant article about how command batching works in SqlClient: https://blogs.msdn.microsoft.com/dataaccess/2005/05/19/does-ado-net-update-batching-really-do-something/.