作乙個查詢的效能優化。
先清快取
dbcc dropcleanbuffersdbcc freeproccache
原查詢 前人遺留。
1declare
@total
float,@total_person
float,@times_person
float,@date
varchar(50) 2
select
@date
=convert(char(10),getdate(),120) 3
4select
@total
=sum(price*person)*
1.0from db_time t inner
join db_movie m on t.movieid=m.id inner
join db_cinema c on t.cinemaid=
c.id
5where
cast(showdate as date)=
'2014-02-27
'and t.sta=16
7select
@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
8where
cast(showdate as date)=
'2014-02-27
'and t.sta=19
10select
@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
11where
cast(showdate as date)=
'2014-02-27
'and t.sta=1;
1213
with sr as(14
select
15--
row_number() over(order by sum(price*person) desc) as 'index'
16--,17
movieid id
18,m.name name
19,m.enname
20 ,sum(price*person)*
1.0as
boxoffice
21 ,sum(price*person)*
1.0/
@total
boxpercent
22 ,sum(1
) showcount
23 ,sum(1)*
1.0/
@times_person
showpercent
24 ,sum
(person) audiencecount
25 ,sum(person)*
1.0/
@total_person
audiencepercent
26 ,cast(round(sum(price*person)*
1.0/
sum(person),0) as
int) price
27--
,sum(person)*1.0/sum(1) as test
28--
,sum(person)*1.0 as t1
29--
,sum(1) as t2
30 ,cast(round(sum(person)*
1.0/
sum(1),0) as
int) as
renci
31 ,round(cast(sum(person) as
float)/
sum(seat),4) as
shangzl
32from db_time t inner
join db_movie m on t.movieid=m.id inner
join db_cinema c on t.cinemaid=
c.id
33where
cast(showdate as date)=
'2014-02-27
'and t.sta=134
group
bymovieid,m.name,m.enname35)
3637
select
*from sr order
by boxoffice desc
執行時間18s
最開始想著是把上面3條求總量的查詢改成在一條裡完成,where條件重複多次,想想開脆改成開窗函式好了
經開窗函式改造後的查詢。
1with sr as(2
select
3distinct4--
row_number() over(order by sum(price*person) desc) as 'index'5--
,6movieid id
7,m.name name
8,m.enname
9 ,(sum(price*person) over(partition by movieid))*
1.0as
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
18from db_time t inner
join db_movie m on t.movieid=m.id inner
join db_cinema c on t.cinemaid=
c.id
19where
cast(showdate as date)=
'2014-02-27
'and t.sta=120
)21select
*from sr order
by boxoffice desc
**確實精簡不少,同樣的where子句消除了。(兩個查詢中的rownumber完全沒用,注掉了)
執行時間17s,心裡隱隱期待的是查詢時間有明顯減少,實際查詢時間在誤差範圍內,基本未變化,看來開發開窗函式的目的不是為效能提公升,而是為了方便開發人員編寫查詢**,減少查詢難度,提高查詢可讀性。
查詢計畫有很大變化,經開窗函式改造後的查詢計畫,多了很多「表假離線」的執行步驟
但兩種查詢最耗時的依然是97%聚集索引掃瞄(表上只有id的自增聚集索引)
rank 開窗函式 排序類開窗函式
1,row number over 排序,連續 select score,row number over from sc 按原始 的成績順序進行排序 原始 成績順序 先將分數從大到小排序,分數相同,排名不同 select score,row number over order by score fr...
oracle開窗函式
1.使用row number分頁,查詢第1 10條資料 select t.custid,t.companyname,t.address,t.city from select row number over order by custid as rownum,custid,companyname,ad...
開窗函式簡介
比如我們想查詢每個工資小於5000元的員工資訊 城市以及年齡 並且在每行中都顯示所有工資小於5000元的員工個數,執行下面的sql語句 這個語句顯然是錯誤的,因為count 是聚合函式,然後fname和fage欄位沒有包含分組裡面。那麼,這樣寫呢?sql view plain copy select...