Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Any SQL Server multiple-recordset stored procedure gotchas?

Context

My current project is a large-ish public site (2 million pageviews per day) site running a mixture of asp classic and asp.net with a SQL Server 2005 back-end. We're heavy on reads, with occasional writes and virtually no updates/deletes. Our pages typically concern a single 'master' object with a stack of dependent (detail) objects.

I like the idea of returning all the data required for a page in a single proc (and absolutely no unnecesary data). True, this requires a dedicated proc for such pages, but some pages receive double-digit percentages of our overall site traffic so it's worth the time/maintenance hit. We typically only consume multiple-recordsets from our .net code, using System.Data.SqlClient.SqlDataReader and it's NextResult method. Oh, yeah, I'm not doing any updates/inserts in these procs either (except to table variables).

The question

SQL Server (2005) procs which return multiple recordsets are working well (in prod) for us so far but I am a little worried that multi-recordset procs are my new favourite hammer that i'm hitting every problem (nail) with. Are there any multi-recordset sql server proc gotchas I should know about? Anything that's going to make me wish I hadn't used them? Specifically anything about it affecting connection pooling, memory utilization etc.

like image 266
Jaysen Marais Avatar asked Jan 23 '09 12:01

Jaysen Marais


3 Answers

Here's a few gotchas for multiple-recordset stored procs:

They make it more difficult to reuse code. If you're doing several queries, odds are you'd be able to reuse one of those queries on another page.

They make it more difficult to unit test. Every time you make a change to one of the queries, you have to test all of the results. If something changed, you have to dig through to see which query failed the unit test.

They make it more difficult to tune performance later. If another DBA comes in behind you to help performance improve, they have to do more slicing and dicing to figure out where the problems are coming from. Then, combine this with the code reuse problem - if they optimize one query, that query might be used in several different stored procs, and then they have to go fix all of them - which makes for more unit testing again.

They make error handling much more difficult. Four of the queries in the stored proc might succeed, and the fifth fails. You have to plan for that.

They can increase locking problems and incur load in TempDB. If your stored procs are designed in a way that need repeatable reads, then the more queries you stuff into a stored proc, the longer it's going to take to run, and the longer it's going to take to return those results back to your app server. That increased time means higher contention for locks, and the more SQL Server has to store in TempDB for row versioning. You mentioned that you're heavy on reads, so this particular issue shouldn't be too bad for you, but you want to be aware of it before you reuse this hammer on a write-intensive app.

like image 77
Brent Ozar Avatar answered Sep 22 '22 17:09

Brent Ozar


I think multi recordset stored procedures are great in some cases, and it sounds like yours maybe one of them.

The bigger (more traffic), you site gets, the more important that 'extra' bit of performance is going to matter. If you can combine 2-3-4 calls (and possibly a new connections), to the database in one, you could be cutting down your database hits by 4-6-8 million per day, which is substantial.

I use them sparingly, but when I have, I have never had a problem.

like image 40
E.J. Brennan Avatar answered Sep 26 '22 17:09

E.J. Brennan


I would recommend having invoking in one stored procedure several inner invocations of stored procedures that return 1 resultset each.

create proc foo 
as
execute foobar --returns one result

execute barfoo --returns one result

execute bar  --returns one result

That way when requirments change and you only need the 3rd and 5th result set, you have a easy way to invoke them without adding new stored procedures and regenerating your data access layer. My current app returns all reference tables (e.g. US states table) if I want them or not. Worst is when you need to get a reference table and the only access is via a stored procedure that also runs an expensive query as one of its six resultsets.

like image 23
MatthewMartin Avatar answered Sep 25 '22 17:09

MatthewMartin