自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

小白學(xué)習mysql之高新能索引基礎(chǔ)篇

開發(fā) 后端
索引在數(shù)據(jù)庫中的地位是及其的重要,同時要想完全的掌握索引并不是一件容易的事,需要對數(shù)據(jù)的查詢原理以及計算機操作系統(tǒng)有深刻的認識,當然相關(guān)的算法和數(shù)據(jù)結(jié)構(gòu)也是必須的。因此,這篇文章感到了一些壓力,不過還是決定先拿出來總結(jié)一下,理一理索引,就當做學(xué)習筆記了。

索引在數(shù)據(jù)庫中的地位是及其的重要,同時要想完全的掌握索引并不是一件容易的事,需要對數(shù)據(jù)的查詢原理以及計算機操作系統(tǒng)有深刻的認識,當然相關(guān)的算法和數(shù)據(jù)結(jié)構(gòu)也是必須的。因此,這篇文章感到了一些壓力,不過還是決定先拿出來總結(jié)一下,理一理索引,就當做學(xué)習筆記了。

索引的重要習性猶如一本字典的拼音檢索和部首檢索部分,想象一下你買了一本只有正文的字典,那該有多么抓狂。而且在一個軟件系統(tǒng)中,通常數(shù)據(jù)的查詢與修改往往占到了10:1的比例,也就是我們需要將大部分的精力投入到數(shù)據(jù)的查詢上,其中很多工作是用來提升查詢的速度的,那么在這個過程中索引就扮演者非常重要的角色。

索引的實質(zhì)

如果說一本字典的正文內(nèi)容的實質(zhì)是紙張的話,那么它前面按照拼音或者部首檢索的索引的實質(zhì)是什么呢!當然也是紙張了,可能有人覺得是廢話,當我們同時類比到索引上就可以知道,一個數(shù)據(jù)表的實質(zhì)是數(shù)據(jù)文件(即文件),那么索引的實質(zhì)也當然是文件了,Mysql的InnoDB的數(shù)據(jù)表中的索引就是表空間的一部分。因此,初學(xué)者可以把索引完全想象成為一本字典,一本字典就是一個數(shù)據(jù)表,正文部分呢,就是這個數(shù)據(jù)表的詳細內(nèi)容,按照拼音和部首的檢索都是索引。 當我們通過索引查找一條數(shù)據(jù)項的時候就猶如通過拼音索引查找某一個字,當在索引中查找到那個字的時候,會根據(jù)右邊對應(yīng)的頁碼找到那個字的解釋,同樣,MySQL的索引工作原理也是如此,每個索引項都有一個建索引列的關(guān)鍵字和一個指向該數(shù)據(jù)項的指針(類似字典中的頁碼),當我們查找到那個目標關(guān)鍵字時,根據(jù)指針便可以直接定位到數(shù)據(jù)表中該關(guān)鍵字的位置。

但現(xiàn)實中的真是數(shù)據(jù)表并不像字典那樣,內(nèi)容都是嚴格按照拼音序列排列的,因為有很多不確定的新內(nèi)容要插入或者要進行其他操作,所以字典只是一種特殊的數(shù)據(jù)表,并不能把所有的數(shù)據(jù)表都拿來和字典比,這里用字典來類比只是為了對索引的實質(zhì)有一個立體的認識。

索引是如何實現(xiàn)快速查找的

假設(shè)A公司有1024名員工(員工編號1-1024),早上的出勤人數(shù)為1023次,現(xiàn)在想知道員工編號為8的小明是否出勤,如何通過早上的簽到表快速的查詢小明是否出勤呢!在沒有索引的情況下,通常的做法是從第一條記錄逐個向后查找,如果小明最后一個來或者沒有來,那么就需要查找1023次,效率為O(N)。也許會覺得1023次查找對現(xiàn)在的計算機根本不算什么,但是對于很多系統(tǒng)動輒都是上千萬的數(shù)據(jù)記錄,你可以想象查找的時間,比如你用15分鐘終于通過了qq的身份校驗登陸上了qq是一種怎么樣的體驗。因此,索引就呼之欲出了,我們?nèi)绾瓮ㄟ^索引來提高一個數(shù)量級的查找效率,這個時候就需要對這1024條數(shù)據(jù)做些什么了,在每條記錄插入的時候,可以根據(jù)每條記錄的員工編號和存儲該記錄的地址(指針)建立一個二叉查找樹,這樣1023條記錄便可以通過10次查找便可查到,查找效率足足提高了100倍。

同樣,為了效率的提升,也付出了一些代價,因為建立二叉查找樹需要額外的存儲空間,同時每次插入數(shù)據(jù)的時候需要對二叉查找樹進行維護,減緩了數(shù)據(jù)的更新速度。但綜合來考慮,一般認為這樣做是值得的。

當然在MySQL中,不是采用的二叉樹查找樹來完成索引的存儲的,上面舉得例子只是為了說明索引的工作過程,但其思想是相同的。MySQL中沒有特殊說明的話,一般說的索引指的就是B-Tree索引,采用B-Tree這種數(shù)據(jù)結(jié)構(gòu)是綜合了計算機操作系統(tǒng)以及組成而綜合考慮的。其核心思想主要是減少磁盤的IO次數(shù),提高查詢速度。

如何理解聚簇索引

你只需記住它的名字叫聚簇索引,它不同于其他普通的索引!聚簇索引不僅僅是一種索引,更是一種存儲方式,InnoDB中將B-Tree索引和數(shù)據(jù)行存儲在一個數(shù)據(jù)結(jié)構(gòu)中,意味著什么呢?這意味著數(shù)據(jù)行即索引,索引即數(shù)據(jù)行,它們是在一起,在一起,在一起的。

接著通過來建立字典的例子來理解聚簇索引和其他普通索引的區(qū)別,現(xiàn)在要建立一本中華字典,這個時候字典是空的,要我們造一本字典出來,首先我們要完成字典的正文,我們按照漢語拼音的順序去組織字典的正文,第一個是“安 an ”,放在一個位置,同時后面附加上注釋(這里,“an”就相當于聚簇索引的關(guān)鍵字,而后面的注釋就是數(shù)據(jù)行,它們存在一起),第二個是“王 wang”字,通過和“安 an”字比較,拼音順序靠后,所以放第二個。注意這里的放是指存儲在磁盤中的位置,可以理解為存儲順序。第三個字是“小 xiao”字,通過拼音順序,需要將第三個字存在第一個字“安”后面,那“王”字已經(jīng)占了磁盤頁面的位置,所以它需要向后面移動,如果移出該列,就導(dǎo)致了也分裂,所以可以看到聚集索引的更新代價真的很大,那為什么還要這樣做呢?聚簇索引帶來了那些好處?

......,假設(shè)按照上面方法已經(jīng)建立好了字典的正文內(nèi)容,這個時候就可以讓我們體會一下聚簇索引的好處了,假如你要找“安 an”字,根據(jù)拼音序列,你一定知道它一定在前幾個頁面,所以直接可以翻到前面,同時你也可以找到拼音“an”所對應(yīng)的所有的漢字,這就是聚簇索引帶來的好處,同時聚簇索引是和數(shù)據(jù)行放在一起的,你不需要在根據(jù)索引里的指針找到對應(yīng)的數(shù)據(jù)行,然后翻頁找到(翻頁就相當于磁盤IO),這些都是效率的提升。然而,上面也看到了聚簇索引的負面影響比如插入的時候,因此它就像一般利劍,用的合適效率提升,用的糟糕也會帶來很大的不好影響。

是時候區(qū)別一下非聚聚索引了,這個時候我們又按照部首建立了一個索引,那么按照部首建立的索引就是非聚簇索引,它單獨的存在在字典的前幾個頁面,而且同一個部首的字所對應(yīng)的頁碼也是沒有順序的,如果我們要山字旁所對應(yīng)的所有漢字,那就要取很多個頁面的值,導(dǎo)致很多隨機IO產(chǎn)生,同時不能很好利用計算機存儲系統(tǒng)的緩存系統(tǒng),因此效率遠沒有聚簇索引高。

InnoDB中聚簇索引產(chǎn)生的原則:

  • 當有主鍵時,主鍵為聚簇索引
  • 當沒有主鍵時,引擎會選擇一個唯一的*非空*列來作為聚簇索引
  • 如果沒有以上兩種情況的列,引擎會隱式的定義一個主鍵作為聚簇索引

最后,通過建立一個數(shù)據(jù)表來感受聚簇索引,首先建立有一個沒有主鍵也沒有唯一非空列索引的數(shù)據(jù)表,即聚簇索引是系統(tǒng)隱式生成這種情況。這種情況,一般就是按數(shù)據(jù)插入的先后順序進行排列。

  1. CREATE TABLE user_log (
  2. user_id INT NOT NULL,
  3. place VARCHAR(20) NOT NULL DEFAULT '',
  4. login_time TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
  5.  
  6. ) DEFAULT CHARSET utf8;

接下來插入三條數(shù)據(jù):

  1. > INSERT INTO user_log(user_id,place)
  2. VALUES('1','中國');
  3. > INSERT INTO user_log(user_id,place)
  4. VALUES('2','中國');
  5. > INSERT INTO user_log(user_id,place)
  6. VALUES('1','美國');

然后,選擇所有列(即按照存儲順序查看數(shù)據(jù)列),果然如我們猜想,是按照插入順序存儲的:

  1. > SELECT * FROM user_log;
  2.  
  3. user_id place login_time
  4. 1 中國 2015-11-20 10:32:41
  5. 2 中國 2015-11-20 10:33:18
  6. 1 美國 2015-11-20 10:33:18

接下來,我們添加一個唯一的索引(ID+login_time),此時 系統(tǒng)引擎應(yīng)該將此索引作為聚簇索引,因此我們再次插入新的數(shù)據(jù)的時候是按照ID聚簇存儲的,就是說ID相同的會存儲在一起,存儲在同一個頁面,甚至連續(xù)的幾個頁面。 下面首先添加這個唯一索引 并接著添加三條新的記錄:

  1. > ALTER TABLE user_log ADD UNIQUE KEY U_USER_LOG_ID_LOGIN_TIME(user_id,login_time);
  2.  
  3. > INSERT INTO user_log(user_id,place)
  4. VALUES('1','法國');
  5. > INSERT INTO user_log(user_id,place)
  6. VALUES('2','日本');
  7. > INSERT INTO user_log(user_id,place)
  8. VALUES('1','韓國');

然后接著查看數(shù)據(jù)的存儲情況:

  1. > SELECT * FROM user_log;
  2.  
  3. user_id place login_time
  4. 1 中國 2015-11-20 10:32:41
  5. 1 美國 2015-11-20 10:33:18
  6. 1 法國 2015-11-20 10:48:00
  7. 2 中國 2015-11-20 10:33:18
  8. 2 日本 2015-11-20 10:48:00

這樣以來,如果我們要獲取某一個用戶的登陸情況,就可以非常的方便,因為該用戶的所有登陸記錄是按照ID聚集的存儲在一起的,這樣主存緩存一個頁面的數(shù)據(jù)可能就OK了,如果是非聚集存儲的,假如某個id的數(shù)據(jù)分散在100個頁面,那么主存就要緩存這100個頁面,效率可想而知。

總結(jié)

這篇文中一開始的構(gòu)想是想從計算機操作系統(tǒng)的存儲系統(tǒng)和B-Tree入手寫的,結(jié)果寫著寫著發(fā)現(xiàn),有點不太現(xiàn)實,一來文章長度可能增加幾倍,二來可能自己都寫暈了,既然是小白篇嘛,就先來個綜述吧!總之索引是非常強大而且有意思的,然而當數(shù)據(jù)量達到一定量時,感覺索引也是有點乏力,但是盡量用好每一個索引是非常有必要而且是一種態(tài)度。

責任編輯:李英杰 來源: 博客園
相關(guān)推薦

2010-05-27 17:57:09

Svn使用入門

2011-07-11 13:11:54

MySQL索引數(shù)據(jù)結(jié)構(gòu)

2020-10-28 07:08:03

Linux零拷貝內(nèi)核

2021-04-22 22:26:13

Java語言IT

2018-08-16 09:29:26

2019-10-31 08:00:00

機器學(xué)習人工智能AI

2010-08-31 11:30:26

vSphere服務(wù)器虛擬化VMware

2017-02-17 08:58:54

微服務(wù)架構(gòu)

2019-10-12 15:06:02

MySQL數(shù)據(jù)庫命令

2010-09-14 16:54:18

2011-05-24 13:08:51

理光復(fù)合機

2020-02-26 16:52:24

Redis高性能數(shù)據(jù)庫

2021-03-18 08:53:44

MySQL數(shù)據(jù)庫索引

2021-12-29 07:01:53

Mysql復(fù)合索引

2009-11-05 15:47:37

CCNP學(xué)習筆記

2022-03-03 09:05:17

索引MySQL數(shù)據(jù)查詢

2012-06-15 10:13:03

2025-04-14 00:00:00

MCPjson 信息地理編碼

2025-02-10 11:11:47

2010-06-01 13:25:59

視頻會議高速公路捷思銳科技
點贊
收藏

51CTO技術(shù)棧公眾號