Search code examples
sql-servert-sqlquery-optimization

SQL Scan vs Seek when using OR in where criteria


Consider the following two queries from the AdventureWorks database. The where criteria is entirely on indexed columns. If you use OR criteria both tables get a full table scan on them. In the second scenario the criteria is split out over two queries that are unioned. In the second scenario both tables get index seeks. Can someone explain why SQL can't/won't optimize the first query to do an index seek? Are there ways to tell SQL to do a seek without rewriting as a UNION? (I've tried index hints with no success)

SELECT *
FROM [AdventureWorks2022].[Sales].[SalesOrderHeader] hdr
JOIN [AdventureWorks2022].[Sales].[SalesOrderDetail] dtl ON hdr.SalesOrderID = dtl.SalesOrderID
WHERE hdr.SalesOrderID = 43659 OR dtl.SalesOrderDetailID =  43659

----

SELECT *
FROM [AdventureWorks2022].[Sales].[SalesOrderHeader] hdr
JOIN [AdventureWorks2022].[Sales].[SalesOrderDetail] dtl ON hdr.SalesOrderID = dtl.SalesOrderID
WHERE hdr.SalesOrderID = 43659
 
UNION
 
SELECT *
FROM [AdventureWorks2022].[Sales].[SalesOrderHeader] hdr
JOIN [AdventureWorks2022].[Sales].[SalesOrderDetail] dtl ON hdr.SalesOrderID = dtl.SalesOrderID
WHERE dtl.SalesOrderDetailID =  43659

Solution

  • This answer by Paul White seems to explain it and confirms that SQL cannot come up with the UNION plan with the OR criteria.

    This transform only applies to a single table, and does not apply to attribute-to-attribute comparisons.