如何讓你的SQL執行得更快

2022-04-12 06:36:36 字數 4493 閱讀 4524

人們在使用

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電源模式為...