在项目中遇见当数据量达到千万级的时候分页与查询数据出现性能问题,时常出现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 是数据的分区取数,用于给结果集分组,如果没有指定那么它把整个结果集作为一个分组,它和聚合函数不同的地方在于它能够返回一个分组中的多条记录,而聚合函数一般只有一个反映统计值的记录。