SQL開發中容易忽視的一些小地方 六

2021-09-06 14:29:44 字數 3080 閱讀 5582

原文:

sql開發中容易忽視的一些小地方(六)

事由:今天在北京俱樂部msn群中和網友討論了關於索引對delete的影響問題,事後感覺非常汗顏,因為我的隨口導致錯誤連篇。大致話題是這樣的,並非原話:

[討論:]delete course where classid=500001 classid上沒有建立任何索引,為了提高刪除效率,如果在classid上建立乙個非聚集索引會不會提高刪除的效率呢?  

我當時的觀點:不能。

我當時的理由:資料庫在執行刪除時,如果在classid上建立了非聚集索引,首先按這個非聚集索引查詢資料,找到索引行後,根據索引行後面帶的聚集索引位址最後找到真正的物理資料行,並且執行刪除,這個過程看起來沒有作用,只能建立聚集索引來提高刪除效率,因為如果classid是聚集索引,那麼直接聚集索引刪除,此時的效率最高。

下班後對這個話題再次想了下,覺的自己的觀點都自相矛盾,既然知道刪除時,會在條件列上試圖應用已經存在的索引,那麼為什麼建立非聚集索引會無效呢?如果表的資料相當大,classid上如果沒有任何索引,查詢資料時就要執行表掃瞄,而表掃瞄的速度是相當慢的,為此為了證明下這個問題,我特意做了乙個示意性的實驗。

建立兩個表course 和course2,建立語句如下,它們唯一的區別就在於索引,course表中classid上建立了非聚集索引,而course2上沒有建立任何索引

create table [dbo].[course](

[id] [

int] identity(1,

1) not null,

[scoursename] [nchar](

10) collate chinese_prc_ci_as null,

[classid] [

int] null,

constraint [pk_ckh] primary key clustered 

([id] asc

)with (ignore_dup_key 

=off) on [primary]

) on [primary]

--建立索引

create index ix_classid

on course(classid)

create table [dbo].[course2](

[id] [

int] identity(1,

1) not null,

[scoursename] [nchar](

10) collate chinese_prc_ci_as null,

[classid] [

int] null,

constraint [pk_ckh2] primary key clustered 

([id] asc

)with (ignore_dup_key 

=off) on [primary]

) on [primary]

實驗過程:

第一步:分別給兩個表插入相當的資料1000行,然後刪除第500條記錄。

delete course

where

classid

=500

delete course2

where

classid

=500

執行計畫圖如下:我們可以看到在執行刪除時,資料庫分為三部分:

1:查詢到要刪除的資料行;

2:包含乙個top操作。

3:執行聚集索引刪除。

區別一:由於course表的classid上建立了索引,所以查詢時按pk_classid來查詢,course2表的classid由於沒有任何的索引,為了查詢到要刪除的資料行,就只能按聚集索引查詢,此時實際上是全表掃瞄。

區別二:系統開銷不同,讓人意外的是,結果表明好像白天的觀點是正確的,建立了索引的coure表在開銷上比沒有建立索引的course2還大一點。

分析區別二的原因:我們來看下聚集索引刪除的具體內容,下面是在條件列classid上建立了非聚集索引的表course表在發生刪除時的執行計畫圖,它在刪除後需要維護索引pk_classid,占用部分的系統開銷。而沒有建立索引的表course2由於沒有索引維護的額外開銷,所以反而佔優勢。

第二步:分別給兩個表插入相當的資料10000行,然後刪除第5000條記錄。

區別同第一步。難道我的觀點真的正確?

第三步:分別給兩個表插入相當的資料100000行,然後刪除第50000條記錄。執行計畫圖如下:

區別一:同前兩步的區別一。

區別二:系統開銷不同,此時會發現建立了索引的course表在開銷上佔5%,而沒有建立索引的course2表佔了95%,這可是10倍的區別啊。

第四步:分別給兩個表插入相當的資料1000000行,然後刪除第500000條記錄。

區別同第三步。

總結:當刪除語句的條件列沒有建立索引時分兩種情況:

第一:資料量較小,我測試時在10000以下,此時兩者的差別不大,反而會因為建立了索引而引起磁碟開銷。開銷差距不大是因為資料量小時,即使全表掃瞄速度也不慢,此時索引的優勢並不明顯。

第二:資料量較大,我測試時在100000以上,此時兩者的差別較大。條件列建立了索引的表明顯效率高。

第三:歸根結底,系統的主要開銷還是在刪除的第一步,查詢資料行上。能更快查詢到刪除行的方案效率最高。

SQL開發中容易忽視的一些小地方 一

sql開發中容易忽視的一些小地方 一 寫此系列文章緣由 做開發三年來 b s 發現基於web 架構的專案技術主要分兩大方面 第一 c 它是程式的基礎,也可是其它開發語言,沒有開發語言也就不存在應用程式.第二 資料庫,現在是資訊化世界,大多數資訊都可以通過資料庫儲存來交換資訊.常與應用程式互相交流資訊...

SQL開發中容易忽視的一些小地方 一

原文 sql開發中容易忽視的一些小地方 一 寫此系列文章緣由 做開發三年來 b s 發現基於web 架構的專案技術主要分兩大方面 第一 c 它是程式的基礎,也可是其它開發語言,沒有開發語言也就不存在應用程式.第二 資料庫,現在是資訊化世界,大多數資訊都可以通過資料庫儲存來交換資訊.常與應用程式互相交...

SQL開發中容易忽視的一些小地方 一

原文 sql開發中容易忽視的一些小地方 一 寫此系列文章緣由 做開發三年來 b s 發現基於web 架構的專案技術主要分兩大方面 第一 c 它是程式的基礎,也可是其它開發語言,沒有開發語言也就不存在應用程式.第二 資料庫,現在是資訊化世界,大多數資訊都可以通過資料庫儲存來交換資訊.常與應用程式互相交...