I cannot post the actual query here, so I am posting the basic outline of the query which should suffice. The query is used to page and return a set of users ranked according the output of a function, say F. F takes parameters from the User table and other tables which are joined. The query is something like as follows
Select TOP (20)
from (select row_number OVER (Order By F desc) as rownum,
user.*, ..
from user
inner join X on user.blah = X.blah
left outer join Y on user.foo = Y.foo
where DATEDIFF(dd, LastLogin, GetDate()) > 200 and Y.bar > FUBAR) as temp
where rownum > 0
According to the execution plan 91% of the cost is in the Sort. Since the sort is based on F, I cannot add an index to speed the sort. The inner query queries all the records, filters then sorts. Now most of the time the users just look at results in the 1 – 5 pages (1 page has 20 records hence the Top(20)) so I was thinking if there was any way I could limit the rows being processed and sorted and make the query faster and less CPU intensive most of the time.
EDIT: When I say to Calculate F tables are joined, what I mean is this. F takes in parameters such as X.blah and Y.foo and Y.bar. That’s it. All these parameters also need to be returned as part of the resultset. e.g. The Latitude and Longitude of the User’s Last location is stored in X.
Not sure if and how much it’ll help – but two things:
can you make sure all the foreign key columns and colums in the
WHEREclause (user.blah,X.blah,user.foo,Y.foo,Y.bar) are indeed indexed? This will significantly help JOIN performance.If those columns are not indexed, there also might be a sort operation in the execution plan that SQL Server uses so it can then use a Merge Join for the data. So your sort might not even really come from the
OVER (ORDER BY F DESC)that you think causes the sortyou’re combining
TOP (20)with row numbers, but you’re not defining any realORDER BYfor the complete result set – so your results will be random at best. Also, if you already define therownum, couldn’t you just use: