Roundtrips and the real bottlenecks
Now the discussion of yesterday about Dynamic SQL and Stored Procedures are slowing down, I'd like to mention a little thing that popped up during the debate: roundtrips.
A roundtrip is a new request from client to database server with a response from the database server. This takes time, there is no doubt about that. I'll admit that a batch of statements in a stored procedure is easier to work with than a set of statements to create a batch of dynamic sql queries. Some argued that the call to a single stored procedure requires just 1 roundtrip and creating and executing a bunch of dynamic queries would require sometimes more than 1 roundtrip (e.g.: for each dynamic query 1 roundtrip).
This triggered me (pun intended) to think about this further. I wondered: if these people are so focussed on roundtrips and the costs of a roundtrip, are these people also using DataReader.GetBytes() ? Are these people also batching all calls required for, say, a webform, into 1 stored procedure? A wild guess from my side: no I don't think a lot of these people use GetBytes() to do efficient blob retrieval and no they're not batching multiple calls of a page into 1 stored proc. Why are these 2 obvious random features related to roundtrips? Well, focussing on the time it takes a roundtrip over an already opened connection is performed (a few milliseconds to set it up), implies all other bottlenecks in a conversation between client and server are removed already and 'hidden' extra roundtrips are optimized away. I have doubts about that. Performance is important, but if you want to discuss benefits of method A compared to method B, using the argument of the roundtrip is perhaps not the best argument you can pick, because the time a roundtrip may take is far less than for example the time it takes to fetch large blobs in resultsets.
I can imagine a lot of people simply ignore DataReader.GetBytes() and read the complete blob at once, stored procedure or not. This can be very inefficient. When roundtrips concern you because they take time, make certain that you have removed every other bottleneck first, starting with unnecessary fetching of blobdata, after removing the overhead time of using a DataAdapter of course.
When you have optimized your dataretrieval of individual rows and batches of rows, there is another roundtrip issue to be discussed: when for example a webform requests 3 or 4 batches of data to build the webform's content, are these requests bundled into 1 call? If not, you have 3 or 4 roundtrips to the server, while there could be 1. When you are concerned about roundtrips and the time it takes to make one, you definitely shouldn't leave these 2 or 3 unnecessary requests go unnoticed and optimize them away. After all: a roundtrip seems to be important.
Ah, you can't? Because that would interfer GUI design with DAL implementation, it would make the DAL be tight to the GUI's layout? That's right. You can't, or better: you shouldn't. A DAL is a generic service layer, which shouldn't have any GUI-related design aspects, after all: changing the GUI shouldn't affect the DAL. That makes the aspect of talking about roundtrips a little silly don't you think? Focussing on 1 or 2 extra roundtrips for Dynamic SQL statements (which can be batched as well, but that aside) as being a 'disadvantage', while roundtrips which are obvious are not optimized away because of the generic approach of layered design, doesn't seem to me a valid argument. OR you optimize the cr*p out of every line of code and remove every roundtrip there is OR you accept roundtrips exist and deal with the other bottlenecks to keep the performance as high as possible. You can't do both because optimization requires compromises on the design and vice versa.
I'm all for discussions with fair arguments. To me, using 'the amount of roundtrips' for technique A compared to technique B isn't a fair argument, because it is irrelevant when other aspects of a software system is taken into account. Optimization doesn't start with optimizing tiny loops. It starts with optimizing the general algorithms used.