日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 运维知识 > 数据库 >内容正文

数据库

MySQL索引重点问题总结(需要完整脑图的联系我)

發(fā)布時(shí)間:2023/12/14 数据库 29 豆豆
生活随笔 收集整理的這篇文章主要介紹了 MySQL索引重点问题总结(需要完整脑图的联系我) 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

MySQL索引

MySQL邏輯架構(gòu)

連接層

MySQL連接層主要包括連接池,mysql屬于C/S架構(gòu),每次客戶端和服務(wù)端連接時(shí),底層都會(huì)創(chuàng)建一個(gè)TCP連接,連階層主要負(fù)責(zé)管理這些連接,驗(yàn)證用戶名密碼和權(quán)限認(rèn)證

服務(wù)層

mysql的服務(wù)層主要負(fù)責(zé)sql語句的解析優(yōu)化。它有基礎(chǔ)服務(wù)組件,SQL借口,解析器,優(yōu)化器,查詢緩存(MySQL8.0之后去除了這個(gè)雞肋的設(shè)計(jì))等組成。整個(gè)語句的執(zhí)行過程是這樣的先查看查詢緩存中是否存在當(dāng)前執(zhí)行的語句,如果不存在則先由解析器解析,優(yōu)化器指定執(zhí)行計(jì)劃,調(diào)用sql接口由存儲(chǔ)引擎層執(zhí)行真正的工作。

解析器

數(shù)據(jù)庫(kù)的解析器先對(duì)sql語句進(jìn)行詞法分析,分析出哪些是關(guān)鍵字,表名,屬性,然后進(jìn)行語法分析,創(chuàng)建出語法出語法數(shù),進(jìn)行權(quán)限認(rèn)證。

優(yōu)化器

優(yōu)化器的主要作用是制定一個(gè)高效的執(zhí)行計(jì)劃,對(duì)語句的優(yōu)化分為邏輯上的優(yōu)化比如說是否可以將一個(gè)子查詢改寫為一個(gè)多表連接語句(因?yàn)樽硬樵儠?huì)創(chuàng)建臨時(shí)表并且不能夠使用索引)和物理上的優(yōu)化比如說使用什么樣的索引可以增加查詢的速度等等。

查詢緩存

查詢緩存其實(shí)就是mysql中一個(gè)kv鍵值對(duì)的存儲(chǔ)空間它將對(duì)應(yīng)的sql語句作為key,執(zhí)行的結(jié)果作為value。如果后續(xù)執(zhí)行相同的語句可以通過緩存直接得到結(jié)果。 弊端:查詢緩存中以sql語句作為key,只要輸入的語句有一點(diǎn)點(diǎn)不同即使語句的語義一致也不能夠使用上緩存。針對(duì)一些函數(shù)比如說時(shí)間函數(shù)now,會(huì)改變語句中的時(shí)間頁使用不到緩存。對(duì)數(shù)據(jù)庫(kù)的改變會(huì)刷新緩存降低命中率 Oracle中的緩存設(shè)計(jì),使用到一個(gè)共享池的概念,它不僅僅會(huì)緩存語句還會(huì)緩存對(duì)應(yīng)的執(zhí)行計(jì)劃,而且它還利用一種類似函數(shù)的機(jī)制有利于批量處理數(shù)據(jù)。

存儲(chǔ)引擎層

存儲(chǔ)引擎以前有個(gè)很土的名字叫做表處理器,這個(gè)名字更能夠讓我們了解其的作用。其實(shí)每個(gè)存儲(chǔ)引擎就是對(duì)應(yīng)著不同應(yīng)用場(chǎng)景下設(shè)計(jì)不同數(shù)據(jù)庫(kù)表的存儲(chǔ)方式,在不同的存儲(chǔ)結(jié)構(gòu)上面構(gòu)建具有不同作用不同性能的表處理器。
例如最經(jīng)典的INNODB存儲(chǔ)引擎在5.0階段的存儲(chǔ)結(jié)構(gòu)就是由.opt文件來存儲(chǔ)一些數(shù)據(jù)庫(kù)通用的設(shè)置,由.frm文件存儲(chǔ)表的結(jié)構(gòu)由.ibd文件來存儲(chǔ)數(shù)據(jù)和索引(innodb中有一句很經(jīng)典的話叫做數(shù)據(jù)即索引,索引即數(shù)據(jù));在升級(jí)到mysql8.0之后mysql的存儲(chǔ)結(jié)構(gòu)變成了.ibd文件一個(gè)它將數(shù)據(jù)庫(kù)配置信息,表結(jié)構(gòu)信息,和索引數(shù)據(jù)都存儲(chǔ)在一個(gè)文件中。
再比如MYIAM存儲(chǔ)引擎,它底層的表存儲(chǔ)結(jié)構(gòu)為使用.frm文件來存儲(chǔ)表結(jié)構(gòu),分別使用.myi,.myd文件存儲(chǔ)索引和數(shù)據(jù),這也導(dǎo)致它在索引的設(shè)計(jì)上和innodb有一些細(xì)微的差別

查看和設(shè)置存儲(chǔ)引擎

對(duì)于數(shù)據(jù)庫(kù)存儲(chǔ)引擎的查看和設(shè)置

查看mysql所有支持的存儲(chǔ)引擎:
show engines
查看存儲(chǔ)引擎相關(guān)的信息:
show variables like “%storage_engine%”
show variables like “default_storage_engine”

對(duì)于表級(jí)別存儲(chǔ)引擎的設(shè)置和修改
可以在表定義的時(shí)候在后面跟上

engine = “InnoDB”
可以修改表的結(jié)構(gòu)來修改存儲(chǔ)引擎:
alter table table_name engine = “innoDB”

各種存儲(chǔ)引擎的介紹

InnoDB

InnoDB是在mysql5.5之后默認(rèn)的存儲(chǔ)引擎,優(yōu)點(diǎn)在于其支持事務(wù),缺點(diǎn)在于它對(duì)比MYISAM上性能會(huì)有所偏差

MYSISAM

MYISAM存儲(chǔ)引擎主要適合用于處理讀比較多的業(yè)務(wù)場(chǎng)景。
優(yōu)點(diǎn)在于它的性能會(huì)比較好
缺點(diǎn)在于它不支持事務(wù),行級(jí)別的鎖,外鍵等,無法保證失敗回滾

CSV

CSV存引擎可以支持使用excel打開

Archive

Archive的意思是歸檔,所以說這是一個(gè)專門用于歸檔的存儲(chǔ)引擎,它只有增加和查詢操作。并且有很好的壓縮機(jī)制

memory

memory存儲(chǔ)引擎的數(shù)據(jù)表結(jié)構(gòu)使用.frm文件存儲(chǔ)在磁盤上但是其數(shù)據(jù)存儲(chǔ)在內(nèi)存中,適合使用在短時(shí)間內(nèi)訪問的臨時(shí)數(shù)據(jù)。默認(rèn)使用的索引結(jié)構(gòu)是hash索引,并且對(duì)表的字段和大小都有嚴(yán)格的限制。

InnoDB和MYISAM的區(qū)別

①首先從文件系統(tǒng)的存儲(chǔ)結(jié)構(gòu)上來說InnoDB在8.0之前將數(shù)據(jù)庫(kù)通用設(shè)置存儲(chǔ)在.opt文件中,將表機(jī)構(gòu)存儲(chǔ)在.fem文件中,將數(shù)據(jù)和索引存儲(chǔ)在.ibd文件中(所以InnoDB中有一句話叫做索引即數(shù)據(jù)數(shù)據(jù)即索引,因?yàn)樗鼈兪且黄鸫娣诺?#xff09;,在8.0之后將上述的所有信息都存儲(chǔ)在.ibd文件中.而對(duì)于MYISAM存儲(chǔ)引擎來說它將表結(jié)構(gòu)存儲(chǔ)在.frm中,將數(shù)據(jù)存儲(chǔ)在.myi中,將數(shù)據(jù)存儲(chǔ)myd文件中。數(shù)據(jù)和索引是分開存放的這也導(dǎo)致MYISAM中的索引都是通過B+Tree的結(jié)構(gòu)在索引文件中存放然后通過指針指向數(shù)據(jù)的所以在MYISAM中不存在聚簇索引這一說。
②由于底層存儲(chǔ)的結(jié)構(gòu)不一樣導(dǎo)致緩存也不一樣,INnoDB緩存聚簇索引和數(shù)據(jù),MYIASM只緩存數(shù)據(jù)
③由于底層結(jié)構(gòu)不一致所以索引的實(shí)現(xiàn)上也有所不同
④InnoDB提供對(duì)事務(wù)的支持,MYIAM則沒有
⑤InnoDB提供對(duì)行鎖的支持,MYIAM沒有
⑥InnoDB支持外鍵MYIAMmy
⑦總結(jié)來說不同的存儲(chǔ)引擎設(shè)置不一樣的底層表存儲(chǔ)結(jié)構(gòu)為了適應(yīng)不一樣的業(yè)務(wù)場(chǎng)景,InnoDb側(cè)重事務(wù)性,MyIAM側(cè)重性能

物理層

物理層是真正硬件中存儲(chǔ)mysql中數(shù)據(jù)庫(kù)表和每一行數(shù)據(jù)的地方,為了不讓mysql大部分工作在磁盤中完成,mysql在內(nèi)存中分配了一塊緩存以減少磁盤工作和IO時(shí)間大大增加mysql的提高了mysql的整體性能。

數(shù)據(jù)庫(kù)緩沖池

數(shù)據(jù)庫(kù)緩沖池其實(shí)就是在內(nèi)存中開辟一塊空間用于存儲(chǔ)頁,減少磁盤IO的時(shí)間和磁盤的哦工作提升數(shù)據(jù)庫(kù)的整體性能。 緩沖的規(guī)則:數(shù)據(jù)庫(kù)緩沖池的緩沖規(guī)則是“位置 * 頻率”,其中位置表示的磁盤能夠快速檢索到的位置,頻率指的是數(shù)據(jù)庫(kù)頁的使用頻率。對(duì)于使用頻率較高的數(shù)據(jù)它不僅僅會(huì)緩存本頁的數(shù)據(jù)還會(huì)連帶著緩存上下頁的數(shù)據(jù)提高數(shù)據(jù)庫(kù)的整體執(zhí)行效率。

MYSQL索引

為什么要有索引:如果數(shù)據(jù)庫(kù)的底層不存在索引,那么我們查詢數(shù)據(jù)就需要全表掃描效率極低 什么是索引:索引是快速檢索(基于某一種數(shù)據(jù)結(jié)構(gòu)組織數(shù)據(jù),并且在該種數(shù)據(jù)結(jié)構(gòu)上執(zhí)行對(duì)應(yīng)的檢索算法)數(shù)據(jù)的數(shù)據(jù)結(jié)構(gòu)?;诓煌拇鎯?chǔ)引擎索引有著不同的實(shí)現(xiàn)。 索引的特點(diǎn)就是排序和檢索

優(yōu)缺點(diǎn)

優(yōu)點(diǎn):
①加快數(shù)據(jù)檢索的速度
②對(duì)于數(shù)據(jù)加上唯一索引能夠保證數(shù)據(jù)的唯一性
③使用索引對(duì)數(shù)據(jù)的排序和分組有很大的性能提升
④使用索引可以加快多表連接
缺點(diǎn):
①創(chuàng)建索引需要一定的時(shí)間
③索引需要一定的存儲(chǔ)空間存放
③雖然索引有利于快速查找數(shù)據(jù),但是對(duì)于數(shù)據(jù)的修改更新和刪除需要付出更多的成本來維護(hù)數(shù)據(jù)和索引

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

B+Tree

為什么是B+Tree

索引底層的機(jī)構(gòu)剛剛開始并不是B+Tree,通過一代代的更新迭代的。
一、首先我們想到的檢索數(shù)據(jù)的結(jié)構(gòu)是hash,它的優(yōu)點(diǎn)在于插入和查詢的復(fù)雜度都是O(1)級(jí)別的。但是這種復(fù)雜度是用于檢索一條數(shù)據(jù)的,當(dāng)檢索范圍數(shù)據(jù)時(shí)它逐條掃描,掃描一次IO一次效率十分低下,而且還存在著hash碰撞的情況。但是我們?cè)诓樵儠r(shí)還是可以使用自適應(yīng)性hash的,它可以讓我們快熟定位到數(shù)據(jù)頁。
二、第二個(gè)快速檢索的數(shù)據(jù)結(jié)構(gòu)就是樹形結(jié)構(gòu),在樹形結(jié)構(gòu)中檢索和插入的時(shí)間復(fù)雜度能夠達(dá)到logn級(jí)別
①首當(dāng)其沖的數(shù)據(jù)結(jié)構(gòu)是二叉樹,二叉樹的缺點(diǎn)是當(dāng)我們按照順序插入數(shù)據(jù)時(shí)它就會(huì)退化為一個(gè)鏈表,那么我們檢索數(shù)據(jù)無異于全表掃描。
②接著考慮書的平衡性,我們就使用平衡二叉樹(AVL數(shù)樹),但是平衡二叉樹的缺點(diǎn)在于,它雖然可以有效控制樹的平衡性但是數(shù)據(jù)庫(kù)所需要的樹是要盡量能夠減少磁盤IO的樹也就是說樹的高度不能夠太高所以不能夠使用AVL樹
③我們考慮使用B-Tree(多路平衡搜索樹),這樣增加每個(gè)節(jié)點(diǎn)的兒子節(jié)點(diǎn)數(shù)量,大大減小了樹的高度,有效控制磁盤IO。
④我們使用B+Tree(改進(jìn)的多路平衡搜索樹),它對(duì)于B-Tree的改進(jìn)在于它不在非葉子節(jié)點(diǎn)存儲(chǔ)數(shù)據(jù),二十將所有的數(shù)據(jù)都放到葉子節(jié)點(diǎn)使用一個(gè)雙向鏈表的結(jié)構(gòu)連接起來。
好處在于,非葉子節(jié)點(diǎn)現(xiàn)在只存儲(chǔ)索引不存儲(chǔ)真實(shí)的數(shù)據(jù)這樣能夠讓樹的分支更多有效降低了樹的高度,減少了IO的次數(shù)。底層使用雙向鏈表的結(jié)構(gòu)將所有的數(shù)據(jù)按照大小的順序排列這樣有利于檢索范圍的數(shù)據(jù),對(duì)于B樹來說如果要檢索范圍的數(shù)據(jù)則需要中序遍歷。

B+Tree索引的介紹
數(shù)據(jù)庫(kù)索引的推演過程

推演的過程:
①首先設(shè)想數(shù)據(jù)庫(kù)中不存在索引,那么一個(gè)表中的數(shù)據(jù)是散落在一個(gè)個(gè)的頁中的,各個(gè)頁之間使用雙向鏈表的結(jié)構(gòu)連接起來這個(gè)數(shù)據(jù)記錄在頁首部的字段中。各個(gè)頁的內(nèi)部使用向鏈表的結(jié)構(gòu)來組織存儲(chǔ),各個(gè)記錄之間的指針信息存儲(chǔ)在字段首部信息中。這樣我們要檢索一個(gè)數(shù)據(jù)就要從第一頁開始逐條搜索,然后通過指針信息跳轉(zhuǎn)到下一個(gè)頁中,接著逐條掃描,效率極其低下。
②那我們就會(huì)想使用一個(gè)數(shù)據(jù)結(jié)構(gòu)給本結(jié)構(gòu)做一個(gè)優(yōu)化處理,于是想到在數(shù)據(jù)頁的上一層建立一層索引頁(其實(shí)也是數(shù)據(jù)頁區(qū)別在于索引頁中的記錄類型和記錄頭信息有細(xì)微的差別),這樣我們就可以先訪問索引頁找到對(duì)應(yīng)的頁位置大大減小了IO的次數(shù)。
③當(dāng)插入的數(shù)據(jù)過多底層產(chǎn)生頁分裂導(dǎo)致上層索引頁不夠記錄數(shù)據(jù),索引頁頁產(chǎn)生了頁分裂,這樣我們就需要在索引頁上層頁再建立一層索引頁。保證整個(gè)索引的訪問結(jié)構(gòu)中樹只有一個(gè)根節(jié)點(diǎn)(這個(gè)跟節(jié)點(diǎn)頁一般時(shí)存儲(chǔ)在內(nèi)存當(dāng)中的,當(dāng)需要使用索引時(shí)就可以減少一次IO操作,這也是為什么數(shù)據(jù)的訪問只需要兩次或者三次IO的原因)

推演中三個(gè)需要糾正的點(diǎn)

①根節(jié)點(diǎn)的位置萬年不變,我們上述的推到過程時(shí)從下往上的推到,而現(xiàn)實(shí)中的B+Tree創(chuàng)建時(shí)從上往下的,當(dāng)一個(gè)索引頁中的數(shù)據(jù)不夠存放時(shí)會(huì)產(chǎn)生頁分裂這個(gè)時(shí)候創(chuàng)建一個(gè)新的頁將本頁中的數(shù)據(jù)copy到新的頁中然后將本頁的指針指向新創(chuàng)建的索引頁中。
②索引中數(shù)據(jù)記錄要保證唯一性,所以創(chuàng)建索引時(shí)不單單要保存當(dāng)前的數(shù)據(jù)記錄,為了保證每個(gè)節(jié)點(diǎn)的唯一性還需要保存當(dāng)前表的主鍵值。
③由于我們要?jiǎng)?chuàng)建的是一個(gè)是一個(gè)樹型結(jié)構(gòu)所以索引頁的分支不能少于二

B+Tree索引的文件存儲(chǔ)結(jié)構(gòu)

mysql管理數(shù)據(jù)底層存儲(chǔ)的層級(jí)分為,表空間,段,區(qū),頁,數(shù)據(jù)行

表空間

表空間是mysql中一個(gè)邏輯概念,mysql的表空間中我們需要了解的就是系統(tǒng)表空間和獨(dú)立表空間兩種

####### 系統(tǒng)表空間

系統(tǒng)表空間在mysql5.5之前可以用于存儲(chǔ)用戶表中的數(shù)據(jù)和系統(tǒng)表中的數(shù)據(jù),但是在5.6之后只能用于存儲(chǔ)系統(tǒng)表中的數(shù)據(jù)。mysql系統(tǒng)數(shù)據(jù)庫(kù)主要有如下幾個(gè)
①information_schame:這個(gè)數(shù)據(jù)庫(kù)中存儲(chǔ)的主要是數(shù)據(jù)庫(kù)的一些配置參數(shù)信息比如說使用的存儲(chǔ)引擎信息,設(shè)置的字符集信息等
②performance—_schame:這個(gè)數(shù)據(jù)庫(kù)中存儲(chǔ)的主要是數(shù)據(jù)庫(kù)運(yùn)行的一些狀態(tài)信息比如說我們的profile信息等。
③sys:為了更加方便查閱數(shù)據(jù)庫(kù)中的信息我們將一些經(jīng)常需要查詢大的數(shù)據(jù)庫(kù)配置信息和狀態(tài)信息存儲(chǔ)在這個(gè)數(shù)據(jù)庫(kù)中。

####### 獨(dú)立表空間

獨(dú)立的表空間在mysql5.6之后專門用于存儲(chǔ)用戶自定義的數(shù)據(jù)庫(kù)中的信息,我們表中的ibd文件都存儲(chǔ)在獨(dú)立表空間中。
好處:
①有利于數(shù)據(jù)的遷移
②有利于表空間的回收

mysql中的段主要包括,數(shù)據(jù)段,索引段,系統(tǒng)段,事務(wù)段,undo段等等。我們將數(shù)據(jù)組織成B+Tree之后樹中有分為索引頁和數(shù)據(jù)頁為了訪問對(duì)應(yīng)的數(shù)據(jù)更加純粹我們分出了段的概念。

區(qū)

為什么要有區(qū):
這個(gè)涉及到數(shù)據(jù)頁訪問的效率,比如說我們?cè)趦?nèi)存中訪問一個(gè)數(shù)據(jù)頁大概需要1ms的時(shí)間,在磁盤上使用隨機(jī)IO訪問一頁數(shù)據(jù)的時(shí)間大概是10ms(大部分的時(shí)間浪費(fèi)在半圈旋轉(zhuǎn),尋道和排隊(duì)等待上而真正用于IO的時(shí)間只有十分之一),如果在磁盤上使用順序IO呢,在大批量加載的前提下訪問一個(gè)數(shù)據(jù)頁的時(shí)間只需要0.4ms。至此我們看到了隨機(jī)IO和順序IO的效率差別還是很大的所以我們?cè)L問數(shù)據(jù)的時(shí)候應(yīng)該盡可能使用順序IO來提升數(shù)據(jù)訪問的效率。區(qū)就此誕生它將64個(gè)頁組織成一個(gè)連續(xù)的存儲(chǔ)空間(大小正好為1MB),方便我們?cè)诜秶@一個(gè)區(qū)的數(shù)據(jù)時(shí)時(shí)順序IO。而區(qū)和區(qū)之間再使用指針來連接做到物理上的來連續(xù)。
區(qū)的分類:
要介紹區(qū)的分類首先得引入一個(gè)概念叫做碎片區(qū),我們?cè)O(shè)想很小的數(shù)據(jù)量情況下我們需要在數(shù)據(jù)段和索引段中各種劃分出一個(gè)區(qū)也就是2M的存儲(chǔ)空間來存儲(chǔ)比如說10kb的數(shù)據(jù),這太浪費(fèi)空間了。所以對(duì)于著一些占用很小空間的數(shù)據(jù)我們完全可以讓它們共享一個(gè)區(qū),而這個(gè)區(qū)就叫做碎片區(qū)。所以MySQL底層在分配空間的時(shí)候,碎片區(qū)首先時(shí)隸屬于表空間的當(dāng)某一個(gè)數(shù)據(jù)占有超過32個(gè)區(qū)的時(shí)候再給它分配一個(gè)專門的段。
所以區(qū)的分類就出來了:
①空閑區(qū)
②帶有剩余空間的碎片區(qū)
③不帶有空閑空間的碎片區(qū)
④隸屬于某一個(gè)段的區(qū)

頁是內(nèi)存和磁盤交互的基本單位(基本單位的意思是說,不管我們只需要獲取修改一個(gè)頁中的一條或者幾條數(shù)據(jù),都需要加載完整的頁和寫入完整的頁)一個(gè)頁的大小默認(rèn)是64kB。
頁的底層存儲(chǔ)結(jié)構(gòu)是雙向鏈表結(jié)構(gòu),頁內(nèi)部則是采用單向鏈表來存儲(chǔ)每一條數(shù)據(jù)。

####### 頁的存儲(chǔ)格式

頁的存儲(chǔ)格式主要分為七個(gè)部分我們將這七個(gè)部分分為三類來分卸:
一、:文件的頭尾
文件頭存儲(chǔ)的信息包括:文件屬于什么類型,頁號(hào),頁的前后指針,校驗(yàn)和以及日志文件中記錄的位置
文件尾存儲(chǔ)的信息:就只有校驗(yàn)和和日志文件中記錄的位置

其中最重要的兩個(gè)部分就是校驗(yàn)和和日志文件中存儲(chǔ)的位置。
首先我們看看校驗(yàn)和到底是個(gè)什么東西,當(dāng)一個(gè)文件很長(zhǎng)的時(shí)候我們可以使用抽樣算法抽取出文件中的主要信息相當(dāng)于形成一個(gè)文件的指紋用于標(biāo)識(shí)一個(gè)文件。這個(gè)指紋就叫做校驗(yàn)和。那么它的作用就是當(dāng)一個(gè)頁被加載到內(nèi)存中使用和修改之后會(huì)修改它的頭尾校驗(yàn)和,當(dāng)刷盤中出現(xiàn)錯(cuò)誤時(shí),就會(huì)導(dǎo)致首尾的校驗(yàn)和不一致的問題這個(gè)時(shí)候我們就能夠識(shí)別這一種錯(cuò)誤,采取回滾或者借助redo日志完成刷盤操作。

日志文件的記錄位置頁是起到這一個(gè)作用

二、頁頭和頁目錄
頁頭存儲(chǔ)著野種許多零零碎碎的信息,比如頁中有多少條記錄,有多少個(gè)用于頁目錄訪問的槽位以及頁中刪除鏈表的信息等。

頁目錄:
引入頁目錄的原因是為了快速查找一個(gè)頁面中的數(shù)據(jù),他的設(shè)計(jì)是這樣的為了減少空間的使用它將數(shù)據(jù)分為一組一組最小記錄為一組其他記錄按照達(dá)到九個(gè)分裂出四個(gè)的方式分組。我們只要記錄每組中最大的記錄作為一個(gè)槽位來進(jìn)行二分法查找如果,具體的查找過程由于單鏈表單向訪問的特點(diǎn)所以我們要查找一組中的數(shù)據(jù)的時(shí)候需要查找它的上一個(gè)分組中的最大記錄順序往下。
這個(gè)還涉及到了行格式中行頭部信息的一個(gè)用于記錄一組中有多少個(gè)記錄的一個(gè)標(biāo)志位,這個(gè)標(biāo)志位只會(huì)存在于一組中最大的記錄中。

三、:最大最小記錄,頁記錄,空閑空間
最大最小記錄很好理解就是一頁中最大的額和最小的它們存儲(chǔ)在頭部中并且記錄的編號(hào)為0和1

頁記錄:這個(gè)位置就是真正用于記錄我們每一條記錄的位置

剩余空間:就是我們這個(gè)頁還有多多少可用的空間。

數(shù)據(jù)行

####### 數(shù)據(jù)行格式

數(shù)據(jù)行的格式大體上分為四種:
compact,dynamic,compressed,redundant其中最主要需要了解的就是compact其他的格式都和它大同小異。

######## compact

compact格式大體上分為額外記錄的信息和行數(shù)據(jù),額外記錄的信息中包括邊長(zhǎng)字段長(zhǎng)度列表和null值列表記錄頭信息,行行記錄信息分為隱藏列信息和真實(shí)數(shù)據(jù)。

######### 額外信息

########## 變長(zhǎng)字段長(zhǎng)度列表

變長(zhǎng)字段長(zhǎng)度列表主要用于記錄我們的表記錄中邊長(zhǎng)字段真實(shí)使用的長(zhǎng)度信息,它的記錄方式是從尾到頭記錄我們變長(zhǎng)字段長(zhǎng)度

########## null值列表

null值列表的意思是使用一個(gè)bit位來記錄我們的字段是否為null并且它也是倒序存放d

########## 記錄頭信息

記錄頭信息記錄以下幾個(gè)信息:
表中字段的類型,序號(hào),下一條記錄的位置,以及三個(gè)屬性分別為當(dāng)前的記錄是否被刪除(被刪除的記錄會(huì)標(biāo)識(shí)為1并且所有已經(jīng)被刪除的記錄組成一個(gè)鏈表方便后期使用),該條記錄是否是頁中一組中的最小值以及一組中數(shù)據(jù)的個(gè)數(shù)

######### 真是數(shù)據(jù)信息

########## 隱藏列數(shù)據(jù)

隱藏列主要有如下三條:
①本條記錄的rou_id:這個(gè)值用于唯一標(biāo)識(shí)一條記錄,當(dāng)我們的數(shù)據(jù)表中不存在主鍵和唯一字段時(shí)就是使用這個(gè)字段來作為主鍵
②事務(wù)id
③回滾指針

########## 表記錄數(shù)據(jù)

######## dynamic

######## compressed

######## redundant

基于不同存儲(chǔ)引擎的實(shí)現(xiàn)

InnoDB 底層索引
索引分類

####### 聚簇索引

聚簇索引其實(shí)就是mysql通過主鍵創(chuàng)建的一個(gè)索引(如果表中有主鍵直接通過表中的主鍵創(chuàng)建,如果沒有主鍵但是存在唯一約束字段就會(huì)通過這個(gè)字段創(chuàng)建,如果兩者都沒則會(huì)自動(dòng)生成一個(gè)字段來代表主鍵)這個(gè)索引的底層存儲(chǔ)的是表中的整行記錄
優(yōu)點(diǎn):
①索引及數(shù)據(jù),數(shù)據(jù)即索引,查找的速度很快
②對(duì)于排序和范圍的數(shù)據(jù),可以做到快速查找
③減少IO
缺點(diǎn):
①對(duì)于表記錄的修改操作(增,刪,改)我們?yōu)榱司S護(hù)現(xiàn)在的聚簇索引結(jié)構(gòu)可能會(huì)出現(xiàn)頁分裂,記錄移位,記錄換位的情況
②二級(jí)索引需要借助主鍵索引才能訪問到其他列中的數(shù)據(jù)

####### 非聚簇索引(二級(jí)索引,輔助索引)

非聚簇索引(也叫二級(jí)索引或者輔助索引),就是通過非主鍵字段創(chuàng)建的索引它的底層存儲(chǔ)的是該字段的值以及主鍵字段的值。InnoDB中有個(gè)詞叫做回表,如果要查詢的字段就在這個(gè)索引底層存儲(chǔ)表示我們可以通過這個(gè)索引來直接的到數(shù)據(jù)這樣獲取到的數(shù)據(jù)就叫做索引覆蓋,如果在這個(gè)索引中得不到數(shù)據(jù)就需要根據(jù)主鍵的值在聚簇索引中進(jìn)行一個(gè)回表操作獲得值。

####### 聯(lián)合索引

聯(lián)合索引(或者叫多列索引),就是通過多個(gè)字段共同構(gòu)建的索引會(huì)根據(jù)聲明索引的順序先后按照字段排序組織索引。

MYISAM底層索引

MYISAM存儲(chǔ)引擎的表文件系統(tǒng)表存儲(chǔ)結(jié)構(gòu)時(shí)將索引和數(shù)據(jù)分離的,所以在MYIAM中不存在聚簇索引,非聚簇索引這一說。
它的底層也是通過B+Tree實(shí)現(xiàn)的只不過它的葉子節(jié)點(diǎn)中存儲(chǔ)的是指向數(shù)據(jù)的指針。

MYISAM和InnoDB索引對(duì)比

①首先二者文件存儲(chǔ)結(jié)構(gòu)不同,InnoDb將數(shù)據(jù)和索引存儲(chǔ)在一個(gè)文件中,MyIAM將數(shù)據(jù)和索引分別存儲(chǔ)
②MYISAM中的索引通過字段組織二叉樹,葉子節(jié)點(diǎn)存儲(chǔ)的是數(shù)據(jù)的地址,InnoDb存儲(chǔ)的是真正的數(shù)據(jù),所以MYISAM中的索引其實(shí)都是需要回表操作的但是它的回表操作是通過地址直接獲取到數(shù)據(jù)不像InnoDB中通過主鍵索引去獲取數(shù)據(jù)效率低下
③InnoDB中的索引分為聚簇索引和非聚簇索引使用聚簇索引可以快速查找到數(shù)據(jù)不需要回表,非聚簇索引借助聚簇索引查找數(shù)據(jù)。聚簇索引要求InnoDB中必須要有主鍵,MYIAM是可以沒有主鍵的

索引的增刪改查以及MYSQL8.0中索引的新特性

索引的增刪改查

索引的創(chuàng)建

索引其實(shí)可以在兩個(gè)時(shí)機(jī)創(chuàng)建第一個(gè)時(shí)在建表的時(shí)候創(chuàng)建索引,第二個(gè)實(shí)在建表之后創(chuàng)建索引

建表的時(shí)候創(chuàng)建索引

####### 隱式創(chuàng)建

其實(shí)對(duì)于主鍵索引(也就是我們所說的聚簇索引)在聲明表的主鍵的時(shí)候就已經(jīng)創(chuàng)建,而對(duì)表的唯一約束則時(shí)和唯一索引綁定,我們?cè)诼暶魑ㄒ患s束的時(shí)候就已經(jīng)創(chuàng)建了一個(gè)唯一索引

####### 顯式創(chuàng)建索引

在建表的時(shí)候顯式創(chuàng)建索引其實(shí)只需要在建表語句的最后和加約束一樣加上創(chuàng)建索引的語句就可以:
eg:
create table table_name(
id int primary key,
name char(10) unique,
index index_name(col1,col2)
);

在建表之后創(chuàng)建索引

在建表之后創(chuàng)建索引的方式有兩種:
①使用alter table 語句創(chuàng)建
eg:alter table add index index_name(col1,col2);
②使用create index index_name on table_name(col1,col2);

索引的刪除

索引的刪除也有兩種方式:
①通過alter table語句刪除
alter table table_name drop index
index_name;
②通過drop index… on…語句刪除
eg:drop index index_name on table_table_name;

如何查看一個(gè)表中的索引

eg:show index from table_name

MYSQL8.0中索引的新特性

隱藏索引

隱藏索引其實(shí)可以看作時(shí)間索引開啟或者關(guān)閉,用于測(cè)試有索引和沒有索引時(shí)數(shù)據(jù)庫(kù)的查詢xing’neng

降序索引

在mysql5的版本中其實(shí)就有降序索引的功能但是其底層組織索引還是使用升序索引只是在訪問時(shí)反著訪問而已,但是在mysql8.0之后真正的將索引數(shù)據(jù)降序組織

索引的分類

按照邏輯功能分類

按照邏輯功能分類索引可以分為主鍵索引,唯一索引,全文索引。普通索引

按照物理組織方式分類

按照物理組織方式對(duì)索引分類可以分為聚簇索引和非聚簇索引

按照索引的列數(shù)

按照索引的列數(shù)分類可以將索引分為單列索引和多列索引

索引創(chuàng)建的原則

什么情況下可以使用索引

①針對(duì)列來說
對(duì)于重復(fù)低的列(一個(gè)可參照的數(shù)據(jù)時(shí)%33),具有唯一約束的列,使用distinct的列,列的類型占用字節(jié)較小的,對(duì)于字符串類型的值需要對(duì)字符串的前綴建立索引
②針對(duì)語句來說
where語句中經(jīng)常使用的列(這里的where手的時(shí)select,update和delete),group by和order by,對(duì)于連表查詢的字段建立索引前提是兩個(gè)連表查詢的字段類型要一致
③針對(duì)聯(lián)合索引來說
對(duì)于經(jīng)常一起使用的字段建立索引,需要注意最左前綴pi’pei

什么情況下不可以使用索引

從表的角度來說:
對(duì)于數(shù)據(jù)量較小的表不需要建立索引,對(duì)于經(jīng)常更新的表不需要建立索引
從列的角度來說:
數(shù)據(jù)上來考慮對(duì)于重復(fù)度較高(%33),無序的數(shù)據(jù)不需要建立索引對(duì)于where使用不到的字段不建立索引

不要?jiǎng)?chuàng)建過多的索引

①刪除冗余的索引
②刪除使用不到或者使用少的索引

數(shù)據(jù)庫(kù)性能分析

數(shù)據(jù)庫(kù)調(diào)優(yōu)的過程

①首先得查看服務(wù)器是否存在性能忽高忽低的情況如果存在就需要加上緩存。
②開啟慢查詢?nèi)罩?#xff0c;查看慢sql,對(duì)失去了語句使用性能分析工具驚醒分析,查看是sql執(zhí)行的等待時(shí)間過長(zhǎng)還是執(zhí)行時(shí)間過長(zhǎng)。如果是等待時(shí)間過長(zhǎng)則需要配置服務(wù)器參數(shù)。如果是執(zhí)行時(shí)間過長(zhǎng)則查看是否是是表結(jié)構(gòu)問題,索引的問題還是join語句過多導(dǎo)致的。
③如果性能還是不好則試著數(shù)據(jù)庫(kù)分庫(kù)分表,主從復(fù)制讀寫分離。

性能分析工具的使用

慢查詢?nèi)罩?/h5>

①慢查詢?nèi)罩镜拈_啟和關(guān)閉
使用“slow_query_log”參數(shù)開啟和關(guān)閉
②慢查詢?nèi)罩镜膬蓚€(gè)指標(biāo)一個(gè)文件和一個(gè)工具
“l(fā)ong_query_time”:表示最大查詢時(shí)間
“min_examing_rows_limit”:標(biāo)識(shí)查詢的條數(shù)
“slow_query_log_file”指定慢查詢?nèi)罩疚募?br /> 使用mysqldumpslowk可以分析慢查詢?nèi)罩?br /> ③如何查看慢查詢
使用:show status like "Slow_queries"查看慢查詢語句

Explain

explain分析工具用于分析一條sql語句的執(zhí)行計(jì)劃,一條查詢語句再?gòu)?fù)雜最終也得對(duì)每一個(gè)表進(jìn)行訪問,所以explain的每一條記錄代表著一個(gè)表的訪問方式,每一個(gè)id代表著一條查詢語句的執(zhí)行。它可以使用explain或者describe關(guān)鍵字來查看

使用explain的注意點(diǎn)

在sql5.6之前explain只能對(duì)select語句使用explain在5.6的后續(xù)版本中就可以使用explain查看delete,insert和update
在5.7版本explain中的patitions和filtered需要使用系統(tǒng)表查看,在后續(xù)版本中直接可以在explain查看

四種查看方式

它的查看方式分為comand窗口查看,可視化工具查看或者使用json和Tree的形式查看

各列的信息

由于explain是針對(duì)表的訪問方法確定的所以有一下分類:
①id和select_type為一類表示查詢語句的編號(hào)和查詢類型
②涉及到表的分別有table,type,patitions為一類標(biāo)表示表名稱和表的訪問類型,表分區(qū)的具體信息
③possible_keys,key,key_len和ref分為一類表示可能使用的索引,使用的索引,索引的長(zhǎng)度和等職比較的具體信息
④rows,filter分為一類用于表示是否為范圍一共訪問到的記錄條數(shù)和過濾的百分比
⑤extra單獨(dú)為一類表示額外的信息

####### 查詢的信息

?

######## id

一個(gè)id用于表示一條查詢語句,id的訪問優(yōu)先級(jí)從大到小1,如果優(yōu)先級(jí)相同則從上到下

######## select_type

select_type用于表示本查詢?cè)诳傮w查詢中是什么樣的地位:
simple:簡(jiǎn)單查詢
primary:
union:聯(lián)合結(jié)果
union_result:聯(lián)合結(jié)果產(chǎn)生去重的臨時(shí)表
dependent_union:使用in和exist會(huì)產(chǎn)生相關(guān)的聯(lián)合
subquery:子查詢
dependent_subquery:相關(guān)子查詢

####### 表的信息

######## table:

這條記錄中被發(fā)訪問的表名

######## type:

表的訪問方式,主要分為一下幾種:
system:表中只有一條記錄,并且所使用的存儲(chǔ)引擎提供的數(shù)據(jù)是精確的
const:采用主鍵索引或者唯一索引匹配一個(gè)常量
eq_ref:使用主鍵索引或者唯一索引聯(lián)表查詢
ref:使用普通索引進(jìn)行常量查詢
unique_subquery:使用唯一索引或者主鍵索引子查詢
range:使用索引匹配方范圍數(shù)據(jù)
index:使用全索引掃描
all:全表掃描

######## patitions

所使用的表是否是分區(qū)表,分區(qū)表的具體信息

####### 索引的信息

######## possible_keys

這個(gè)查詢中可能使用到的索引,這個(gè)索引數(shù)量越多越不好因?yàn)椴樵儍?yōu)化器需要諸葛排除選出最好索引,可以使用的索引太多了導(dǎo)致判斷的時(shí)間過長(zhǎng)

######## key

真正使用到的索引

######## key_len

使用到的索引的長(zhǎng)度,這個(gè)長(zhǎng)度的計(jì)算首先根據(jù)不同的字符集確定初始長(zhǎng)度,再加上兩個(gè)字節(jié)代表邊長(zhǎng)字段長(zhǎng)度列表再叫上一個(gè)字節(jié)代表null值列表

######## ref

這個(gè)用于判斷等職匹配的的值的基本信息可以和查詢的類型一起判斷

####### 訪問條數(shù)

######## rows

篩選出來訪問到的記錄數(shù)量

######## filtered

過濾率

####### 額外的信息

?

######## extra

這個(gè)用于記錄整個(gè)sql語句中執(zhí)行的額外信息蕾仕于一句提示,十分重要。
①普通的比如說from中沒有東西那么就不提示信息,如果使用到where直接查詢沒有使用到索引或者回表的就會(huì)提示using where,如果條件不成立就會(huì)使用impossible where
②關(guān)于索引
using index:使用到覆蓋索引
using index condition:使用到索引條件嚇退
③幾種不好的情況:
using buffer:表連接沒有使用到索引創(chuàng)建了緩沖
file sort:排序沒有使用到索引
using temporary:使用到臨時(shí)表,使用distinct,gruop by,union可能會(huì)使用lin’shi’biao

ProFile

ProFile用于查看sql語句的執(zhí)行成本
①開啟和關(guān)閉ProFile
設(shè)置profiling開啟關(guān)閉profile
②查看sql執(zhí)行成本
show profiles
show profile
show profile for query index

trace

trace用于查看sql執(zhí)行的全過程包括優(yōu)化器優(yōu)化的過程

last_query_cost

用于查看最后一條查詢語句的成本

數(shù)據(jù)庫(kù)調(diào)優(yōu)策略

數(shù)據(jù)庫(kù)的優(yōu)化策略中有一個(gè)三角形,分為四個(gè)層次上的優(yōu)化,優(yōu)化成本越低起的作用反而越好。這四個(gè)層次分別是sql以及索引優(yōu)化,表結(jié)構(gòu)優(yōu)化,數(shù)據(jù)庫(kù)系統(tǒng)參數(shù)配置和硬件優(yōu)化

查詢優(yōu)化和索引優(yōu)化

查詢優(yōu)化
關(guān)聯(lián)查詢優(yōu)化

####### 外連接優(yōu)化

外查詢優(yōu)化語句我們應(yīng)該在被驅(qū)動(dòng)表上添加索引,這樣可以將被驅(qū)動(dòng)被的數(shù)據(jù)表訪問類型變成ref提升整體的連接查詢效率

####### 內(nèi)連接優(yōu)化

①如果連接的表都沒有或者都有索引,那么內(nèi)連接遵循小表驅(qū)動(dòng)大表的原則。
②如果有一個(gè)表的連接字段上有索引那么該表就會(huì)被當(dāng)作是被驅(qū)動(dòng)biao

####### 關(guān)聯(lián)查詢的底層原理

關(guān)聯(lián)查詢的底層原理是Nested Loop Join(嵌套循環(huán)連接)這個(gè)優(yōu)點(diǎn)i像我們學(xué)習(xí)編程中的循環(huán)語句。
NLJ分為如下幾種:
①SNLJ(Simple Nested Loop Join)
簡(jiǎn)單的嵌套循環(huán)連接就像編程語言中的嵌套循環(huán)一樣先從外層循環(huán)找一條記錄,然后取出連接字段,到內(nèi)層表當(dāng)中逐個(gè)匹配如果匹配上了就當(dāng)作是一條記錄。
②BNLJ(Bolck Nested Loop Join)
簡(jiǎn)單的嵌套循環(huán)連接每次取出外層的一條記錄對(duì)比內(nèi)層記錄之后就會(huì)釋放內(nèi)存數(shù)據(jù)等到下一次接著加載內(nèi)層循環(huán)的數(shù)據(jù),塊嵌套循環(huán)連接其實(shí)在其基礎(chǔ)上做了優(yōu)化,在內(nèi)存中多了一個(gè)join buffer,使得外層循環(huán)中多條記錄重用內(nèi)層循環(huán)的數(shù)據(jù),不用每次都加載,一定程度上提升了性能
③INLJ(Index Nested Loop Join)
索引嵌套循環(huán)優(yōu)化其實(shí)可以看組是內(nèi)層連接使用到了索引復(fù)雜度降低到了logn
④在MySQL8.0.20之后的版本中表連接使用Hash Join的方式進(jìn)行

子查詢優(yōu)化

子查詢其實(shí)就是一條查詢語句能夠做到平常多條查詢語句的查詢效果,也就是內(nèi)查詢的結(jié)果是外查詢提供給外查詢使用,這樣可以有效減少數(shù)據(jù)庫(kù)交互的次數(shù)。但是內(nèi)查詢?cè)谑褂蒙弦泊嬖诤芏嗳秉c(diǎn):
①內(nèi)查詢會(huì)生成臨時(shí)表
②內(nèi)查詢生成的臨時(shí)表沒辦法使用索引

優(yōu)化建議:盡量少寫子查詢,要使用子查詢的地方盡量使用連接查詢來優(yōu)化

order by,group by和limit優(yōu)化

o

####### Order by

①order by上其實(shí)是可以使用索引的,當(dāng)排序和過濾的字段一致使用單列索引,當(dāng)不同時(shí)使用多列索引需要注意最左前綴匹配原則
②當(dāng)沒有辦法使用到索引時(shí)只能使用filesort那么我們就該調(diào)節(jié)對(duì)應(yīng)的數(shù)據(jù)庫(kù)調(diào)優(yōu)參數(shù)將filesort的空間增大

####### Group By

①gruop by語句其實(shí)也是可以使用索引的,當(dāng)我們分組和過濾的列一致時(shí)使用但開裂索引,當(dāng)不一致時(shí)使用多列索引需要注意最所前綴匹配原則
②當(dāng)無法使用索引時(shí)也需要設(shè)置對(duì)飲的數(shù)據(jù)庫(kù)調(diào)優(yōu)參數(shù)
③只有包含分組函數(shù)時(shí)使用having否則一律使用where

####### Limit

使用到Limit時(shí)我們不應(yīng)該直接使用類似于
select * from employees limit 1000,2
對(duì)應(yīng)的優(yōu)化策略有兩條
①當(dāng)所查詢的列能夠直接使用索引時(shí)可以使用索引定位
select id from employees limit 10000,1
②當(dāng)對(duì)應(yīng)的列使用不到索引時(shí)我應(yīng)該直接定位
select * from employees where id > 20000 limit 2

索引優(yōu)化
索引失效的案例

####### 涉及到表的

①表中的字符集應(yīng)該和數(shù)據(jù)庫(kù)的字符集保持一致不然使用時(shí)十分容易出現(xiàn)亂碼導(dǎo)致索引失效
②主鍵插入的時(shí)候應(yīng)該保持遞增排序,如果老是從中間插入主鍵,那么聚簇索引底層不斷出現(xiàn)頁分裂不斷調(diào)整數(shù)據(jù)也和索引頁的數(shù)據(jù)這樣性能很差

####### 涉及到計(jì)算,類型轉(zhuǎn)換,函數(shù)的

①過濾條件中使用計(jì)算函數(shù)類型轉(zhuǎn)換都會(huì)時(shí)索引失效
②當(dāng)使用不等于時(shí)索引失效,比如說<>,!=,NOT NUll等等
③使用like “%abc”索引失效
③使用OR連接條件時(shí)條件中只要有一個(gè)使用不到索引那么其他列都使用不索引

####### 涉及到多列索引

①全職匹配可以直接使用到索引覆蓋,不用回表
②最左前綴原則:索引都是逐級(jí)排序的,當(dāng)使用不到前一段索引后一段頁使用不到。
③碰到范圍列時(shí)索引當(dāng)前列可以使用后面的列失效

覆蓋索引

在InnoDB的索引從物理實(shí)現(xiàn)上細(xì)分為聚簇索引,非聚簇索引兩種。聚簇索引是通過主鍵(如果沒有主鍵就找唯一字段,如果沒有唯一字段就找數(shù)據(jù)行隱藏列中的row_id)排序形成的一個(gè)索引,其底層存放的時(shí)所有的數(shù)據(jù)記錄,非聚簇索引(頁叫做輔助索引或者二級(jí)索引)底層存放的時(shí)主鍵值和本列的值,如果時(shí)多列索引(也叫聯(lián)合索引)底層存放的就是聲明索引的多列值和主鍵值。而我們所提及的覆蓋索引的意思就是我們使用二級(jí)索引并且訪問到的字段就是用于組織索引的字段,不需要通過主鍵再回表查詢。

索引下推

索引條件嚇退發(fā)生在二級(jí)索引,多發(fā)生在多列索引當(dāng)中,當(dāng)使用道二級(jí)索引并且需要回表,我們就可以使用到索引底層那些我們不查詢的數(shù)據(jù)來過濾數(shù)據(jù)達(dá)到回表時(shí)查詢數(shù)據(jù)盡量少的目的提升語句的性能

給字符串添加索引

再阿里巴巴開發(fā)規(guī)范里頭指出如果給字符串字段添加索引必須要指明索引前綴的長(zhǎng)度,也就是說我們不是給整個(gè)字符串添加上索引給字符串的前多少個(gè)字符加上前綴(至于是多少個(gè)前綴我們判斷規(guī)則如下如果加多了浪費(fèi)空間如果加少了達(dá)不到索引的效果所以我們應(yīng)該再選取前綴盡量少區(qū)分度盡量高的一個(gè)維度上選擇)

唯一索引和普通索引的區(qū)別

①在查找數(shù)據(jù)上的區(qū)別
在查找數(shù)據(jù)上唯一索引和普通索引的區(qū)別就是唯一索引找到一個(gè)數(shù)據(jù)直接返回,普通索引找到一個(gè)數(shù)據(jù)之后還需要進(jìn)行重復(fù)值的判斷,不過這點(diǎn)對(duì)數(shù)據(jù)庫(kù)的性能損耗來說可以忽略不記
②在修改數(shù)據(jù)上的區(qū)別
在數(shù)據(jù)庫(kù)修改上最大的區(qū)別就在于普通索引可以使用change buffer而唯一索引不可以使用change buffer。change buffer是一塊緩存空間如果我們修改的數(shù)據(jù)頁存在數(shù)據(jù)庫(kù)緩存當(dāng)中,直接修改數(shù)據(jù)頁,如果不存在則記錄這個(gè)修改操作當(dāng)修改的頁被加載到緩存當(dāng)中是由一個(gè)merge線程完成修改的操作,在數(shù)據(jù)庫(kù)服務(wù)器關(guān)閉的時(shí)候merge線程也完成未完成的更新操作。
基于以上這個(gè)性能差距我們應(yīng)該在確定了數(shù)據(jù)唯一性的場(chǎng)景中使用普通索引,當(dāng)業(yè)務(wù)需要數(shù)據(jù)庫(kù)來保證數(shù)據(jù)唯一性的情況下使用唯一索引

其他瑣碎的優(yōu)化點(diǎn)
select *

我們應(yīng)該減少select *的使用,理由有如下兩點(diǎn):
①數(shù)據(jù)庫(kù)在執(zhí)行select 語句是需要將“”轉(zhuǎn)化為各個(gè)字段
②使用select * 意味著無論如何操作我們都需要回表除非在數(shù)據(jù)表的所有字段上建立一個(gè)聯(lián)合索引但是這顯然不是很現(xiàn)實(shí)

count(*) count(1) count(字段)

①count(*)和count(1):這兩者的性能基本無差別,但是基于不同的存儲(chǔ)引擎還是存在差別的,比如收使用MYISAM存儲(chǔ)引擎時(shí)底層會(huì)使用一個(gè)字段來記當(dāng)前表中的記錄數(shù),查詢時(shí)只需要查詢這個(gè)字段的值就行其時(shí)間復(fù)雜度時(shí)O(1),但是使用InnoDB的時(shí)候每一次執(zhí)行count
操作都會(huì)真真切切的去數(shù)據(jù)庫(kù)中去找遍歷一遍所以時(shí)間復(fù)雜度時(shí)O(n)
②count(具體字段):在執(zhí)行這個(gè)操作的時(shí)候我們必須要去表中尋找一遍了查找到底有多少個(gè)記錄,查詢優(yōu)化器會(huì)選擇成本最少的索引去查詢

Exist和In

Exist和In適合使用的場(chǎng)景,需要區(qū)分表的大小來定,如果內(nèi)表大于外表應(yīng)該使用Exist,如果內(nèi)表小于小標(biāo)則可以用將內(nèi)表當(dāng)作一個(gè)集合來處理,使用In

多使用Commit

如果沒有開啟數(shù)據(jù)庫(kù)事務(wù)自動(dòng)提交功能,我們?cè)谕瓿梢粋€(gè)事務(wù)操作的時(shí)候應(yīng)該及時(shí)使用commit釋放資源,比如說事務(wù)底層需要使用的鎖,redo,undo,和回滾段

數(shù)據(jù)庫(kù)表結(jié)構(gòu)設(shè)計(jì)和優(yōu)化

數(shù)據(jù)表設(shè)計(jì)原則
范式

####### 鍵和屬性

各種建:
超鍵:可以唯一識(shí)別一個(gè)數(shù)據(jù)行都可以稱之為時(shí)超鍵
候選鍵:候選鍵是烈屬最少地超鍵
主鍵:可以在候選鍵當(dāng)中挑選出一個(gè)字段座位表的主鍵
外鍵:A表中的一個(gè)字段不是A的主鍵但卻是B表的主鍵
屬性:
主屬性:主鍵字段
非主屬性:非主鍵字段

####### 數(shù)據(jù)庫(kù)表設(shè)計(jì)的六大范式

范式是什么:數(shù)據(jù)庫(kù)庫(kù)表涉及的原則,范式向下兼容,并且遵從的范式越高數(shù)據(jù)庫(kù)比表的冗余度越低

######## 第一范式

第一范式規(guī)定數(shù)據(jù)庫(kù)表的所有字段都是原子的不可再分的

######## 第二范式

第二范式在第一范式的基礎(chǔ)上規(guī)定數(shù)據(jù)庫(kù)表必須有一個(gè)主鍵用于唯一標(biāo)識(shí)一個(gè)數(shù)行,并且所有的非主鍵字段都必須完全依賴于主鍵

######## 第三范式

第三范式規(guī)定所有非主屬性字段都必須直接依賴于主鍵字段而不能傳遞依賴于主鍵

######## BC(巴斯歌德范式)

候選鍵只有一個(gè)或者存在多個(gè)候選鍵但是這個(gè)多個(gè)候選鍵都是單屬性的

######## 第四范式

要明白第四范式首先得提出一個(gè)概念叫做多值依賴,多值依賴分為平凡的多值依賴和非平方的多值依賴,平凡的多值依賴指的是一個(gè)字段和另一個(gè)字段有1對(duì)多的關(guān)系,非平凡的多值依賴指的是存在字段A,B,CA和B,C都存在一對(duì)多的關(guān)系。第四范式中不能存在非平凡多值依賴

######## 第五范式(完美范式)

所有的 連接依賴都由候選鍵發(fā)出

####### 反范式化

我們?cè)O(shè)計(jì)數(shù)據(jù)庫(kù)表應(yīng)該以業(yè)務(wù)優(yōu)先的原則設(shè)計(jì),不能夠單單考慮數(shù)據(jù)的冗余度。所以我們?cè)谠O(shè)計(jì)數(shù)據(jù)庫(kù)表的時(shí)候還要反范式化設(shè)計(jì)這樣增加冗余字段可以增加數(shù)據(jù)庫(kù)的性能。
但是冗余字段頁存在一定的問題:
一個(gè)字段更新了它的冗余字段也要更新,這樣難以維護(hù)并且還會(huì)有一定的性能損耗,還會(huì)占用一定的空間。所以設(shè)計(jì)數(shù)據(jù)庫(kù)冗余的時(shí)候我們應(yīng)該遵頊冗余字段對(duì)是我們真實(shí)需要的并且不經(jīng)常更新的。

E-R圖的使用

####### 三要素

當(dāng)數(shù)據(jù)庫(kù)表設(shè)計(jì)比較復(fù)雜的時(shí)候我們可以借助E-R圖作為工具設(shè)計(jì)出表各個(gè)實(shí)體屬性以及關(guān)系,觀察我們?cè)O(shè)計(jì)中存在的邏輯問題,再將它轉(zhuǎn)化為數(shù)據(jù)表。E-R圖的三要素包括實(shí)體,屬性和關(guān)系

######## 實(shí)體

實(shí)體的特點(diǎn)就是可以獨(dú)立存在。尸體可以強(qiáng)實(shí)體和若實(shí)體,強(qiáng)實(shí)體就是不依賴于其他實(shí)體單獨(dú)存在。弱實(shí)體就是需要依賴于存在。用正方形標(biāo)識(shí)

######## 屬性

一個(gè)實(shí)體上不可以再分的特性可以抽象為一個(gè)屬性。用橢圓形標(biāo)識(shí)

######## 關(guān)系

關(guān)系就是各個(gè)實(shí)體之間的關(guān)系,可以分為一對(duì)一的關(guān)系,一對(duì)多的關(guān)系,多對(duì)多的關(guān)系。菱形來標(biāo)識(shí)

####### PowerDesigner

####### E-R圖轉(zhuǎn)化為數(shù)據(jù)表

首先看轉(zhuǎn)換關(guān)系:
一個(gè)實(shí)體或者一個(gè)多對(duì)多的關(guān)系轉(zhuǎn)換為一張表,屬性轉(zhuǎn)化為字段,有一對(duì)一和一對(duì)多的關(guān)系可以轉(zhuǎn)化為i外連接和外鍵

數(shù)據(jù)表主鍵的設(shè)計(jì)

①設(shè)計(jì)的原則
主鍵的式設(shè)計(jì)原則是唯一并且遞增排序
②不推薦使用:
自增主鍵:
自增主鍵存在很多問題,比如說可靠性底(在8.0之前存在主鍵回溯),安全性(可以通過怕從手段輕易的得到判斷數(shù)據(jù)信息),性能差(需要數(shù)據(jù)庫(kù)生成主鍵降低數(shù)據(jù)庫(kù)的性能),交互多(數(shù)據(jù)庫(kù)生成主角按之后要給客戶端客戶端確立之后存入數(shù)據(jù)庫(kù)),局部唯一性(比如說連鎖店各個(gè)店都有自己的自增主鍵但是等到整合所有連鎖店的數(shù)據(jù)時(shí)就會(huì)存在主鍵重復(fù)的問題)

UUID
UUID其實(shí)是一個(gè)時(shí)間+始終序列+MAC地址的一個(gè)組合所以很好的實(shí)現(xiàn)了唯一性但是它并沒有遞增排序這樣插入很容易引起底層頁分裂性能很差

業(yè)務(wù)字段
如果直接使用業(yè)務(wù)字段來構(gòu)建主鍵,我們很難保證業(yè)務(wù)字段是否存在,是否改變后期很難調(diào)整

③推薦使用
例如淘寶使用的主鍵設(shè)計(jì):時(shí)間 + 去重 + 用戶id的一個(gè)片段這樣很好保證唯一性和自增

變化后的UUID,UUID的時(shí)間時(shí)倒著存放的我們可以調(diào)整它變?yōu)闀r(shí)間正序這樣很好保證自增

如果使用的不是MYSQL8.0版本的話我們可以使用時(shí)間 + 用戶ID的形式作為主鍵局部在申請(qǐng)主鍵先到主庫(kù)中查詢當(dāng)前ID分配到哪然后根據(jù)這個(gè)值生成

數(shù)據(jù)庫(kù)參數(shù)配置

硬件優(yōu)化

分庫(kù)分表

當(dāng)數(shù)據(jù)量大的時(shí)候一個(gè)數(shù)據(jù)庫(kù)的性能達(dá)到瓶頸我們就想著對(duì)數(shù)據(jù)庫(kù)分庫(kù)分表。
分庫(kù):
根據(jù)不同的業(yè)務(wù)將不同的數(shù)據(jù)庫(kù)表分到不同的數(shù)據(jù)庫(kù)中,降低單庫(kù)的壓力
分表:
水平分表:
將表中的記錄拆分成不同的范圍放到不同表中,存在的問題就是有的時(shí)候涉及到兩張表的數(shù)據(jù)很難搞定
垂直分表:
將表字段拆分,這樣做的壞處就是查詢的字段過多的時(shí)候會(huì)有很多的表連接所以在拆分時(shí)應(yīng)該講究點(diǎn)

主從復(fù)制,讀寫分離

總結(jié)

以上是生活随笔為你收集整理的MySQL索引重点问题总结(需要完整脑图的联系我)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。