SQLServer效能優化之活用臨時表
繼續調優,今天上午分析了以下一條處理時間達40秒的SQL語句
select *
from table
where T_table_ID in
(
select distinct s.t_table_id
from
(
select distinct a.t_table_id,a.bt
from
(select left(bt,4) as bbt,* from table where fsrq>getdate()-1 and gkbz=1 and scbz=0) a,
(select distinct left(bt,4) as bbt,t_table_id from table where fsrq>getdate()-1 and gkbz=1 and scbz=0) b
where b.bbt like a.bbt and a.t_table_id<>b.t_table_id
and a.bbt not like '%aaaa%' and a.bbt not like '%bbbb%' and a.bbt not like '%cccc%'
and a.bbt not like '%dddd%' and a.bbt not like '%eeee%' and a.bbt not like '%ffff%'
and a.bbt not like '%aaaa%' and a.bbt not like '%bbbb%' and a.bbt not like '%cccc%'
and a.bbt not like '%dddd%' and a.bbt not like '%eeee%' and a.bbt not like '%ffff%'
-- order by a.bt
union all
select distinct a.t_table_id,a.bt
from
(select right(bt,5) as bbt,* from table where fsrq>getdate()-1 and gkbz=1 and scbz=0) a,
(select distinct right(bt,5) as bbt,t_table_id from table where fsrq>getdate()-1 and gkbz=1 and scbz=0) b
where b.bbt like a.bbt and a.t_table_id<>b.t_table_id
and a.bbt not like '%aaaa%' and a.bbt not like '%bbbb%' and a.bbt not like '%cccc%'
and a.bbt not like '%dddd%' and a.bbt not like '%eeee%' and a.bbt not like '%ffff%'
and a.bbt not like '%aaaa%' and a.bbt not like '%bbbb%' and a.bbt not like '%cccc%'
and a.bbt not like '%dddd%' and a.bbt not like '%eeee%' and a.bbt not like '%ffff%'
and a.bbt not like '%'+(select right(convert(varchar(10),getdate()-1,20),2)+')') +'%'
and b.bbt not like '%'+(select right(convert(varchar(10),getdate()-1,20),2)+')') +'%'
) s
)order by bt
基本上可以認為是對同一張表的反覆操作,而且語句中夾雜了太多的全表掃描
SQLServer的執行計劃我個人認為圖形化介面固然是好,但是有些時候對於量化的I/O,CPU,COST輸出卻很不直觀,此外像該SQL這樣的執行計劃,估計1600*1200的整個螢幕都無法顯示,可以認為基本是沒法看的
只能將SQL分解成若干小SQL,逐步找到瓶頸所在,例如
select left(bt,4) as bbt,* from table where fsrq>getdate()-1 and gkbz=1 and scbz=0
select distinct left(bt,4) as bbt,t_table_id from table where fsrq>getdate()-1 and gkbz=1 and scbz=0
這兩個語句的執行都非常快,並且結果集也比較小,但是兩條語句合併後並加上相關條件就非常緩慢。
乾脆直接構建兩個臨時表,反正都是全表掃描,用兩個臨時表做相互的join,測試之後發現只需要1秒
再構建下面的兩個SQL臨時表,也做同樣的測試
最後再全部合併到一起進行測試,發現也就是2~3秒
實際上還可以再優化一些臨時表的構建,但效果達到了也就不願意嘗試了
也嘗試過用CTE,不過似乎效果不佳
以下為優化後的SQL樣例
/*
with temp1 as
(select left(bt,4) as bbt,* from table where fsrq>getdate()-1 and gkbz=1 and scbz=0),
temp2 as
(select distinct left(bt,4) as bbt,t_table_id from table where fsrq>getdate()-1 and gkbz=1 and scbz=0),
temp3 as
(select left(bt,5) as bbt,* from table where fsrq>getdate()-1 and gkbz=1 and scbz=0),
temp4 as
(select distinct left(bt,5) as bbt,t_table_id from table where fsrq>getdate()-1 and gkbz=1 and scbz=0)
*/
print convert(varchar,getdate(),9)
select left(bt,4) as bbt,* into #temp1 from table where fsrq>getdate()-1 and gkbz=1 and scbz=0
select distinct left(bt,4) as bbt,t_table_id into #temp2 from table where fsrq>getdate()-1 and gkbz=1 and scbz=0
select right(bt,5) as bbt,* into #temp3 from table where fsrq>getdate()-1 and gkbz=1 and scbz=0
select distinct right(bt,5) as bbt,t_table_id into #temp4 from table where fsrq>getdate()-1 and gkbz=1 and scbz=0
select
(select ms from xtclb where dm=lmxz and lb in (130,131) ) as '欄目選擇',
bt,mtly,czy
from table
where T_table_ID in
(
select distinct s.t_table_id
from
(
select distinct a.t_table_id,a.bt
from
#temp1 a,
#temp2 b
where b.bbt like a.bbt and a.t_table_id<>b.t_table_id
and a.bbt not in ('aaaa','bbbb','cccc','dddd','eeee','ffff')
and b.bbt not in ('aaaa','bbbb','cccc','dddd','eeee','ffff')
union all
select distinct a.t_table_id,a.bt
from
#temp3 a,
#temp4 b
where b.bbt like a.bbt and a.t_table_id<>b.t_table_id
and a.bbt not like '%aaaa%' and a.bbt not like '%bbbb%' and a.bbt not like '%cccc%'
and a.bbt not like '%dddd%' and a.bbt not like '%eeee%' and a.bbt not like '%ffff%'
and a.bbt not like '%'+(select right(convert(varchar(10),getdate()-1,20),2)+')') +'%'
and a.bbt not like '%aaaa%' and a.bbt not like '%bbbb%' and a.bbt not like '%cccc%'
and a.bbt not like '%dddd%' and a.bbt not like '%eeee%' and a.bbt not like '%ffff%'
and b.bbt not like '%'+(select right(convert(varchar(10),getdate()-1,20),2)+')') +'%'
) s
)order by bt
--OPTION (loop join);
--34
print convert(varchar,getdate(),9)
/*
drop table #temp1
drop table #temp2
drop table #temp3
drop table #temp4
*/
select *
from table
where T_table_ID in
(
select distinct s.t_table_id
from
(
select distinct a.t_table_id,a.bt
from
(select left(bt,4) as bbt,* from table where fsrq>getdate()-1 and gkbz=1 and scbz=0) a,
(select distinct left(bt,4) as bbt,t_table_id from table where fsrq>getdate()-1 and gkbz=1 and scbz=0) b
where b.bbt like a.bbt and a.t_table_id<>b.t_table_id
and a.bbt not like '%aaaa%' and a.bbt not like '%bbbb%' and a.bbt not like '%cccc%'
and a.bbt not like '%dddd%' and a.bbt not like '%eeee%' and a.bbt not like '%ffff%'
and a.bbt not like '%aaaa%' and a.bbt not like '%bbbb%' and a.bbt not like '%cccc%'
and a.bbt not like '%dddd%' and a.bbt not like '%eeee%' and a.bbt not like '%ffff%'
-- order by a.bt
union all
select distinct a.t_table_id,a.bt
from
(select right(bt,5) as bbt,* from table where fsrq>getdate()-1 and gkbz=1 and scbz=0) a,
(select distinct right(bt,5) as bbt,t_table_id from table where fsrq>getdate()-1 and gkbz=1 and scbz=0) b
where b.bbt like a.bbt and a.t_table_id<>b.t_table_id
and a.bbt not like '%aaaa%' and a.bbt not like '%bbbb%' and a.bbt not like '%cccc%'
and a.bbt not like '%dddd%' and a.bbt not like '%eeee%' and a.bbt not like '%ffff%'
and a.bbt not like '%aaaa%' and a.bbt not like '%bbbb%' and a.bbt not like '%cccc%'
and a.bbt not like '%dddd%' and a.bbt not like '%eeee%' and a.bbt not like '%ffff%'
and a.bbt not like '%'+(select right(convert(varchar(10),getdate()-1,20),2)+')') +'%'
and b.bbt not like '%'+(select right(convert(varchar(10),getdate()-1,20),2)+')') +'%'
) s
)order by bt
基本上可以認為是對同一張表的反覆操作,而且語句中夾雜了太多的全表掃描
SQLServer的執行計劃我個人認為圖形化介面固然是好,但是有些時候對於量化的I/O,CPU,COST輸出卻很不直觀,此外像該SQL這樣的執行計劃,估計1600*1200的整個螢幕都無法顯示,可以認為基本是沒法看的
只能將SQL分解成若干小SQL,逐步找到瓶頸所在,例如
select left(bt,4) as bbt,* from table where fsrq>getdate()-1 and gkbz=1 and scbz=0
select distinct left(bt,4) as bbt,t_table_id from table where fsrq>getdate()-1 and gkbz=1 and scbz=0
這兩個語句的執行都非常快,並且結果集也比較小,但是兩條語句合併後並加上相關條件就非常緩慢。
乾脆直接構建兩個臨時表,反正都是全表掃描,用兩個臨時表做相互的join,測試之後發現只需要1秒
再構建下面的兩個SQL臨時表,也做同樣的測試
最後再全部合併到一起進行測試,發現也就是2~3秒
實際上還可以再優化一些臨時表的構建,但效果達到了也就不願意嘗試了
也嘗試過用CTE,不過似乎效果不佳
以下為優化後的SQL樣例
/*
with temp1 as
(select left(bt,4) as bbt,* from table where fsrq>getdate()-1 and gkbz=1 and scbz=0),
temp2 as
(select distinct left(bt,4) as bbt,t_table_id from table where fsrq>getdate()-1 and gkbz=1 and scbz=0),
temp3 as
(select left(bt,5) as bbt,* from table where fsrq>getdate()-1 and gkbz=1 and scbz=0),
temp4 as
(select distinct left(bt,5) as bbt,t_table_id from table where fsrq>getdate()-1 and gkbz=1 and scbz=0)
*/
print convert(varchar,getdate(),9)
select left(bt,4) as bbt,* into #temp1 from table where fsrq>getdate()-1 and gkbz=1 and scbz=0
select distinct left(bt,4) as bbt,t_table_id into #temp2 from table where fsrq>getdate()-1 and gkbz=1 and scbz=0
select right(bt,5) as bbt,* into #temp3 from table where fsrq>getdate()-1 and gkbz=1 and scbz=0
select distinct right(bt,5) as bbt,t_table_id into #temp4 from table where fsrq>getdate()-1 and gkbz=1 and scbz=0
select
(select ms from xtclb where dm=lmxz and lb in (130,131) ) as '欄目選擇',
bt,mtly,czy
from table
where T_table_ID in
(
select distinct s.t_table_id
from
(
select distinct a.t_table_id,a.bt
from
#temp1 a,
#temp2 b
where b.bbt like a.bbt and a.t_table_id<>b.t_table_id
and a.bbt not in ('aaaa','bbbb','cccc','dddd','eeee','ffff')
and b.bbt not in ('aaaa','bbbb','cccc','dddd','eeee','ffff')
union all
select distinct a.t_table_id,a.bt
from
#temp3 a,
#temp4 b
where b.bbt like a.bbt and a.t_table_id<>b.t_table_id
and a.bbt not like '%aaaa%' and a.bbt not like '%bbbb%' and a.bbt not like '%cccc%'
and a.bbt not like '%dddd%' and a.bbt not like '%eeee%' and a.bbt not like '%ffff%'
and a.bbt not like '%'+(select right(convert(varchar(10),getdate()-1,20),2)+')') +'%'
and a.bbt not like '%aaaa%' and a.bbt not like '%bbbb%' and a.bbt not like '%cccc%'
and a.bbt not like '%dddd%' and a.bbt not like '%eeee%' and a.bbt not like '%ffff%'
and b.bbt not like '%'+(select right(convert(varchar(10),getdate()-1,20),2)+')') +'%'
) s
)order by bt
--OPTION (loop join);
--34
print convert(varchar,getdate(),9)
/*
drop table #temp1
drop table #temp2
drop table #temp3
drop table #temp4
*/
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/6517/viewspace-669618/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 資料庫優化之臨時表優化資料庫優化
- Oracle效能優化:收縮臨時表空間Oracle優化
- ORACLE臨時表和SQLSERVER臨時表異同OracleSQLServer
- SQLServer臨時表的使用SQLServer
- SQLServer表變數和臨時表系列之概念篇SQLServer變數
- SQLServer效能優化之查詢提示SQLServer優化
- SQLServer臨時表和表變數系列之踢館篇SQLServer變數
- MySQL臨時表的優化方案MySql優化
- Oracle臨時表 優化查詢速度Oracle優化
- SQLServer效能優化之改寫SQL語句SQLServer優化
- oracle筆記整理10——效能調優之臨時表與物化檢視Oracle筆記
- SQLServer資料庫中建立臨時表SQLServer資料庫
- sqlserver中判斷表或臨時表是否存在SQLServer
- 如何優化WindowsOS使SQLServer效能最優化優化WindowsSQLServer
- SQLServer效能優化之 nolock,大幅提升資料庫查詢效能SQLServer優化資料庫
- MySQL之臨時表MySql
- SQLServer如何釋放tempdb臨時表空間SQLServer
- Sqlserver 關於臨時表和表變數的總結SQLServer變數
- MySQL資料庫效能優化之表結構優化(轉)MySql資料庫優化
- SQLSERVER 臨時表和表變數到底有什麼區別?SQLServer變數
- MySQL 效能優化之索引優化MySql優化索引
- MySQL 效能優化之SQL優化MySql優化
- 效能優化之 NSDateFormatter優化ORM
- Android效能優化篇之計算效能優化Android優化
- 【Database】Oracle10g臨時表空間的管理和優化DatabaseOracle優化
- Web效能優化之圖片優化Web優化
- 六、Android效能優化之UI卡頓分析之渲染效能優化Android優化UI
- 效能優化漫談之七:效能優化的誤區優化
- 前端效能優化之效能測試前端優化
- Android效能優化之佈局優化Android優化
- 前端效能優化之WebP前端優化Web
- oracle效能優化之--hintsOracle優化
- iOS效能優化 - APP啟動時間優化iOS優化APP
- MySQL臨時表MySql
- PostgreSQL:臨時表SQL
- oracle臨時表Oracle
- Oracle 臨時表Oracle
- 【轉載】MySQL之臨時表和記憶體表MySql記憶體