在項目中遇見當數據量達到千萬級的時候分頁與查詢數據出現性能問題,時常出現timeout現象。
要求,查詢出某個地區在某種類型下相應子類型最近一天的的報價信息,如果采用把某個地區的某種類型下的所有子類型的最近一天報價相應信息與日期放到臨時表中,然后再歷史報價表中查詢相應的最近日期,會出現timeout:
現在做如下修改:

1 CREATE PROC [dbo].[usp_GetHistoryPrices] 2 @AreaID INT, 3 @TypeID INT 4 AS 5 BEGIN 6 SET NOCOUNT ON; 7 WITH temp_1 AS( 8 SELECT ss.*,ROW_NUMBER() OVER(PARTITION BY AreaID,GoodsID Order by PriceDate DESC) AS pn FROM MD_HistoryPrices ss 9 INNER JOIN MD_Goods gg ON ss.GoodsId = gg.ID AND GG.TypeId = @TypeID AND gg.IsDelete= 0 and AreaID = @AreaID 10 ) 11 SELECT * FROM temp_1 WHERE pn=1 12 END
調用端:

1 DECLARE @AreaID INT; 2 DECLARE @TypeID INT; 3 SET @AreaID = 1; 4 SET @TypeID = 1; 5 EXEC [usp_GetHistoryPrices] @AreaID,@TypeID
此時查詢效率提高。
采用方式,針對地區和子類型進行分組,排序,同時給每個地區,子類型,報價日期進行編號,當pn=1時候就代表是相應地區與子類型最近一天的報價。
另外,Row_Number() over()時常用在分頁中。

1 CREATE PROC [dbo].[usp_Page] 2 @PageIndex INT, 3 @PageSize INT, 4 @TypeID INT, 5 @AreaID INT 6 AS 7 BEGIN 8 SET NOCOUNT ON; 9 WITH TEMP_1 AS( 10 SELECT ss.*,ROW_NUMBER () OVER( ORDER BY ss.ID DESC) AS pn FROM MD_HistoryPrices ss INNER JOIN MD_Goods gg ON gg.TypeId =@TypeID 11 AND gg.ID =ss.GoodsId AND ss.AreaID=@AreaID 12 ) 13 SELECT * FROM TEMP_1 WHERE pn>@PageIndex*@PageSize AND pn<=(@PageIndex +1)*@PageSize 14 END 15
在使用 row_number() over()函數時候,over()里頭的分組以及排序的執行晚於 where group by order by 的執行。
partition by 是數據的分區取數,用於給結果集分組,如果沒有指定那么它把整個結果集作為一個分組,它和聚合函數不同的地方在於它能夠返回一個分組中的多條記錄,而聚合函數一般只有一個反映統計值的記錄。