人們在使用
sql時往往會陷入乙個誤區,即太關注於所得的結果是否正確,而忽略了不同的實現方法之間可能存在的效能差異,這種效能差異在大型的或是複雜的資料庫環境中
(如聯機事務處理
oltp
或決策支援系統
dss)
中表現得尤為明顯。筆者在工作實踐中發現,不良的
sql往往來自於不恰當的索引設計、不充份的連線條件和不可優化的
where
子句。在對它們進行適當的優化後,其執行速度有了明顯地提高
!下面我將從這三個方面分別進行總結
: 人們在使用
sql時往往會陷入乙個誤區,即太關注於所得的結果是否正確,而忽略了不同的實現方法之間可能存在的效能差異,這種效能差異在大型的或是複雜的資料庫環境中
(如聯機事務處理
oltp
或決策支援系統
dss)
中表現得尤為明顯。筆者在工作實踐中發現,不良的
sql往往來自於不恰當的索引設計、不充份的連線條件和不可優化的
where
子句。在對它們進行適當的優化後,其執行速度有了明顯地提高
!下面我將從這三個方面分別進行總結
:為了更直觀地說明問題,所有例項中的
sql執行時間均經過測試,不超過
1秒的均表示為
(< 1秒)
。測試環境
--主機
:hp lh ii
主頻:330mhz
記憶體:128
兆作業系統
:operserver5.0.4
資料庫:sybase11.0.3
一、不合理的索引設計例:
表record
有620000
行,試看在不同的索引下,下面幾個
sql的運**況:1.
在date
上建有一非個群集索引
select count(*) from record where date >
'19991201' and date < '19991214'and amount >
2000 (25秒)
select date,sum(amount) from record group by date
(55秒
)select count(*) from record where date >
'19990901' and place in ('bj','sh') (27秒)
分析:date
上有大量的重複值,在非群集索引下,資料在物理上隨機存放在資料頁上,在範圍查詢時,必須執行一次表掃瞄才能找到這一範圍內的全部行。2.在
date
上的乙個群集索引
select count(*) from record where date >
'19991201' and date < '19991214' and amount >
2000 (14
秒)select date,sum(amount) from record group by date(28
秒)select count(*) from record where date >
'19990901' and place in ('bj','sh')(14
秒)
分析:在群集索引下,資料在物理上按順序在資料頁上,重複值也排列在一起,因而在範圍查詢時,可以先找到這個範圍的起末點,且只在這個範圍內掃瞄資料頁,避免了大範圍掃瞄,提高了查詢速度。3.在
place
,date
,amount
上的組合索引
select count(*) from record where date >
'19991201' and date < '19991214' and amount >
2000 (26
秒)select date,sum(amount) from record group by date(27
秒)select count(*) from record where date >
'19990901' and place in ('bj', 'sh')
(< 1
秒)
分析:這是乙個不很合理的組合索引,因為它的前導列是
place
,第一和第二條
sql沒有引用
place
,因此也沒有利用上索引
;第三個
sql使用了
place
,且引用的所有列都包含在組合索引中,形成了索引覆蓋,所以它的速度是非常快的。4.在
date
,place
,amount
上的組合索引
select count(*) from record where date >
'19991201' and date < '19991214' and amount >
2000(< 1秒)
select date,sum(amount) from record group by date(11
秒)select count(*) from record where date >
'19990901' and place in ('bj','sh')
(< 1
秒)
分析:這是乙個合理的組合索引。它將
date
作為前導列,使每個
sql都可以利用索引,並且在第一和第三個
sql中形成了索引覆蓋,因而效能達到了最優。
5.總結
:預設情況下建立的索引是非群集索引,但有時它並不是最佳的
;合理的索引設計要建立在對各種查詢的分析和**上。一般來說:①
.有大量重複值、且經常有範圍查詢
(between, >,<
,>=,< =)
和order by
、group by
發生的列,可考慮建立群集索引;②
.經常同時訪問多列,且每列都含有重複值可考慮建立組合索引;③
.組合索引要盡量使關鍵查詢形成索引覆蓋,其前導列一定是使用最頻繁的列。
二、不充份的連線條件:例:
表card
有7896
行,在card_no
上有乙個非聚集索引,表
account
有191122
行,在account_no
上有乙個非聚集索引,試看在不同的表連線條件下,兩個
sql的執**況
:select sum(a.amount) from account a,
card b where a.card_no = b.card_no(20
秒)
將sql改為:
select sum(a.amount) from account a,
card b where a.card_no = b.card_no and a.
account_no=b.account_no
(< 1
秒)
分析:在第乙個連線條件下,最佳查詢方案是將
account
作外層表,
card
作內層表,利用
card
上的索引,其
i/o次數可由以下公式估算為
:外層表
account
上的22541頁+(
外層表account
的191122行*
內層表card
上對應外層表第一行所要查詢的3頁
)=595907
次i/o
在第二個連線條件下,最佳查詢方案是將
card
作外層表,
account
作內層表,利用
account
上的索引,其
i/o次數可由以下公式估算為
:外層表
card
上的1944頁+(
外層表card
的7896行*
內層表account
上對應外層表每一行所要查詢的4頁
)= 33528
次i/o
可見,只有充份的連線條件,真正的最佳方案才會被執行。總結:
1.多表操作在被實際執行前,查詢優化器會根據連線條件,列出幾組可能的連線方案並從中找出系統開銷最小的最佳方案。連線條件要充份考慮帶有索引的表、行數多的表
;內外表的選擇可由公式
:外層表中的匹配行數
*內層表中每一次查詢的次數確定,乘積最小為最佳方案。
2.檢視執行方案的方法
-- 用
set showplanon
,開啟showplan
選項,就可以看到連線順序、使用何種索引的資訊
;想看更詳細的資訊,需用
sa角色執行
如何讓你的SQL執行得更快
一 不合理的索引 例 表record有620000行,試看在不同的索引下,下面幾個 sql的運 況 1.在date上建有一非個群集索引 selectcount fromrecordwheredate 19991201 anddate 19991214 andamount 2000 25秒 selec...
加入sql標籤,讓sql語句更快的執行
原本的sql語句執行 select from 表單 這種方式會獲取表中所有字段,專案大時會特別的慢 select from video where id 咱們在查詢之前插入sql標籤 sql標籤中的id務必與之後include中的refid一致 id,title 新增完sql標籤以後 標籤內部只有i...
如何讓win10系統執行更快
電腦執行的速度主要看硬體和軟體的配合使用,但是硬體從電腦買來的時候基本上是固定了的。除非對硬體進行公升級。在硬體不變的前提下如何讓電腦執行快一點的呢?下面以win10為例,教你們設定兩個地方,讓win10執行得更加快速點,跑起來更加溜。方法步驟 設定win10為最佳效能模式 設定win10電源模式為...