1

I unfortunately have quite a broad question regarding queries that return more columns than they need.

Simply put, is this bad practice and should it be avoided at all costs? We continuously have debates about this in our development team. Some argue that all queries should only return the exact data they need as this would reduce I/O etc, others argue that it is OK to have a query that returns a few extra columns such as int or nvarchar(50) as this reuses execution plans and makes development faster. We are not using any SELECT * statements anywhere so this is not an issue - it is purely where a few extra columns are explicitly specified.

I know this may trigger a debate rather than an answer but any insight would be helpful.

7
  • 6
    How does returning extra columns make development faster?
    – mustaccio
    Commented Jan 15, 2019 at 11:51
  • 2
    This is not something that’s easy to answer. Let’s take the simple case of two versions of a query with no filters: one with six columns (Q6), the other with three more columns for a total of 9 (Q9). Sure Q6 incurs less I/O but now you have two entries in the plan cache. What it probably comes down to is (a) how much development time is really saved by reusing Q9? (b) how much more I/O is used by Q9? (c) how often is Q6 all you need, compared to Q9? I don’t really buy the development argument - surely it doesn’t take long for a dev to understand their code enough to specify the exact columns. Commented Jan 15, 2019 at 12:16
  • 1
    SELECT A,B,C could read only an INDEX while SELECT A,B,C,D does not. Commented Jan 15, 2019 at 13:49
  • 5
    @argumentativedev to me this is close to moving into the God Object territory. It also adds to maintenance burden, having to explain to others, and your future self, why on earth you're not using values returned by the method.
    – mustaccio
    Commented Jan 15, 2019 at 14:31
  • 3
    This would violate some fundamental development practices of creating a dependency where one is not required. When you have to change that one query that is used by n methods, you have to test all of those methods and you risk breaking all of them. It may not seem like a big deal if it's just a column or two and a process or two, but does it scale? No--it can become a big deal later, and then it's too much time to do it right so you have a mess. If it doesn't scale, don't do it (IMO). Commented Jan 15, 2019 at 16:00

1 Answer 1

4

Some argue that all queries should only return the exact data they need as this would reduce I/O etc...

And they are correct!

...others argue that it is OK to have a query that returns a few extra columns such as int or nvarchar(50) as this reuses execution plans and makes development faster

These folks are also correct!

There are always tradeoffs with these things.

Imagine a web page where users can edit their profile, populated by "query 1" here:

SELECT Id, FullName, UserName, Phone 
FROM dbo.Users 
WHERE Id = @Id;

And then there's an admin page that uses "query 2" here:

SELECT Id, FullName, UserName, Phone, IsActive, AdminComments 
FROM dbo.Users 
WHERE Id = @Id;

Performance

For the situation where we're using both queries, we have (non-exhaustive list of pros and cons):

  • Con: two different plans taking up space in the plan cache
  • Con: developers had to write two different queries / stored procedures
  • Pro: the first query will only be doing the work it needs to (no extra I/O)
  • Pro: the two queries can be optimized differently
  • Pro: the two queries can be indexed for separately

If we just have query 2, the situation is basically inverted (only one plan in the cache, only one query / proc had to be written, but the query uses more I/O, etc).

Security

There's also an aspect of security: you might not want those "admin only" columns getting queried for non-admin pages, even if they are never presented to the user.

Maintainability

Sharing the same query for multiple different pages that don't need all that data can also lead to maintainability problems down the road. What if query 2 suddenly needs to join to other tables, in order to pull in additional information about user activity that's not available to regular users?

Now the normal user page is being impacted by the admin query. And developers at that time might not realize they need to go back and check on the regular user page.

What if some enterprising developer removes columns from query 2, because it's decided admins don't care about them? Now the regular user page is actually broken.

Takeaway

Re-using queries can be a valid time-saving strategy, but it requires good change management and testing later to make sure that you don't break anything when these re-used queries are modified. It's also possible various factors will cause the queries to be split up later (performance, feature changes). You'll have to keep that in mind to determine if the up front time saving is worth the cost later.

Generally speaking, I think it's better to have queries that are specific to each use-case. You'll notice that this results in lots of stored procedures / queries, which has it's own maintenance overhead. There are some things you can do to help with that though (keep the procedures small where possible, include a comment in the procedure that indicates what app function / page uses that query, name the procedures very clearly).

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.