今天因工作需要改了个查询,开窗函数的使用,但实际也没觉得快多少。

作一个查询的性能优化。

DBCC DROPCLEANBUFFERS

DBCC FREEPROCCACHE

清缓存

原查询 前人遗留。

  declare @total float,@total_person float,@times_person float,@date varchar(50) 

                        select @date=CONVERT(char(10),GETDATE(),120) 



                        select @total=sum(price*person)*1.0 from db_time t inner join db_movie m on t.movieid=m.id inner join db_cinema c on t.cinemaid=c.id 

                        where CAST(showdate as date)='2014-02-27' and t.sta=1 



                        select @times_person=sum(1)         from db_time t inner join db_movie m on t.movieid=m.id inner join db_cinema c on t.cinemaid=c.id

                        where CAST(showdate as date)='2014-02-27' and t.sta=1 



                        select @total_person=sum(person)    from db_time t inner join db_movie m on t.movieid=m.id inner join db_cinema c on t.cinemaid=c.id

                        where CAST(showdate as date)='2014-02-27' and t.sta=1 ;



                        with sr as(

                        select 

                        --ROW_NUMBER() over(order by SUM(price*person) desc) as 'index'

                        --,

                        movieid id

                        ,m.name name                        

                        ,m.enname 

                        ,SUM(price*person)*1.0 as BoxOffice 

                        ,SUM(price*person)*1.0/@total BoxPercent

                        ,sum(1) ShowCount

                        ,sum(1)*1.0/@times_person ShowPercent

                        ,sum(person) AudienceCount

                        ,sum(person)*1.0/@total_person AudiencePercent

                        ,cast(round(sum(price*person)*1.0/sum(person),0) as int) Price 

                        --,sum(person)*1.0/sum(1) as test

                        --,sum(person)*1.0 as t1

                        --,sum(1) as t2

                        ,cast(round(sum(person)*1.0/sum(1),0) as int) as Renci

                        ,round(CAST(sum(person) as float)/sum(seat),4) as Shangzl 

                        from db_time t inner join db_movie m on t.movieid=m.id inner join db_cinema c on t.cinemaid=c.id

                        where CAST(showdate as date)='2014-02-27' and t.sta=1 

                        group by movieid,m.name,m.enname

                        )



                        select * from sr order by BoxOffice desc

                      
View Code

执行时间18S

最开始想着是把上面3条求总量的查询改成在一条里完成,多少能省点时间,个人看这么些重复的查询串,where条件,心里不太舒服,想想开脆改成开窗函数好了。心里隐隐期待的是查询时间大幅减少。

经开窗函数改造后的查询。

 1 with sr as(

 2                         select 

 3                         distinct

 4                         --ROW_NUMBER() over(order by SUM(price*person)  desc) as 'index'

 5                         --,

 6                         movieid id

 7                         ,m.name name                        

 8                         ,m.enname 

 9                         ,(SUM(price*person) OVER(PARTITION BY movieid))*1.0 as BoxOffice 

10                         ,(SUM(price*person) OVER(PARTITION BY movieid))*1.0/(SUM(price*person) OVER()) as BoxPercent

11                         ,sum(1) OVER(PARTITION BY movieid) as  ShowCount

12                         ,(sum(1) OVER(PARTITION BY movieid))*1.0/(sum(1) OVER()) ShowPercent

13                         ,sum(person) OVER(PARTITION BY movieid) AudienceCount

14                         ,((sum(person) OVER(PARTITION BY movieid))*1.0)/((sum(person) OVER())) AudiencePercent

15                         ,cast(round((sum(price*person) OVER(PARTITION BY movieid))*1.0/(sum(person) OVER(PARTITION BY movieid)),0) as int) Price 

16                         ,cast(round(((sum(person) OVER(PARTITION BY movieid))*1.0/(count(0) OVER(PARTITION BY movieid))),0) as int) as Renci

17                         ,round(CAST((sum(person) OVER(PARTITION BY movieid)) as float)/(sum(seat) OVER(PARTITION BY movieid)),4) as Shangzl 

18                         from db_time t inner join db_movie m on t.movieid=m.id inner join db_cinema c on t.cinemaid=c.id

19                         where CAST(showdate as date)='2014-02-27' and t.sta=1 

20                         )

21                         select * from sr order by BoxOffice desc
View Code

代码确实精简不少,同样的where子句消除了。(两个查询中的rownumber完全没用,注掉了)

但执行时间17S,速度并未明显提升。(个人感觉,开发开窗函数的目的不是性能提升,而是为了方便开发人员编写查询代码,有误请指出)

查询计划有很大变化,经开窗函数改造后的查询计划,多了很多“表假脱机”的执行步骤

但两种查询最耗时的依然是97%聚集索引扫描(表上只有id的自增聚集索引)

待我加完索引,按时分区后再看结果。

 

个人猜想,提升并不大,统计总的数据量,是会走聚集扫描的。索引和分区唯一有帮助的是找出where条件对应的行,放到开窗函数里,这部分的统计,但建了个索引SQL未必会走。

写在完全的一个查询里明确指定索引,全表的统计扫描又是个问题。

==看结果吧,看where部分会不会自动走索引。

再看 明确指定索引,对全表扫描有什么影响(这部分应该还是走全表聚集扫描)

 

你可能感兴趣的:(工作)