I am working on rewriting some poorly written SQL queries and they are over-utilizing sub-queries. I am looking for best-practices regarding the use of sub-queries.
There is no silver bullet here. Each and every usage has to be independently assessed. There are some cases where correlated subqueries are plain inefficient, this one below is better written as a JOIN
select nickname, (select top 1 votedate from votes where user_id=u.id order by 1 desc)
from users u
On the other hand, EXISTS and NOT EXISTS queries will win out over JOINs.
select ...
where NOT EXISTS (.....)
Is normally faster than
select ...
FROM A LEFT JOIN B
where B.ID is null
Yet even these generalizations can be untrue for any particular schema and data distribution.
Unfortunately the answer greatly depends on the sql server you're using. In theory, joins are better from a pure-relational-theory point of view. They let the server do the right thing under the hood and gives them more control and thus in the end can be faster. If the server is implemented well. In practice, some SQL servers perform better if you trick it into optimizing it's queries through sub-queries and the like.
Subqueries are usually fine unless they are dependent subqueries (also known as correlated subqueries). If you are only using independent subqueries and they are using appropriate indexes then they should run quickly. If you have a dependent subquery you might run into performance problems because a dependent subquery typically needs to be run once for each row in the outer query. So if your outer query has 1000 rows, the subquery will be run 1000 times. On the other hand an independent subquery typically only needs to be evaluated once.
If you're not sure what is meant by a subquery being dependent or independent here's a rule of thumb - if you can take the subquery, remove it from its context, run it, and get a result set then it's an independent subquery
.
If you get a syntax error because it refers to some tables outside of the subquery then its a dependent subquery
.
The general rule of course has a few exceptions. For example:
If performance is an issue then measure your specific queries and see what works best for you.