詳細了解mysql的索引和事務

本文主要給大家簡單講講詳細了解MySQL的索引和事務,相關專業(yè)術語大家可以上網查查或者找一些相關書籍補充一下,這里就不涉獵了,我們就直奔主題吧,希望詳細了解mysql的索引和事務這篇文章可以給大家?guī)硪恍嶋H幫助。                                                           

創(chuàng)新互聯(lián)建站是一家集成都網站設計、成都網站制作、網站頁面設計、網站優(yōu)化SEO優(yōu)化為一體的專業(yè)網站制作公司,已為成都等多地近百家企業(yè)提供網站建設服務。追求良好的瀏覽體驗,以探求精品塑造與理念升華,設計最適合用戶的網站頁面。 合作只是第一步,服務才是根本,我們始終堅持講誠信,負責任的原則,為您進行細心、貼心、認真的服務,與眾多客戶在蓬勃發(fā)展的市場環(huán)境中,互促共生。

一、索引是做什么的?

很多時候,當你的應用程序進行SQL查詢速度很慢時,應該想想是否可以建索引。

大多數(shù)MySQL索引(PRIMARY KEY、UNIQUE、INDEX和FULLTEXT)在B樹中存儲。只是空間列類型的索引使用R-樹,并且MEMORY表還支持hash索引。

索引是一個排序的列表,在這個列表中存儲著索引的值和包含這個值的數(shù)據所在行的物理地址,在數(shù)據十分龐大的時候,索引可以大大加快查詢的速度,這是因為使用索引后可以不用掃描全表來定位某行的數(shù)據,而是先通過索引表找到該行數(shù)據對應的物理地址然后訪問相應的數(shù)據。

二、索引的優(yōu)缺點

優(yōu)勢:可以快速檢索,減少I/O次數(shù),加快檢索速度;根據索引分組和排序,可以加快分組和排序;

劣勢:索引本身也是表,因此會占用存儲空間,一般來說,索引表占用的空間的數(shù)據表的1.5倍;索引表的維護和創(chuàng)建需要時間成本,這個成本隨著數(shù)據量增大而增大;構建索引會降低數(shù)據表的修改操作(刪除,添加,修改)的效率,因為在修改數(shù)據表的同時還需要修改索引表;

詳細了解mysql的索引和事務

三、索引的分類

常見的索引類型有:主鍵索引、唯一索引、普通索引、全文索引、組合索引

1、主鍵索引:即主索引,根據主鍵pk_clolum(length)建立索引,不允許重復,不允許空值;

ALTER TABLE 'table_name' ADD PRIMARY KEY('id');

2、唯一索引:用來建立索引的列的值必須是唯一的,允許空值

ALTER TABLE 'table_name' ADD UNIQUE('email');

3、普通索引:用表中的普通列構建的索引,沒有任何限制

ALTER TABLE 'table_name' ADD INDEX index_name('description');

4、全文索引:用大文本對象的列構建的索引(下一部分會講解)

ALTER TABLE 'table_name' ADD FULLTEXT('content');

5、組合索引:用多個列組合構建的索引,這多個列中的值不允許有空值

ALTER TABLE 'table_name' ADD INDEX index_name('col1','col2','col3');

遵循“最左前綴”原則,把最常用作為檢索或排序的列放在最左,依次遞減,組合索引相當于建立了col1,col1col2,col1col2col3三個索引,而col2或者col3是不能使用索引的。

在使用組合索引的時候可能因為列名長度過長而導致索引的key太大,導致效率降低,在允許的情況下,可以只取col1和col2的前幾個字符作為索引

ALTER TABLE 'table_name' ADD INDEX index_name(col1(4),col2(3));

表示使用col1的前4個字符和col2的前3個字符作為索引

四、索引的實現(xiàn)原理

MySQL支持諸多存儲引擎,而各種存儲引擎對索引的支持也各不相同,因此MySQL數(shù)據庫支持多種索引類型,如BTree索引,B+Tree索引,哈希索引,全文索引等等,

1、哈希索引:

只有memory(內存)存儲引擎支持哈希索引,哈希索引用索引列的值計算該值的hashCode,然后在hashCode相應的位置存執(zhí)該值所在行數(shù)據的物理位置,因為使用散列算法,因此訪問速度非??欤且粋€值只能對應一個hashCode,而且是散列的分布方式,因此哈希索引不支持范圍查找和排序的功能。

2、全文索引:

FULLTEXT(全文)索引,僅可用于MyISAM和InnoDB,針對較大的數(shù)據,生成全文索引非常的消耗時間和空間。對于文本的大對象,或者較大的CHAR類型的數(shù)據,如果使用普通索引,那么匹配文本前幾個字符還是可行的,但是想要匹配文本中間的幾個單詞,那么就要使用LIKE %word%來匹配,這樣需要很長的時間來處理,響應時間會大大增加,這種情況,就可使用時FULLTEXT索引了,在生成FULLTEXT索引時,會為文本生成一份單詞的清單,在索引時及根據這個單詞的清單來索引。FULLTEXT可以在創(chuàng)建表的時候創(chuàng)建,也可以在需要的時候用ALTER或者CREATE INDEX來添加:

//創(chuàng)建表的時候添加FULLTEXT索引
CTREATE TABLE my_table(
id INT(10) PRIMARY KEY,
name VARCHAR(10) NOT NULL,
my_text text CHARACTER SET utf8 COLLATE utf8_general_ci NULL,
FULLTEXT(my_text));

//創(chuàng)建表以后,在需要的時候添加FULLTEXT索引
ALTER my_table ADD FULLTEXT ft_index(my_text);
CREATE INDEX ft_index ON my_table(my_text);

對于較大的數(shù)據集,把數(shù)據添加到一個沒有FULLTEXT索引的表,然后添加FULLTEXT索引的速度比把數(shù)據添加到一個已經有FULLTEXT索引的表快。

MySQL自帶的全文索引只能用于MyISAM存儲引擎,如果是其它數(shù)據引擎,那么全文索引不會生效。

在MySQL中,全文索引支隊英文有用,目前對中文還不支持。

在MySQL中,如果檢索的字符串太短則無法檢索得到預期的結果,檢索的字符串長度至少為4字節(jié),此外,如果檢索的字符包括停止詞,那么停止詞會被忽略。

3、BTree索引和B+Tree索引

BTree索引

BTree是平衡搜索多叉樹,設樹的度為d(d>1),高度為h,那么BTree要滿足以一下條件:

每個葉子結點的高度一樣,等于h;

每個非葉子結點由n-1個key和n個指針point組成,其中d<=n<=2d,key和point相互間隔,結點兩端一定是key;

葉子結點指針都為null;

非葉子結點的key都是[key,data]二元組,其中key表示作為索引的鍵,data為鍵值所在行的數(shù)據;

BTree的結構如下:

詳細了解mysql的索引和事務

在BTree的機構下,就可以使用二分查找的查找方式,查找復雜度為h*log(n),一般來說樹的高度是很小的,一般為3左右,因此BTree是一個非常高效的查找結構。

B+Tree索引

B+Tree是BTree的一個變種,設d為樹的度數(shù),h為樹的高度,B+Tree和BTree的不同主要在于:

B+Tree中的非葉子結點不存儲數(shù)據,只存儲鍵值;

B+Tree的葉子結點沒有指針,所有鍵值都會出現(xiàn)在葉子結點上,且key存儲的鍵值對應的數(shù)據的物理地址;

B+Tree的結構如下:

詳細了解mysql的索引和事務

一般來說B+Tree比BTree更適合實現(xiàn)外存的索引結構,因為存儲引擎的設計專家巧妙的利用了外存(磁盤)的存儲結構,即磁盤的一個扇區(qū)是整數(shù)倍的page(頁),頁是存儲中的一個單位,通常默認為4K,因此索引結構的節(jié)點被設計為一個頁的大小,然后利用外存的“預讀取”原則,每次讀取的時候,把整個節(jié)點的數(shù)據讀取到內存中,然后在內存中查找,已知內存的讀取速度是外存讀取I/O速度的幾百倍,那么提升查找速度的關鍵就在于盡可能少的磁盤I/O,那么可以知道,每個節(jié)點中的key個數(shù)越多,那么樹的高度越小,需要I/O的次數(shù)越少,因此一般來說B+Tree比BTree更快,因為B+Tree的非葉節(jié)點中不存儲data,就可以存儲更多的key。

帶順序索引的B+TREE

很多存儲引擎在B+Tree的基礎上進行了優(yōu)化,添加了指向相鄰葉節(jié)點的指針,形成了帶有順序訪問指針的B+Tree,這樣做是為了提高區(qū)間查找的效率,只要找到第一個值那么就可以順序的查找后面的值。

B+Tree的結構如下:

詳細了解mysql的索引和事務

分析了MySQL的索引結構的實現(xiàn)原理,然后我們來看看具體的存儲引擎怎么實現(xiàn)索引結構的,MySQL中最常見的兩種存儲引擎分別是MyISAM和InnoDB,分別實現(xiàn)了非聚簇索引和聚簇索引。

首先要介紹幾個概念,在索引的分類中,我們可以按照索引的鍵是否為主鍵來分為“主索引”和“輔助索引”,使用主鍵鍵值建立的索引稱為“主索引”,其它的稱為“輔助索引”。因此主索引只能有一個,輔助索引可以有很多個。

MyISAM——非聚簇索引

MyISAM存儲引擎采用的是非聚簇索引,非聚簇索引的主索引和輔助索引幾乎是一樣的,只是主索引不允許重復,不允許空值,他們的葉子結點的key都存儲指向鍵值對應的數(shù)據的物理地址。

非聚簇索引的數(shù)據表和索引表是分開存儲的。

非聚簇索引中的數(shù)據是根據數(shù)據的插入順序保存。因此非聚簇索引更適合單個數(shù)據的查詢。插入順序不受鍵值影響。

只有在MyISAM中才能使用FULLTEXT索引。

最開始我一直不懂既然非聚簇索引的主索引和輔助索引指向相同的內容,為什么還要輔助索引這個東西呢,后來才明白索引不就是用來查詢的嗎,用在那些地方呢,不就是WHERE和ORDER BY 語句后面嗎,那么如果查詢的條件不是主鍵怎么辦呢,這個時候就需要輔助索引了。

InnoDB——聚簇索引

聚簇索引的主索引的葉子結點存儲的是鍵值對應的數(shù)據本身,輔助索引的葉子結點存儲的是鍵值對應的數(shù)據的主鍵鍵值。因此主鍵的值長度越小越好,類型越簡單越好。

聚簇索引的數(shù)據和主鍵索引存儲在一起。

聚簇索引的數(shù)據是根據主鍵的順序保存。因此適合按主鍵索引的區(qū)間查找,可以有更少的磁盤I/O,加快查詢速度。但是也是因為這個原因,聚簇索引的插入順序最好按照主鍵單調的順序插入,否則會頻繁的引起頁分裂,嚴重影響性能。

在InnoDB中,如果只需要查找索引的列,就盡量不要加入其它的列,這樣會提高查詢效率。

使用主索引的時候,更適合使用聚簇索引,因為聚簇索引只需要查找一次,而非聚簇索引在查到數(shù)據的地址后,還要進行一次I/O查找數(shù)據。

因為聚簇輔助索引存儲的是主鍵的鍵值,因此可以在數(shù)據行移動或者頁分裂的時候降低委會成本,因為這時不用維護輔助索引。但是輔助索引會占用更多的空間。

聚簇索引在插入新數(shù)據的時候比非聚簇索引慢很多,因為插入新數(shù)據時需要減壓主鍵是否重復,這需要遍歷主索引的所有葉節(jié)點,而非聚簇索引的葉節(jié)點保存的是數(shù)據地址,占用空間少,因此分布集中,查詢的時候I/O更少,但聚簇索引的主索引中存儲的是數(shù)據本身,數(shù)據占用空間大,分布范圍更大,可能占用好多的扇區(qū),因此需要更多次I/O才能遍歷完畢。

下圖可以形象的說明聚簇索引和非聚簇索引的區(qū)別

詳細了解mysql的索引和事務

五、索引的使用策略

什么時候要使用索引?

主鍵自動建立唯一索引;

經常作為查詢條件在WHERE或者ORDER BY 語句中出現(xiàn)的列要建立索引;

作為排序的列要建立索引;

查詢中與其他表關聯(lián)的字段,外鍵關系建立索引

高并發(fā)條件下傾向組合索引;

什么時候不要使用索引?

經常增刪改的列不要建立索引;

有大量重復的列不建立索引;

表記錄太少不要建立索引;

在組合索引中不能有列的值為NULL,如果有,那么這一列對組合索引就是無效的;

在一個SELECT語句中,索引只能使用一次,如果在WHERE中使用了,那么在ORDER BY中就不要用了;

LIKE操作中,'%aaa%'不會使用索引,也就是索引會失效,但是‘aaa%’可以使用索引;

在索引的列上使用表達式或者函數(shù)會使索引失效,例如:select from users where YEAR(adddate)<2018,將在每個行上進行運算,這將導致索引失效而進行全表掃描,因此我們可以改成:select from users where adddate<’2018-12-24′。

在查詢條件中使用正則表達式時,只有在搜索模板的第一個字符不是通配符的情況下才能使用索引。

在查詢條件中使用<>會導致索引失效。

在查詢條件中使用IS NULL會導致索引失效。

在查詢條件中使用OR連接多個條件會導致索引失效,這時應該改為兩次查詢,然后用UNION ALL連接起來。

盡量不要包括多列排序,如果一定要,最好為這隊列構建組合索引;

只有當數(shù)據庫里已經有了足夠多的測試數(shù)據時,它的性能測試結果才有實際參考價值。如果在測試數(shù)據庫里只有幾百條數(shù)據記錄,它們往往在執(zhí)行完第一條查詢命令之后就被全部加載到內存里,這將使后續(xù)的查詢命令都執(zhí)行得非常快--不管有沒有使用索引。只有當數(shù)據庫里的記錄超過了1000條、數(shù)據總量也超過了MySQL服務器上的內存總量時,數(shù)據庫的性能測試結果才有意義。

六、索引的優(yōu)化

1、最左前綴

索引的最左前綴和和B+Tree中的“最左前綴原理”有關,舉例來說就是如果設置了組合索引<col1,col2,col3>那么以下3中情況可以使用索引:col1,<col1,col2>,<col1,col2,col3>,其它的列,比如<col2,col3>,<col1,col3>,col2,col3等等都是不能使用索引的。

根據最左前綴原則,我們一般把排序分組頻率最高的列放在最左邊,以此類推。

2、帶索引的模糊查詢優(yōu)化

在上面已經提到,使用LIKE進行模糊查詢的時候,'%aaa%'不會使用索引,也就是索引會失效。如果是這種情況,只能使用全文索引來進行優(yōu)化(上文有講到)。

為檢索的條件構建全文索引,然后使用

SELECT * FROM tablename MATCH(index_colum) ANGAINST(‘word’);

事務介紹

首先,什么是事務?事務就是一段sql 語句的批處理,但是這個批處理是一個atom(原子),不可分割,要么都執(zhí)行,要么回滾(rollback)都不執(zhí)行。

MySQL 事務主要用于處理操作量大,復雜度高的數(shù)據。比如說,在人員管理系統(tǒng)中,你刪除一個人員,你即需要刪除人員的基本資料,也要刪除和該人員相關的信息,如信箱,文章等等,這樣,這些數(shù)據庫操作語句就構成一個事務!

  • 在 MySQL 中只有使用了 Innodb 數(shù)據庫引擎的數(shù)據庫或表才支持事務。

  • 事務處理可以用來維護數(shù)據庫的完整性,保證成批的 SQL 語句要么全部執(zhí)行,要么全部不執(zhí)行。

  • 事務用來管理 insert,update,delete 語句

一般來說,事務是必須滿足4個條件(ACID): Atomicity(原子性)、Consistency(穩(wěn)定性)、Isolation(隔離性)、Durability(可靠性)

  • 1、事務的原子性:一組事務,要么成功;要么撤回。

  • 2、穩(wěn)定性 :有非法數(shù)據(外鍵約束之類),事務撤回。

  • 3、隔離性:事務獨立運行。一個事務處理后的結果,影響了其他事務,那么其他事務會撤回。事務的100%隔離,需要犧牲速度。

  • 4、可靠性:軟、硬件崩潰后,InnoDB數(shù)據表驅動會利用日志文件重構修改。可靠性和高速度不可兼得, innodb_flush_log_at_trx_commit 選項 決定什么時候吧事務保存到日志里。

詳細了解mysql的索引和事務

事務并發(fā)并不進行事務隔離造成的臟讀、幻讀、不可重復讀

  • 臟讀:事務A讀到未提交事務B修改的數(shù)據,如果此時事務B中途執(zhí)行失敗回滾,那么此時事務A讀取到的就是臟數(shù)據。比如事務A對money進行修改,此時事務B讀取到事務A的更新結果,但是如果后面事務A回滾,那么事務B讀取到的就是臟數(shù)據了。

  • 不可重復讀:同一個事務中,對同一份數(shù)據讀取的結果不一致。事務A在事務B對數(shù)據更新前進行讀取,然后事務B更新提交,事務A再次讀取,這時候兩次讀取的數(shù)據不同。

  • 幻讀:(同一個事務中,同一個查詢多次返回的結果不一樣。事務B查詢表的記錄數(shù),然后事務A對表插入一條記錄,接著事務B再次查詢發(fā)現(xiàn)記錄數(shù)不同。注意這個解釋是不正確,網絡上有很多這樣的解釋,包括我認為比較權威的專家,但是經過實驗發(fā)現(xiàn)并不正確。所以這是需要注意的)。可以做這樣一個實驗,事務A查詢記錄數(shù),事務B插入一條記錄(主鍵值為6),提交,然后事務A查詢記錄數(shù),發(fā)現(xiàn)記錄數(shù)沒有改變,但是此時插入一條主鍵值為6的記錄發(fā)現(xiàn)沖突了,感覺像出現(xiàn)了幻覺。

區(qū)別

1、臟讀和不可重復讀:臟讀是事務讀取了還未提交事務的更新數(shù)據。不可重復讀是同一個事務中,幾次讀取的數(shù)據不同。

2、不可重復讀和幻讀的區(qū)別:都是在同一個事務中,前者是幾次讀取數(shù)據不同,后者是幾次讀取數(shù)據整體不同。

隔離級別

詳細了解mysql的索引和事務

詳細了解mysql的索引和事務


  • 隔離級別改變影響鎖的周期

  • mysql支持上面4種隔離級別,默認為可重復讀

詳細了解mysql的索引和事務

詳細了解mysql的索引和事務

MySQL有三種鎖的級別:頁級、表級、行級。

MyISAM和MEMORY存儲引擎采用的是表級鎖(table-level locking);

BDB存儲引擎采用的是頁面鎖(page-level locking),但也支持表級鎖;

InnoDB存儲引擎既支持行級鎖(row-level locking),也支持表級鎖,但默認情況下是

采用行級鎖。

MySQL這3種鎖的特性可大致歸納如下: 1、表級鎖:開銷小,加鎖快;不會出現(xiàn)死鎖;鎖定粒度大,發(fā)生鎖沖突的概率最高,并發(fā)度最低。表級鎖讓多線程可以同時從數(shù)據表中讀取數(shù)據,但是如果另一個線程想要寫數(shù)據的話,就必須要先取得排他訪問(默認加排他表鎖);(共享讀鎖(Table Read Lock)更新數(shù)據時,必須要等到更新完成了,其他線程才能訪問(讀)這個表。(獨占寫鎖(Table Write Lock))

2、行級鎖:開銷大,加鎖慢;會出現(xiàn)死鎖;鎖定粒度最小,發(fā)生鎖沖突的概率最低,并發(fā)度也最高。

3、頁面鎖:開銷和加鎖時間界于表鎖和行鎖之間;會出現(xiàn)死鎖;鎖定粒度界于表鎖和行鎖之間,并發(fā)度一般。

原則上數(shù)據表有一個讀鎖時,其它進程無法對此表進行更新操作,但在一定條件下,MyISAM表也支持查詢和插入操作的并發(fā)進行。

一般MyISAM引擎的表也支持查詢和插入操作的并發(fā)進行(原則上數(shù)據表有一個讀鎖時,其它進程無法對此表進行更新操作)

MyISAM引擎有一個系統(tǒng)變量concurrent_insert,專門用以控制其并發(fā)插入的行為,其值分別可以為0、1或2:

a、concurrent_insert為0,不允許并發(fā)插入。     
b、concurrent_insert為1,如果MyISAM表中沒有空洞(即表的中間沒有被刪除的行),MyISAM允許在一個進程讀表的同時,另一個進程從表尾插入記錄。這也是MySQL的默認設置。     
c、concurrent_insert為2,無論MyISAM表中有沒有空洞,都允許在表尾并發(fā)插入記錄。

如果有讀寫請求同時進行的話,MYSQL將會優(yōu)先執(zhí)行寫操作。這樣MyISAM表在進行大量的更新操作時(特別是更新的字段中存在索引的情況下),會造成查詢操作很難獲得讀鎖,從而導致查詢阻塞。

我們還可以調整MyISAM讀寫的優(yōu)先級別:

  a、通過指定啟動參數(shù)low-priority-updates,使MyISAM引擎默認給予讀請求以優(yōu)先的權利。
  b、通過執(zhí)行命令SET LOW_PRIORITY_UPDATES=1,使該連接發(fā)出的更新請求優(yōu)先級降低。
  c、通過指定INSERT、UPDATE、DELETE語句的LOW_PRIORITY屬性,降低該語句的優(yōu)先級。

MyISAM使用的是 flock 類的函數(shù),直接就是對整個文件進行鎖定(叫做文件鎖定),MyISAM的數(shù)據表是按照單個文件存儲的,可以針對單個表文件進行鎖定;

InnoDB使用的是 fcntl 類的函數(shù),可以對文件中局部數(shù)據進行鎖定(叫做行鎖定),InnoDB是一整個文件,把索引、數(shù)據、結構全部保存在 ibdata 文件里,所以必須用行鎖定。

事物控制語句:

BEGIN或START TRANSACTION;顯式地開啟一個事務;     
COMMIT;也可以使用COMMIT WORK,不過二者是等價的。
COMMIT會提交事務,并使已對數(shù)據庫進行的所有修改稱為永久性的;      
ROLLBACK;有可以使用ROLLBACK WORK,不過二者是等價的?;貪L會結束用戶的事務,并撤銷正在進行的所有未提交的修改;      
SAVEPOINT identifier;SAVEPOINT允許在事務中創(chuàng)建一個保存點,一個事務中可以有多個SAVEPOINT;     
RELEASE SAVEPOINT identifier;刪除一個事務的保存點,當沒有指定的保存點時,執(zhí)行該語句會拋出一個異常;     
ROLLBACK TO identifier;把事務回滾到標記點;     
SET TRANSACTION;用來設置事務的隔離級別。
InnoDB存儲引擎提供事務的隔離級別有READ UNCOMMITTED、READ COMMITTED、REPEATABLE READ和SERIALIZABLE。

MYSQL 事務處理主要有兩種方法:

1、用 BEGIN, ROLLBACK, COMMIT來實現(xiàn)

BEGIN 開始一個事務     
ROLLBACK 事務回滾    
COMMIT 事務確認

2、直接用 SET 來改變 My

SQL 的自動提交模式:

SET AUTOCOMMIT=0 禁止自動提交     
SET AUTOCOMMIT=1 開啟自動提交

注意點

1、如果事務中sql正確運行,后面沒有commit,結果是不會更新到數(shù)據庫的,所以需要手動添加commit。

2、如果事務中部分sql語句出現(xiàn)錯誤,那么錯誤語句后面不會執(zhí)行。而我們可能會認為正確操作會回滾撤銷,但是實際上并沒有撤銷正確的操作,此時如果再無錯情況下進行一次commit,之前的正確操作會生效,數(shù)據庫會進行更新。

詳細了解mysql的索引和事務就先給大家講到這里,對于其它相關問題大家想要了解的可以持續(xù)關注我們的行業(yè)資訊。我們的板塊內容每天都會捕捉一些行業(yè)新聞及專業(yè)知識分享給大家的。

新聞標題:詳細了解mysql的索引和事務
網頁路徑:http://bm7419.com/article28/gihscp.html

成都網站建設公司_創(chuàng)新互聯(lián),為您提供網頁設計公司網站改版、小程序開發(fā)外貿網站建設、網站營銷、用戶體驗

廣告

聲明:本網站發(fā)布的內容(圖片、視頻和文字)以用戶投稿、用戶轉載內容為主,如果涉及侵權請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內容未經允許不得轉載,或轉載時需注明來源: 創(chuàng)新互聯(lián)

網站優(yōu)化排名