sql server 創建唯一性非聚集索引語句_數據庫專題—索引原理

深入淺出數據庫索引原理

參見:https://www.cnblogs.com/aspwebchh/p/6652855.html

1.為什么給表加上主鍵?

  • 1.平時創建表的時候,都會給表加上主鍵。如果沒有主鍵的表,數據會一行行的排列在磁盤上,查找一個數據需要一條條的進行對比。而加上主鍵的表,會變成樹形(B樹/B+樹),這樣整個表就變成一個索引,即聚合索引

83802bed7283b84b96fdd8690c9088b4.png

假如我們執行一個SQL語句:

select * from table where id = 1256;

首先根據索引定位到1256這個值所在的葉結點,然后再通過葉結點取到id等于1256的數據行。

2.為什么索引后會使查詢變快?

  • 假如一張表有一億條數據 ,需要查找其中某一條數據,按照常規邏輯, 一條一條的去匹配的話, 最壞的情況下需要匹配一億次才能得到結果,用大O標記法就是O(n)最壞時間復雜度,這是無法接受的,而且這一億條數據顯然不能一次性讀入內存供程序使用, 因此, 這一億次匹配在不經緩存優化的情況下就是一億次IO開銷,以現在磁盤的IO能力和CPU的運算能力, 有可能需要幾個月才能得出結果 。如果把這張表轉換成平衡樹結構(一棵非常茂盛和節點非常多的樹),假設這棵樹有10層,那么只需要10次IO開銷就能查找到所需要的數據, 速度以指數級別提升,用大O標記法就是O(log n),n是記錄總樹,底數是樹的分叉數,結果就是樹的層次數。

a0e7d88127ca7b7de0105749918747f7.png

3.為什么加索引后會使寫入、修改、刪除變慢?

  • 事物都是有兩面的, 索引能讓數據庫查詢數據的速度上升, 而使寫入數據的速度下降,原因很簡單的, 因為平衡樹這個結構必須一直維持在一個正確的狀態, 增刪改數據都會改變平衡樹各節點中的索引數據內容,破壞樹結構, 因此,在每次數據改變時, DBMS必須去重新梳理樹(索引)的結構以確保它的正確,這會帶來不小的性能開銷,也就是為什么索引會給查詢以外的操作帶來副作用的原因。

4.什么情況下要同時在兩個字段上建索引?

4.1 非聚合索引

  • 非聚集索引和聚集索引一樣, 同樣是采用平衡樹作為索引的數據結構。索引樹結構中各節點的值來自于表中的索引字段, 假如給user表的name字段加上索引 , 那么索引就是由name字段中的值構成,在數據改變時, DBMS需要一直維護索引結構的正確性。如果給表中多個字段加上索引 , 那么就會出現多個獨立的索引結構,每個索引(非聚集索引)互相之間不存在關聯。 如下圖

e87c2fc17262113b23ad52062f183e6e.png
  • 每次給字段建一個新索引, 字段中的數據就會被復制一份出來, 用于生成索引。 因此, 給表添加索引,會增加表的體積, 占用磁盤存儲空間。

非聚集索引和聚集索引的區別在于, 通過聚集索引可以查到需要查找的數據, 而通過非聚集索引可以查到記錄對應的主鍵值 , 再使用主鍵的值通過聚集索引查找到需要的數據,如下圖

cb2d6d1f0f5716d3aef2ba3455c2870d.png

4.2 覆蓋索引

  • 非聚合索引都會利用主鍵通過聚合索引來定位到數據,聚合索引(主鍵)是通往真實數據所在的唯一路徑,但是有一種例外是可以不使用聚合索引就能查詢到所需要的數據,這種辦法被稱為覆蓋索引。

先看下面這個SQL語句

//建立索引

create index index_birthday on user_info(birthday);

//查詢生日在1991年11月1日出生用戶的用戶名

select user_name from user_info where birthday = '1991-11-1'

這句SQL語句的執行過程如下

首先,通過非聚集索引index_birthday查找birthday等于1991-11-1的所有記錄的主鍵ID值

然后,通過得到的主鍵ID值執行聚集索引查找,找到主鍵ID值對就的真實數據(數據行)存儲的位置

最后, 從得到的真實數據中取得user_name字段的值返回, 也就是取得最終的結果

我們把birthday字段上的索引改成雙字段的覆蓋索引

create index index_birthday_and_user_name on user_info(birthday, user_name);

這句SQL語句的執行過程就會變為

通過非聚集索引index_birthday_and_user_name查找birthday等于1991-11-1的葉節點的內容,然而, 葉節點中除了有user_name表主鍵ID的值以外, user_name字段的值也在里面, 因此不需要通過主鍵ID值的查找數據行的真實所在, 直接取得葉節點中user_name的值返回即可。 通過這種覆蓋索引直接查找的方式, 可以省略不使用覆蓋索引查找的后面兩個步驟, 大大的提高了查詢性能,如下圖

1564b665cbf41f33eeda2b3b6ffab7cc.png

一、為什么要創建索引呢(優點)?

這是因為,創建索引可以大大提高系統的性能。

第一, 通過創建唯一性索引,可以保證數據庫表中每一行數據的唯一性。

第二, 可以大大加快數據的檢索速度,這也是創建索引的最主要的原因。

第三, 可以加速表和表之間的連接,特別是在實現數據的參考完整性方面特別有意義。

第四, 在使用分組和排序子句進行數據檢索時,同樣可以顯著減少查詢中分組和排序的時間。

第五, 通過使用索引,可以在查詢的過程中,使用優化隱藏器,提高系統的性能。

二、建立方向索引的不利因素(缺點)

也許會有人要問:增加索引有如此多的優點,為什么不對表中的每一個列創建一個索引呢?這種想法固然有其合理性,然而也有其片面性。雖然,索引有許多優點,但是,為表中的每一個列都增加索引,是非常不明智的。這是因為,增加索引也有許多不利的一個方面。

第一, 創建索引和維護索引要耗費時間,這種時間隨著數據量的增加而增加。

第二, 索引需要占物理空間,除了數據表占數據空間之外,每一個索引還要占一定的物理空間,如果要建立聚簇索引,那么需要的空間就會更大。

第三, 當對表中的數據進行增加、刪除和修改的時候,索引也要動態的維護,這樣就降低了數據的維護速度。

三、創建方向索引的準則

索引是建立在數據庫表中的某些列的上面。因此,在創建索引的時候,應該仔細考慮在哪些列上可以創建索引,在哪些列上不能創建索引。

一般來說,應該在這些列上創建索引。

第一, 在經常需要搜索的列上,可以加快搜索的速度;

第二, 在作為主鍵的列上,強制該列的唯一性和組織表中數據的排列結構;

第三, 在經常用在連接的列上,這些列主要是一些外鍵,可以加快連接的速度;

第四, 在經常需要根據范圍進行搜索的列上創建索引,因為索引已經排序,其指定的范圍是連續的;

第五, 在經常需要排序的列上創建索引,因為索引已經排序,這樣查詢可以利用索引的排序,加快排序查詢時間;

第六, 在經常使用在WHERE子句中的列上面創建索引,加快條件的判斷速度。

同樣,對于有些列不應該創建索引。一般來說,不應該創建索引的的這些列具有下列特點:

第一, 對于那些在查詢中很少使用或者參考的列不應該創建索引。這是因為,既然這些列很少使用到,因此有索引或者無索引,并不能提高查詢速度。相反,由于增加了索引,反而降低了系統的維護速度和增大了空間需求。

第二, 對于那些只有很少數據值的列也不應該增加索引。這是因為,由于這些列的取值很少,例如人事表的性別列,在查詢的結果中,結果集的數據行占了表中數據行的很大比例,即需要在表中搜索的數據行的比例很大。增加索引,并不能明顯加快檢索速度。

第三, 對于那些定義為text, image和bit數據類型的列不應該增加索引。這是因為,這些列的數據量要么相當大,要么取值很少。

第 四, 當修改性能遠遠大于檢索性能時,不應該創建索引。這是因為,修改性能和檢索性能是互相矛盾的。當增加索引時,會提高檢索性能,但是會降低修改性能。當減少 索引時,會提高修改性能,降低檢索性能。因此,當修改性能遠遠大于檢索性能時,不應該創建索引。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/457960.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/457960.shtml
英文地址,請注明出處:http://en.pswp.cn/news/457960.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

String,StringBuffer,StringBuilder區別

String 字符串常量StringBuffer 字符串變量(線程安全)StringBuilder 字符串變量(非線程安全) 簡要的說, String 類型和 StringBuffer 類型的主要性能區別其實在于 String 是不可變的對象, 因此在每次對 String 類型進行…

oracle數據庫更新語句_20_手把手教你學Python之操作數據庫

數據庫是數據的倉庫,將大量數據按照一定的方式組織并存儲起來,方便進行管理和維護,例如快速檢索和統計等。數據庫的主要特點:以一定的方式組織、存儲數據;能為多個用戶共享;與程序彼此獨立。……數據庫管理…

第十周學習進度

第十周 所花時間(包括上課) 10小時 代碼量(行) 0行 博客量(篇) 4篇 了解到的知識點 對各組進行評價;思考并回復各組 轉載于:https://www.cnblogs.com/qwer111/p/5470819.html

嵌入式常見筆試題總結(3)

1:設float a2, b4, c3;,以下C語言表達式與代數式 (ab)c計算結果不一致的是 A.(ab)*c/2 B.(1/2)*(ab)*c C.(ab)*c*1/2 D.c/2*(ab) 參考答案:B,因為a,b,c三個變量都是浮點數,所以在B答案中其結果是0,因為…

查詢Oracle正在執行的sql語句

--查詢Oracle正在執行的sql語句及執行該語句的用戶 [sql] view plaincopy SELECT b.sid oracleID, b.username 登錄Oracle用戶名, b.serial#, spid 操作系統ID, paddr, sql_text 正在執行的SQL, b.machine 計算機名 FROM v$p…

WinForm 清空界面控件值的小技巧

WinForm 清空界面控件值的小技巧 原文:WinForm 清空界面控件值的小技巧在WinForm里面有時候需要清空自己輸入內容或是選擇的選項,以便重新操作流程,那么一般你是怎么清空界面各個控件值的呢?如果窗體里面控件,尤其是TextBox控件比…

int 取值范圍_一定范圍內的隨機數

老司機的新問題,取得[min, max]范圍的隨機數。C版本的rand函數很不容易用對,直接用rand() % (max - min 1) min,這個公式不對。這個公式與取最低位的算法相同,而隨機數的最低幾位不一定等概率。Donald Knuth博士教導我們正確的用…

virsh的使用

2019獨角獸企業重金招聘Python工程師標準>>> ###這里最先要完成的是對網卡的配置(os ubuntu14.04) 目的是實現vm上是以橋接的方式聯網 修改/etc/network/interfaces # interfaces(5) file used by ifup(8) and ifdown(8) auto lo iface lo inet loopback #auto eth0…

嵌入式常見筆試題總結(4)

1:用C語言實現大小端的測試 Int CheckCpu() { union { int a; char b; }c; c.a1; if(c.b1) printf(“小端”); else printf(“大端”); } 2:volatile的作用有哪些? Volatile第一變量相當于告訴編…

《java入門第一季》之類String類小案例

String類有許多獲取方法,API文檔里面可查看。針對獲取方法,給出小案例。 /** 需求:遍歷獲取字符串中的每一個字符* 分析: 用到兩個方法:char charAt(int index) 表示獲取字符串指定索引的字符int length() …

同字母異序詞 python_49. 字母異位次分組(Python)

題目 給定一個字符串數組,將字母異位詞組合在一起。字母異位詞指字母相同,但排列不同的字符串。 說明 所有輸入均為小寫字母。 不考慮答案輸出的順序。 示例 輸入: ["eat", "tea", "tan", "ate", "nat&quo…

嵌入式常見筆試題總結(5)

1、 如何在C中初始化一個字符數組。這個問題看似很簡單,但是我們要將最簡單的問題用最嚴謹的態度來對待。關鍵的地方:初始化、字符型、數組。最簡單的方法是char array[];。這個問題看似解決了,但是在初始化上好像還欠缺點什么,個…

SQL Server - 高可用與災難恢復(HADR)技術 -- AlwaysOn可用性組(理論篇)

因為篇幅原因,AlwaysOn可用性組被拆成了兩部分:理論部分和實戰部分。而實戰部分又被拆成了準備工作和AlwaysOn可用性組搭建。 三篇文章各自的鏈接: SQL Server ->> 高可用與災難恢復(HADR)技術 -- AlwaysOn&…

嵌入式常見筆試題總結(6)

一、常識理論題 1、 簡述嵌入式操作系統有哪些,你用過哪幾種,簡述其特點、優勢及劣勢?(5分) 2、 請描述控制及提高嵌入式軟件質量有哪些辦法,在開發過程中怎么才能保證嵌入式軟件的可靠性?(5分)…

python 3.6.5編譯安裝_Linux系統安裝Python3.6.5

Linux系統安裝Python3.6.5 1、下載Python3.6.5 wget https://www.python.org/ftp/python/3.6.5/Python-3.6.5.tgz 如果報command not found則執行:yum -y install wget命令后再進行下載 也可下載好安裝包進行手動上傳 2、安裝Python3.6可能使用的依賴 yum install o…

從傳統運維到云運維演進歷程之軟件定義存儲(一)

運維是企業業務系統從規劃、設計、實施、交付到運維的最后一個步驟,也是重要的步驟。運維從橫向、縱向分可以分為多個維度和層次,本文試圖拋開這紛繁復雜的概念,講述一個傳統的企業級運維人員轉型到云運維人員,尤其是軟件定義存儲…

Abp Uow 設計

初始化入口 在AbpKernelModule類中&#xff0c;通過UnitOfWorkRegistrar.Initialize(IocManager) 方法去初始化 1 /// <summary>2 /// This class is used to register interceptor for needed classes for Unit Of Work mechanism.3 /// </summary>4 …

python3.8 實現鼠標自動移動_“新生報到”!【移動機器人 HD-1500】負載1500kg,實現了重型貨物運輸的自動化...

2020年第三季度歐姆龍自動化&#xff08;中國&#xff09;有限公司新品【移動機器人 HD-1500】即日起在中國市場首次對外發布&#xff0c;實現了重型貨物運輸的自動化。這款最新的自動化移動機器人重型載荷能力為1500 kg&#xff01;更高的載荷能力可以令客戶實現以前無法實現的…

Linux 關閉服務后 鼠標 鍵盤用不了

大部分情況下我們做實驗都是使用虛擬機&#xff0c;但是個人比較本實在太老了&#xff0c;性能有限&#xff0c;所以虛擬機里面的系統啟動神慢&#xff0c;怎么辦&#xff1f;把系統中自己用不到的服務全部關閉掉唄&#xff0c;如下for i in chkconfig --list | awk {print $1}…

對session的理解

java Servlet API引入session 機制來跟蹤客戶的狀態&#xff0c;session指的是在一段時間內&#xff0c;單個客戶和web服務器之間一連串的交互過程&#xff0c;在一個session中&#xff0c;一個客戶可能會多次請求同一個網頁&#xff0c;也可能請求多個不同服務器資源&#xff…