數據庫的分頁查詢通常由兩個查詢組成:數據庫
select count(*) from Goods
和函數
select * from ( select row_number() over(order by goodsId) as rowid, * from Goods ) as a where rowid >= @pageSize * (@pageIndex - 1) + 1 and rowid <= @pageSize * @pageIndex
第一個查詢,獲取符合條件的記錄總數,用於計算總頁數。第二個查詢獲取指定頁上的記錄。測試
兩個查詢須要執行兩次,也就是作兩次表掃描,這對效率是極大的損失。能不能只作一次表掃描?
row_number()函數在作排名時,確定須要作一次表掃描,而排名完成後,確定是知道有多少條記錄的,若是這個內部值能輸出到外部給調用者使用,那麼兩個查詢就能夠合併爲一個查詢,且僅須要一次表掃描了。
通過研究,row_number()函數並無這個功能,可是同時發現 over()這個窗口函數既能夠配合排名函數使用,也能夠配合聚合函數使用。例如:優化
select count(*) over() as recordCount from Goods
那麼,若是利用窗口函數over(),而後同時搭配row_number()排名函數和count()聚合函數,Sql Server的執行計劃可否在內部自動優化爲僅作一次表掃描?因而查詢改成以下:spa
select * from ( select count(*) over() as recordTotalCount, row_number() over(order by goodsId) as rowid, * from Goods ) as a where rowid >= @pageSize * (@pageIndex - 1) + 1 and rowid <= @pageSize * @pageIndex
通過測試,因爲在同一個查詢中,都使用了over()窗口函數,Sql Server在生成執行計劃時,自動優化爲僅進行一次表掃描了code