Please publish the execution plan, as well as the exact definition of the table, including all indexes.
When you use a variable, the optimizer does not know what selectivity the request will have, @LastSeenWorkflowID can filter everything except the very last few lines in Workflow, or it can include all of them. The generated plan should work in both situations. There is a threshold at which a range of searches by a clustered index becomes more expensive than a full scan by a non-clustered index, simply because the clustered index is much wider (it includes each column at the sheet level) and therefore has so many pages to repeat. The generated plan, which considers the value for @LastSeenWorkflowID to be unknown, probably crosses this threshold when evaluating the cost of searching for a clustered index and, as such, chooses to scan by a non-clustered index.
You can specify a narrow index specifically designed for this query:
CREATE INDEX WorkflowSubId ON Workflow(ID, SubId);
or
CREATE INDEX WorkflowSubId ON Workflow(ID) INCLUDE (SubId);
Such an index is too good for your query, regardless of the value of @LastSeenWorkflowID.
source share