SQL優化-索引 (二)結合實際,談索引使用的誤區

(三)結合實際,談索引使用的誤區

  理論的目的是應用。雖然我們剛纔列出了何時應使用聚集索引或非聚集索引,但在實踐中以上規則卻很容易被忽視或不能根據實際情況進行綜合分析。下面我們將根據在實踐中遇到的實際問題來談一下索引使用的誤區,以便於大家掌握索引建立的方法。

  1、主鍵就是聚集索引

  這種想法筆者認爲是極端錯誤的,是對聚集索引的一種浪費。雖然SQL SERVER默認是在主鍵上建立聚集索引的。

  通常,我們會在每個表中都建立一個ID列,以區分每條數據,並且這個ID列是自動增大的,步長一般爲1。我們的這個辦公自動化的實例中的列Gid就是如此。此時,如果我們將這個列設爲主鍵,SQL SERVER會將此列默認爲聚集索引。這樣做有好處,就是可以讓您的數據在數據庫中按照ID進行物理排序,但筆者認爲這樣做意義不大。

  顯而易見,聚集索引的優勢是很明顯的,而每個表中只能有一個聚集索引的規則,這使得聚集索引變得更加珍貴。

  從我們前面談到的聚集索引的定義我們可以看出,使用聚集索引的最大好處就是能夠根據查詢要求,迅速縮小查詢範圍,避免全表掃描。在實際應用中,因爲ID號是自動生成的,我們並不知道每條記錄的ID號,所以我們很難在實踐中用ID號來進行查詢。這就使讓ID號這個主鍵作爲聚集索引成爲一種資源浪費。其次,讓每個ID號都不同的字段作爲聚集索引也不符合“大數目的不同值情況下不應建立聚合索引”規則;當然,這種情況只是針對用戶經常修改記錄內容,特別是索引項的時候會負作用,但對於查詢速度並沒有影響。

  在辦公自動化系統中,無論是系統首頁顯示的需要用戶簽收的文件、會議還是用戶進行文件查詢等任何情況下進行數據查詢都離不開字段的是“日期”還有用戶本身的“用戶名”。

  通常,辦公自動化的首頁會顯示每個用戶尚未簽收的文件或會議。雖然我們的where語句可以僅僅限制當前用戶尚未簽收的情況,但如果您的系統已建立了很長時間,並且數據量很大,那麼,每次每個用戶打開首頁的時候都進行一次全表掃描,這樣做意義是不大的,絕大多數的用戶1個月前的文件都已經瀏覽過了,這樣做只能徒增數據庫的開銷而已。事實上,我們完全可以讓用戶打開系統首頁時,數據庫僅僅查詢這個用戶近3個月來未閱覽的文件,通過“日期”這個字段來限制表掃描,提高查詢速度。如果您的辦公自動化系統已經建立的2年,那麼您的首頁顯示速度理論上將是原來速度8倍,甚至更快。

  在這裏之所以提到“理論上”三字,是因爲如果您的聚集索引還是盲目地建在ID這個主鍵上時,您的查詢速度是沒有這麼高的,即使您在“日期”這個字段上建立的索引(非聚合索引)。下面我們就來看一下在1000萬條數據量的情況下各種查詢的速度表現(3個月內的數據爲25萬條):

  (1)僅在主鍵上建立聚集索引,並且不劃分時間段:

  Select gid,fariqi,neibuyonghu,title from tgongwen

  用時:128470毫秒(即:128秒)

  (2)在主鍵上建立聚集索引,在fariq上建立非聚集索引:

  select gid,fariqi,neibuyonghu,title from Tgongwen

  where fariqi> dateadd(day,-90,getdate())

  用時:53763毫秒(54秒)

  (3)將聚合索引建立在日期列(fariqi)上:

  select gid,fariqi,neibuyonghu,title from Tgongwen

  where fariqi> dateadd(day,-90,getdate())

  用時:2423毫秒(2秒)

  雖然每條語句提取出來的都是25萬條數據,各種情況的差異卻是巨大的,特別是將聚集索引建立在日期列時的差異。事實上,如果您的數據庫真的有1000萬容量的話,把主鍵建立在ID列上,就像以上的第1、2種情況,在網頁上的表現就是超時,根本就無法顯示。這也是我摒棄ID列作爲聚集索引的一個最重要的因素。

  得出以上速度的方法是:在各個select語句前加:

  declare @d datetime

  set @d=getdate()

  並在select語句後加:

  select [語句執行花費時間(毫秒)]=datediff(ms,@d,getdate())

 
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章