SQL中的索引

2021-09-12 14:59:31 字數 4419 閱讀 2386

今天面試問到乙個東西——索引,我懵逼了,只知道這東西可以進行sql優化,但是根本不知道其中的原理。。。

原文:(

實際上,索引可以理解成一種特殊的目錄。微軟的sql server提供了兩種索引:聚集索引(也可稱為聚類索引、簇集索引)和非聚集索引(當然也可以稱為非聚類索引、非簇集索引)。下面,我們舉例來說明一下聚集索引和非聚集索引的區別:

其實,我們的漢語字典正文本身就是乙個聚集索引,我們要查「暗」字,就會很自然地翻開字典的前幾頁,因為對於「暗」的拼音來說「an」,而對於字典的排列順序來說是按照拼音的「a-z」順序排列的,那麼「暗」這個字很明顯就是從字典的前面部分了。如果你翻完了字典的「a」部分,還沒有找到「暗」字,那麼可以確定的認為字典中「暗」字不存在;那麼再次舉例來說,我們查詢「炸」字,根據拼音來查詢「zha」,直接從字典後半部分查詢,如果找遍了「z」拼音部分,還是沒有找到,那麼就可以認為「炸」字不存在於詞典中。所以可以認為,在字典的正文就是一種目錄,我們可以不通過去查詢其他目錄來找到我們所需要查詢的內容。所以對於此:正文內容,我們把其按照一定規則排序的目錄稱之為「聚集索引」。

那麼如果說:我們知道某個字的寫法,但是我們不知道它是怎麼讀了?這個時候我們就可以通過偏旁部首去進行乙個查詢了,然後直接通過頁碼直接找到我們要查詢的字。但是對於通過「部首目錄」和「檢字表」而查詢到的字的排序並不是正文排序的方式,比如說查詢「張」字,可以知道「張」字的頁碼是672頁,而在「檢字表」中「張」字上面的「馳」字頁碼是63頁,「張」字下面的「弩」字頁碼是390頁。絲毫不連續。很顯然,它們並不是真的存在於「張」字的上下方,現在您看到的連續的「馳、張、弩」三個字實際上就他們在非聚集索引中的排序方式,是字典證明中的字在非聚集索引中的對映。我們可以通過這種方式來找到我們所需要的字,但是它需要兩個過程,先找到目錄中的結果,然後再翻到我們所需要的頁面。我們把這種目錄純粹稱之為目錄,正文純粹是正文的排序方式稱為「非聚集索引」。

通過乙個字典的查詢方式,可以簡單的理解一下什麼叫非聚集索引和聚集索引了。那麼我們就可以很容易的理解每張表只能選擇非聚集索引或聚集索引其一。

我們可以通過第一小節中的聚集索引和非聚集索引的介紹來理解記憶上表。比如:返回某一範圍內的資料中的一項資料。比如:我們的乙個表中有乙個時間字段,恰好我們把聚合索引建立在了該字段上,這個時候我們查詢2023年1月1日到2023年12月30日之間的全部資料時,這個速度將會是很快,因為我們的這個字典正文是通過日期來進行排序的,聚類索引只需要找到要檢索的所有資料中的開頭和結尾資料就行;如果我們使用非聚集索引,那麼還要查到2023年1月2號對應的頁碼,然後再根據頁碼來查詢資料,那將是很耗時的。

今天面試筆者就是犯了嚴重的錯誤,面試官咋眼看著我,我很無奈。通常來說,我們會在每個表中建立乙個id欄位,用來區分每一條資料,而且通常來說會使用id自增長配置,每次自增為1。在前面的講解中,可以了解到聚集索引最大的好處就是建立查詢資料的乙個區間,降低查詢資料的總條數,避免全表查詢。在實際應用中,因為id是自動生成的,程式設計師並不知道每條記錄所對應的id,所以我們很難在實際應用中進行乙個id號作為查詢條件。這也讓id號作為聚集索引成為了一種資源浪費。其次,讓每個id號都有不同的字段作為聚集索引頁不符合「在大範圍數量個不同的值作為非聚集索引」規則。所以說,這種錯誤操作是針對於使用者經常修改記錄內容,特別是索引項的時候還會起到負作用,但是對於查詢速度並沒有多大的影響。

對於erp系統中來說,不管是系統中使用者所需要接收的檔案、會議還是使用者進行檔案查詢等任何情況下進行資料查詢都離不開欄位的是「日期」還有使用者本身的「使用者名稱」。

一般來說,對於erp系統的首頁都會顯示每個使用者為簽收的檔案或者會議。雖然我們的where語句可以僅僅限制當前使用者尚未簽收的條件,但是如果您的系統已經建立了很長時間,並且資料量龐大,那麼每個使用者開啟首頁的時候都進行了一次全表掃瞄,這樣做的意義不是很大,而且對於1月之前的檔案資訊,使用者已經進行處理完成了。如果說還進行乙個多餘資料查詢,只是增加了資料庫的開銷而已。所以說,我們完全可以讓使用者開啟系統首頁的時候,資料庫僅僅查詢了這個使用者近3個月的未處理的檔案就可以了。通過「時間日期」這個欄位來限制表的掃瞄條數,提高查詢速度。如果說我們所使用的辦公自動化系統,已經存在了2年的時間,那麼從理論上來講,查詢速度將是原來的8倍之上。

當然如果說不從應用場景來使用聚集索引和非聚集索引的使用字段,那麼查詢速度還是得不到提公升的,即使在「時間日期」這個欄位上建立的非聚集索引。那麼索引還是得不到提公升的。所以,歸根揭底就是一句話:盡量避免在id自增長上建立索引。

2.【只要建立索引就可以提高查詢速度】:

在實際應用中,我們每天都會產生一些資料(500條),那麼這些資料的傳送日期都是相同的,總共資料有5000萬條,那麼這就符合「既不能絕大多數相同的資料,有不能只是極少的相同資料」的規則,所以,對於聚合索引,適當建立是由提高查詢速度的。

3.【把所有需要提高查詢速度的字段都加進聚集索引,用於提高查詢效率】

對於上面已經說到的資料查詢需要使用到索引字段「日期」還有使用者本身的「使用者名稱」。既然這兩個欄位都是如此的重要,那麼我們可以把他們合併起來,建立復合索引。

對於只使用聚集索引的起始字段作為查詢條件和使用到復合聚集索引的全部欄位的查詢速度幾乎一樣,甚至比使用上全部的復合索引字段還要略快(在查詢結果集數目一樣的情況下);而如果僅僅使用了復合聚集索引的非起始字段(只使用使用者名稱條件語句)作為查詢條件的話,這個索引是起不到任何作用的。對於使用單純的聚合索引和使用復合索引執行速度一樣是因為查詢的數目一樣。如果復合索引將所有的字段都用上,而且查詢的結果集少的話,這樣就會形成「索引覆蓋」,因而效能可以達到最優。同時,請記住:無論我們是否經常使用到聚合索引的其他字段,但其前導字段(第乙個條件字段)一定要是使用最頻繁的字段。

1.使用聚集索引比用不上聚集索引的主鍵速度要快。

2.使用聚集索引比用一般的主鍵作為order by時的執行速度要快,特別是在小資料量的情況下,(如果是資料量大,效果不上很明顯)

3.使用聚集索引內的時間段,搜尋時間會按該時間段的資料佔整個資料表的百分比成比例減少(聚集索引時間段內的資料越少,搜尋時間越快,效率越高),而且無論聚集索引使用了多少個。

4.日期字段不會因為有分秒的詳細而減慢查詢速度

關於索引的使用問題,如果使用不當,不僅不會提高檢索效率,如果過多或不當的索引配置,會導致系統效率低下。因為使用者在每張表彙總加入乙個索引,那麼資料庫就要做更多的工作。過多的索引甚至會導致索引碎片效應。

所以說,對於索引的使用問題,應當注意聚合索引的建立。

1.select * from table1 where name = 「wangji」 and tid > 10000

2.select * from table1 where tid > 10000 and name = 「wangji」

對於上面兩條語句,分析感覺是由區別的。因為對於第一條,先查詢出name為wangji的資料,然後再從這批資料查詢出tid大於10000;而第二條,先查詢出tid大於10000,然後再從這批資料查詢出name為wangji的。

其實對於這種分析是錯誤的。因為對於資料庫來說,判斷sql語句的時候,會判斷出where中查詢的條件那個索引能夠縮小表的掃瞄條數。也就是自動化判斷優先順序。

對於這種自動化操作的原理:在查詢語句分析階段,查詢優化器檢視的每個階段並決定限制需要掃瞄的資料量是否有用。如果乙個階段可以被用作乙個掃瞄引數(sarg),那麼就可以認定為該sql是可以進行乙個優化的。並且可以使用索引進行優化。

掃瞄引數:用於限制搜尋的乙個操作·,因為它通常是指定乙個特定的匹配,乙個值得範圍內的匹配或者兩個以上的條件的and連線。例如:

name = 「wangji」

age > 22

「wangji」 = name

name = 「wangji」 and age > 22

如果說乙個表示式不能滿足掃瞄引數的格式,那麼就無法實現限制範圍搜尋,那麼就變成了全表判斷是否滿足。所以乙個索引對於不滿足引數掃瞄的格式是沒有作用的。

那麼說對於sql的編寫,哪些會造成全表搜尋呢?(以下錯誤示範)

使用模糊查詢like :name like 「%際」

使用or查詢:name = 「wangji」 or age > 22

使用非操作符、函式引起的不滿足掃瞄引數的:如:not、!=、、!、not exists、 not in、not like等,另外還有函式。例如:

name like 「%際」

abs < 5000

盡量避免in的作用相當於or『』

not也盡量避免

exists和in的執行效率一樣,也盡量避免使用

使用函式charindex()和上面使用萬用字元%的模糊查詢like執行效率一樣

union並比絕對比or執行效率高

需要查詢多少字段內容就查詢多少字段內容,避免使用*所有字段內容獲取

count(*)執行效率不會比count(欄位名)慢

order by按聚集索引字段排序效率是最高的

top是高效:top 子句用於規定要返回的記錄的數目。select top 10 percent * from record --加「top 10 percent」表示查詢的是資料表中前10%的資料,若將10改為20,則查詢的就是前20%的資料.

SQL中索引的使用

相信很多人寫sql,但是都沒有用到過索引,甚至不知道索引為何物?當然,很多功能不需要用索引頁能實現,那麼微軟為什麼還要設計索引這個工具呢?簡單來說,就是為了提高效能。比如說 新華字典中有很多字,我們要查其中的某乙個字,怎麼查?方法一 剛開始我們可以拼音查詢,恰好字典中字的排序就是拼音。方法二 偏旁查...

SQL 中聚集索引

今天做個試驗,驗證下聚集索引是不是改變表的物理結構。第一步 建立表 只有聚集索引 create table department departmentid int identity 1,1 not null primary key,name nvarchar 200 not null,groupna...

關於sql中索引的優缺點

系統如何訪問表中的資料 一般地,系統訪問資料庫中的資料,可以使用兩種方法 表掃瞄和索引查詢。第一種方法是表掃瞄,就是指系統將指標放置在該錶的表頭資料所在的資料頁上,然後按照資料頁的排列順序,一頁一頁地從前向後掃瞄該錶資料所占有的全部資料頁,直至掃瞄完表中的全部記錄。在掃瞄時,如果找到符合查詢條件的記...