I have a SQL query that’s fairly complicated and involves multiple subqueries and unions. Despite the complexity, the subquery part executes very quickly (< 1ms once compiled). But when I run the query as a whole, it’s taking upwards of 60ms.
I’ve used “set statistics time on” and “set statistics io on” to track accesses of the base tables, and SQL is performing many more logical reads than necessary. When I run the subquery on it’s own, it only does 10 reads or so, but it’s around 1800 when the entire query is run.
I’d like to encourage SQL to evalute the subquery first – the expected number of rows is 1-5 so the data set is tiny. It should then be inner joined to the same base table, and pull back an estimated 10-20 records.
Is there a way to use hints to ensure SQL optimises for the expected cases? The query logic seems to be too much for the optimiser and it’s choosing an execution plan that would only be ideal for row sets far larger than will ever exist in my situation.
Edit: One of the conditions in the final join will filter out 99.99% of the rows in the base table. If I can force SQL to evaluate that first, it should do the trick. Is there a way to do this?
Query text here: http://pastebin.com/zVR91AP2
With the WHERE clause at the end commented out, the query returns 4 rows and runs in <1ms with 33 logical reads of the audit table.
But if I uncomment the WHERE clause, it returns 3 rows (1 filtered out) and takes 50ms with a whopping 1277 logical reads of the audit table. The io stats indicate that a work table is being used in the first instance, but not in the second. I want to encourage SQL to use this work table.
Worked it out. The solution was to use a join hint, which forces the evaluation of the inner query before joining it to the larger table.
inner REMOTE join dbo.poAudit… etc