mysql影片教學欄位介紹底層原理。
MYSQL
一條SQL執行過程
先看看一則查詢SQL
- (這裡提供一下官方對各儲存引擎的文件說明Mysql儲存引擎)
#一條update SQL執行
update的執行從客戶端=> ··· => 執行引擎
是一樣的流程,都要先查到這條數據,然後再去更新。要理解 UPDATE
流程我們先來看看,Innodb的架構模型。
Innodb 架構
上一張MYSQL 官方InnoDB架構圖:
內部模組
連接器(JDBC 、ODBC等) =>
[MYSQL 內部
[Connection Pool] (授权、线程复用、连接限制、内存检测等) => [SQL Interface] (DML、DDL、Views等) [Parser] (Query Translation、Object privilege) [Optimizer] (Access Paths、 统计分析) [Caches & Buffers] => [Pluggable Storage Engines]复制代码
]
=> [File]
記憶體結構
#這裡有個關鍵點,當我們去查詢資料時候會先拿著我們目前查詢的page
去buffer pool
中查詢目前page
#是否在緩衝池
中。如果在,則直接獲取。
而如果是update運算
時,則會直接修改 Buffer
中的值。這時候,buffer pool
中的資料就和我們磁碟中實際儲存的資料不一致
了,稱為髒頁
。每隔一段時間,Innodb儲存引擎就會把髒頁資料
刷入磁碟。一般來說當更新一條數據,我們需要將數據給讀取到buffer
中修改,然後寫回磁碟,完成一次 落盤IO
操作。
為了提高update
的操作效能,Mysql在記憶體中做了最佳化,可以看到,在架構圖的緩衝池
中有一塊區域叫做:change buffer
。顧名思義,給change後的數據,做buffer的
,當更新一個沒有unique index
的數據時,直接將修改的數據放到change buffer
#,然後透過merge
操作完成更新,從而減少了那一次落盤的IO
操作。
- 我們上面說的有個條件:
沒有唯一索引的資料更新時
,為什麼必須要沒有唯一索引的資料更新時
才能直接放入change buffer
呢?如果是有唯一約束的欄位
,我們在更新資料後,可能更新的資料和已經存在的資料有重複,所以只能從磁碟中把所有資料讀出來比對
才能確定唯一性。 - 所以當我們的資料是
寫多讀少
的時候,就可以透過增加innodb_change_buffer_max_size
來調整change buffer
在buffer pool
中所佔的比例,預設25(即:25%)
#問題又來了,merge是如何運作的
#有四種情況:
- 有其他訪問,訪問到了當前頁的數據,就會合併到磁碟
- 後台線程定時merge
- 系統正常shut down之前,merge一次
-
redo log
寫滿的時候,merge到磁碟
#一、redo log是什麼
談到redo,就要談到innodb的crash safe
,使用WAL 的方式實作(write Ahead Logging,在寫之前先記錄日誌)
這樣就可以在,當資料庫崩潰的後,直接從redo log
中恢復數據,保證資料的正確性
redo log 預設儲存在兩個檔案中ib_logfile0
ib_logfile1
,這兩個檔案都是固定大小的
。為什麼需要固定大小?
這是因為redo log
的順序讀取
的特性造成的,必須是連續的儲存空間
二、隨機讀寫與順序讀寫
看一張圖
一般我們的資料都是分散在磁碟上的:
機械硬碟的讀寫順序是:
- 定位到磁軌
- 等待旋轉到對應磁區
- 開始讀取寫入
固態讀寫:
- 直接定位到快閃記憶體晶片(這也是為啥固態比機械快)
- 開始讀寫
其實不管機械還是固態,我們去儲存時,都是透過檔案系統
與磁碟打交道的,而他們打交道的方式就有兩個。 隨機讀寫
和順序讀寫
- 隨機讀寫儲存的資料是分佈在不同的
區塊
(預設1block= 8扇區=4K) - 而順序存儲,顧名思義,資料是分佈在
一串連續的區塊
中,這樣讀取速度就大大提升了
三、回到我們架構圖
看到buffer pool
中的Log Buffer
,其就是用來寫redo log 之前存在的緩衝區
在這裡,redo log具體的執行策略有三種:
- ##不用寫
- Log Buffer
,只需要每秒寫redo log 磁碟資料一次,效能高,但會造成資料1s 內的一致性問題。適用於
強實時性,
弱一致性,例如
評論區評論 寫 - Log Buffer
,同時寫入磁碟,效能最差,一致性最高。適用於
弱實時性,
強一致性,例如
支付場景 寫 - Log Buffer
,同時寫到
os buffer(其會每秒呼叫
fsync將資料刷入磁碟),效能好,安全性也高。這是
即時性適中的,例如
訂單類別。
innodb_flush_log_at_trx_commit就可以設定執行策略。預設為
1
- #Buffer Pool 用來加速讀取
- Change Buffer用於沒有非唯一索引的加速寫入
- Log Buffer 用於加速redo log寫
- 自適應Hash索引
主要用於加快查詢
頁。在查詢時,Innodb透過監視索引搜尋的機制來判斷目前查詢是否能走
Hash索引。例如LIKE運算子和% 通配符就不能走。
ibdata1的檔案中,其中包含:
- #InnoDB Data Dictionary,儲存了元數據,例如表結構資訊、索引等
- Doublewrite Buffer 當
- Buffer Pool
寫入資料頁時,不是直接寫入到文件,而是先寫入到這個區域。這樣做的好處的是,一但作業系統,檔案系統或是mysql掛掉,可以直接從這個
Buffer中取得資料。
Change Buffer 當Mysql shut down的時候,修改就會被儲存在磁碟這裡 - Undo Logs 記錄交易修改操作
.ibd 的文件,儲存資料和索引。
- 有了
- 每表檔案表空間
可以使得
ALTER TABLE與
TRUNCATE TABLE效能得到很好的提升。例如
ALTER TABLE,相較於對駐留在共享表空間中的表,在修改表時,會進行
表複製操作,這可能會增加表空間佔用的
磁碟空間量。此類操作可能需要與表中的資料以及索引一樣多的額外空間。該空間不會像
每表檔案表空間那樣釋放回作業系統。
可以在單獨的儲存裝置上建立每個表格文件表空間資料文件,以進行I / O最佳化,空間管理或備份。這就意味著表資料與結構容易在不同資料庫中遷移。 - 當發生資料損壞,備份或二進位日誌不可用或無法重新啟動MySQL伺服器執行個體時,儲存在單一表空間資料檔案中的表可以節省時間並提高成功復原的機會。
- 儲存空間的使用率低,會存在碎片,在
Drop table
的時候會影響效能(除非你自己管理了碎片) - 因為每個表分成各自的表文件,作業系統不能同時進行
fsync
一次刷入資料到文件中 - mysqld會持續保持每個表文件的
文件句柄
, 以提供維持對檔案的持續存取
三、General Tablespaces
- #通用表空間又叫
共享表空間
,他可以儲存多個表
的資料 - 如果儲存相同數量的表,消耗的儲存比
每個表表空間
小
- 在MySQL 5.7.24中棄用了將表分區放置在常規表空間中的支持,並且在將來的MySQL版本中將不再支持。
四、Temporary Tablespaces
儲存在一個叫 ibtmp1
的檔案中。正常情況下Mysql啟動的時候會建立臨時表空間,停止的時候會刪除臨時表空間。並且它能夠自動擴容。
五、Undo Tablespaces
- 提供修改操作的
原子性
,即當修改到一半,出現異常,可以透過Undo 日誌回滾。 - 它儲存了,交易開始前的原始資料與這次的修改操作。
- Undo log 存在於回滾段(rollback segment)中,回滾段又存在
系統表空間``撤銷表空間``臨時表空間
中,如架構圖所示。
Redo Log
前面已經介紹過
總結一下,我們執行一句update SQL 會發生什麼事
- 查詢到我們要修改的那條數據,我們在這裡稱做
origin
,返給執行器 - 在執行器中,修改數據,稱為
modification
- 將
modification
刷入內存,Buffer Pool
的Change Buffer
- 引擎層:記錄undo log (實作交易原子性)
- 引擎層:記錄redo log (崩潰復原使用)
- 服務層:記錄bin log(記錄DDL)
- 傳回更新成功結果
- 資料等待被工作執行緒刷入磁碟
Bin log
#說了Undo
、Redo
也順便說一下Bin log
.
- 這一個log和
innodb
引擎沒有多大關係,我們前面說的兩種日誌,都在是innodb引擎層的。而Bin log
是處於服務層
的。所以他能被各引擎通用 - 他的主要角色是什麼呢?首先,
Bin log
是以事件的形式,記錄了各個DDL DML
語句,它是一種邏輯意義上的日誌。 - 能夠實現
主從複製
,從
伺服器拿到主
伺服器的bin log
日誌,然後執行。 - 做
資料復原
,拿到某個時間段的日誌,重新執行一遍。
跟著一個SQL語句完成全域預覽後,我們來看看回過頭來讓SQL變得更豐富,我們來加入一個索引
試試看
#華麗的分割線
索引篇
要想徹底弄清楚InnoDB中的索引
是個什麼東西,就必須要了解它的在檔案儲存層級
Innodb中將檔案儲存分為了四個層級
Pages, Extents, Segments, and Tablespaces
它們的關係是:
- 預設的
extent
大小為1M
即64
個16KB
的Page
。平常我們檔案系統所說的頁大小是4KB
,包含8
個512Byte
的磁區。
儲存結構B樹變體B 樹
所以有時候,我們被要求主鍵為什麼要有序的原因就是,如果我們在一個有序的欄位上,建立索引,然後插入資料。
在儲存的時候,innodb就會依照順序一個個儲存到 頁
上,存滿一個頁再去申請新的頁,然後接著存。
但如果我們的欄位是無序的,儲存的位置就會在不同的頁面上。當我們的資料儲存到一個已經被 存滿
的頁
上時,就會造成頁分裂
,從而形成碎片
。
幾種不同的索引組織形式
- 叢集索引,如上圖
B 樹
圖所示,子節點上儲存行資料
,而索引的排列的順序
和索引鍵值順序
一致的話就是叢集索引
。主鍵索引就是叢集索引,除了主鍵索引,其他所以都是輔助索引
- 輔助索引,如果我們建立了一個
輔助索引
,它的葉子節點上只儲存自己的值
和主鍵索引的值
。這就意味著,如果我們透過輔助索引查詢所有數據,就會先去尋找輔助索引
中的主鍵鍵值
,然後再去主鍵索引
#裡面,查到相關資料
。這個過程稱為回表
-
rowid
如果沒有主鍵索引
怎麼辦呢?- 沒有主鍵,但有一個 Unique key 而且都不是 null的,則會根據這個 key來建立
叢集索引
。 - 那上面兩種都沒有呢,別擔心,innodb自己維護了一個叫
rowid
的東西,根據這個id來創建聚簇索引
- 沒有主鍵,但有一個 Unique key 而且都不是 null的,則會根據這個 key來建立
索引如何運作
搞清楚什麼是索引,結構是什麼之後。 讓我們來看看,什麼時候我們要用到索引,理解了這些能更好的幫助我們創建正確高效的索引
離散度低不建索引,也就是資料之間相差不大的就沒必要建立索引。 (因為建立索引,在查詢的時候,innodb大多資料都是相同的,我走索引 和全表沒什麼差別就會直接
全表查詢
)。如 性別欄位。這樣反而浪費了大量的儲存空間。-
聯合欄位索引,例如
idx(name, class_name)
- 當執行
select * from stu where class_name = xx and name = lzw
查詢時,也能走idx
這個索引的,因為優化器將SQL最佳化為了name = lzw and class_name = xx
- #當需要有
select ··· where name = lzw
的時候,不需要建立一個單獨的name
#索引,會直接走idx
這個索引 -
覆蓋索引
。如果我們這次查詢的所有資料
全都包含在索引裡面了,就不需要再回表
去查詢了。例如:select class_name from stu where name =lzw
- 當執行
-
索引條件下推(index_condition_pushdown)
- 有這樣一條SQL,
select * from stu where name = lzw and class_name like '%xx'
- 如果沒有
索引條件下推
,因為後面是like ' %xx'
的查詢條件,所以這裡先根據name
走idx聯合索引
查詢到幾個資料後,再回表
查詢到全量row資料
,然後在server層
進行like 過濾找到資料 - 如果有,則直接在
引擎層
對like也進行過濾了,相當於把server層
這個過濾操作下推到引擎層
了。如圖所示:
- 有這樣一條SQL,
建立索引註意事項
- 在where、order、join的on使用次數多的時候,加上索引
- 離散度高的字段才能建立索引
- 聯合索引把離散度高的放前面(因為首先根據第一個字段匹配,能迅速定位資料位置。)
- 頻繁更新的欄位不能建索引(造成
頁分裂
,索引依序存儲,如果儲存頁滿了,再去插入就會造成頁分割) - 使用例如replace、sum、count等
函數
的時候不會使用索引,所以沒必要額外建 - 出現隱含轉換的時候,例如字串轉int ,也用不到索引
- 特別長的字段,可以截取前面幾位創建索引(可以透過
select count(distinct left(name, 10))/count(*)
來看離散度,決定到底提取前幾位)
- tips: 執行一個SQL,不能確切地說他是否能不能用到索引,畢竟這一切都是
優化器決定的
。例如你使用了Cost Base Optimizer
基於開銷的優化器,那種開銷小就用哪種優化。
弄清楚了索引,我們就有能力打開鎖篇的副本了
又一個華麗的分割線
鎖篇
四大特性
先回顧我們熟能詳的幾個基本概念:
- 原子性(透過Undo log實作)
- 一致性
- 隔離性
- 持久性(當機恢復,Redo log double write 實作)
讀取一致性問題應該由資料庫的交易隔離等級來解決(SQL92 標準)
#前提,在一個交易中:
- 髒讀(讀到了別人還沒有commit的數據,然後別人又回滾掉了)
- 不可重複讀(第一次讀取到了數據,然後別人修改commit了,再次去讀取就讀到了別人已經commit的資料)
- 幻讀(在範圍查詢的時候,讀到別人新加入的資料)
SQL92 標準規定: (並發度從左到右,依序降低)
- tips: Innodb中,Repeatable Read的幻讀,也不可能存在,因為它自己解決了
Innodb中如何解決可重複讀(RR) 中產生幻讀的情況
鎖定模型
- ##LBCC (Lock Based Concurrency Control)讀之前加個鎖,但這樣可能會導致效能問題 => 讀的時候加鎖導致其他事務都不能讀寫了,性能低下
- MVCC(Multi Version Concurrency Control) 讀的時候記錄當時快照,別人來讀取快照就行=> 效能消耗,儲存消耗
RR 的MVCC實作,圖中回溯id 初始值不應該是0而是NULL,這裡為了方便寫成0
- ##RC的MVCC實作是對同一個交易的多個讀取建立一個版本
- 而
RR 是同一個交易任何一條都會建立一個版本
透過
與LBCC
的結合,InnoDB能解決對於不加鎖
條件下的幻讀的情況。而不必像 Serializable
一樣,必須讓交易串行
進行,無任何並發
。 下面我們來深入研究一下
是如何實作RR
交易隔離層級的鎖定深入MVCC在Innodb的實作
一、Innodb 的鎖
Shared and Exclusive Locks 共享與排它鎖定=>(S、X)- Intention Locks 意圖鎖定=> 這裡指的是兩把鎖,其實就是 表格層級
- 的共用和排它鎖=> (IS、IX)
##上面這
四把鎖
最基本鎖定的類型Record Locks 記錄鎖定
- #Gap Locks 間隙鎖定
- Next-key Locks 臨片
- #這三把鎖,理解成對於上面 四把鎖
高階鎖定Insert Intention Locks 插入鎖定
- AUTO-INC Locks 自增鍵鎖定
- Predicate Locks for Spatial Indexes 專用於給Spatial Indexes用的
- #上面三把是額外擴充的鎖
要使用共享鎖,在語句後面加上
lock in share mode- 。排它鎖預設
- Insert、Update、Delete
會使用。顯示使用在語句後面加上
for update。
意向鎖都是由資料庫自己維護的。 (主要作用是給表
打一個標記 ,記錄這個表是否被鎖住了) => 如果沒有這個鎖,別的事務想鎖住這張表的時候,就要去全表掃描是否有鎖,效率太低。所以才會有意向鎖的存在。 -
補充:Mysql中鎖,到底鎖的是什麼
你建了一個Primary key, 就是聚集索引(存儲的是
完整的資料- )
-
沒有主鍵,但有一個Unique key 而是都不是null的,則會根據這個key來建立
叢集索引 -
那上面兩種都沒有呢,別擔心,innodb自己維護了一個叫
rowid 的東西,根據這個id來創建 - 聚簇索引
所以一個表裡面,必然會存在一個索引,所以鎖當然總有索引拿來鎖住了。
索引
的表,進行加鎖查詢時,資料庫其實是不知道到底要查哪些資料的,整張表可能都會用到。所以索性就
鎖整張表。
- 如果是給
輔助索引
加寫鎖,例如select * from where name = 'xxx' for update
最後要回表
查主鍵上的信息,所以這個時候除了鎖輔助索引
還要鎖主鍵索引
三、高階鎖定深入解釋
首先上三個概念,有這麼一組資料:主鍵是 1,3,6,9 在儲存時候有如下:x 1 x 3 x x 6 x x x 9 x···
記錄鎖,鎖的是每個記錄,也就是 1,3,6,9
間隙鎖,鎖的是記錄間隙,每個 x
,(-∞,1), (1,3), (3,6), (6,9), (9, ∞)
臨鎖,鎖的是(-∞,1], (1,3], (3,6], (6,9], (9, ∞] 左開右閉的區間
首先這三種鎖都是排它鎖
, 且臨鍵鎖= 記錄鎖間隙鎖
- #當
select * from xxx where id = 3 for update
時,產生記錄鎖定 - 當
select * from xxx where id = 5 for update
時,產生間隙鎖=> 鎖住了(3,6),這裡要格外注意一點:間隙鎖之間是不衝突的。 - 當
select * from xxx where id = 5 for update
時,產生臨鍵鎖=> 鎖住了(3,6] , mysql預設使用臨鍵鎖,如果不滿足1 ,2 情況則他的行鎖的都是臨鍵鎖
- 回到開始的問題,在這裡
Record Lock 行鎖
防止別的交易修改或刪除,Gap Lock 間隙鎖
防止別的交易新增,Gap Lock 和Record Lock
結合形成的Next- Key鎖定
共同解決RR等級
在寫資料時的幻讀問題。
#說到了鎖那麼必然逃不過要說一下死鎖
死鎖後的檢查
-
show status like 'innodb_row_lock_%'
- Innodb_row_lock_current_waits 目前正在有多少等待鎖定
- Innodb_row_lock_time 共等待了多少時間
- Innodb_row_lock_time_avg 平均等多少時間
- Innodb_row_lock_time_max 最大等多久
- Innodb_row_lock_waits 總共出現過多少次等待
-
#select * from information_schema.INNODB_TRX
可以查看到目前正在運作和被鎖定的交易 -
show full processlist
# =select * from information_
=select * from mainformation_listsche#.process#list ## 可以查詢出是
哪個使用者的
狀態與時間
- 保證存取資料的順序
- 避免where的時候不用索引(這樣會鎖定表,不但死鎖更容易產生,而且效能更低)
- 一個非常大的事務,拆成多個小的事務
- 盡量使用等值查詢(就算用範圍查詢也要限定一個區間,而不要只開不閉,例如id > 1 就鎖住後面所有)
要想獲得更好的查詢效能,可以從這張
查詢執行過程
新增連線池,避免每次都
新建、銷毀連線
- 我們並發的執行SQL,並不會因為連線數量增多而變快。為什麼呢?如果我有10000連接同時並發執行,難道不比你10個連接執行快得多嗎? 答案是否定的,不僅不快反而越來越慢。
- 在電腦中,我們都知道只有
CPU
才能真正去執行執行緒
。而作業系統因為用時間分片
的技術,讓我們以為一個CPU核心
執行了多個執行緒
。 - 但其實上一個
CPU
在某個時間段
只能執行一個執行緒
,所以無論我們怎麼增加並發,CPU
還是只能在這個時段處理這麼多資料。 - 那就算
CPU
處理不了這麼多數據,又怎麼會變慢?因為時間分片
,當多個執行緒看起來在"同時執行"
,其實他們之間的上下文切換
十分耗時 - #所以,一旦執行緒的數量超過了CPU核心的數量,再增加執行緒數係統就只會更慢,而不是更快。
- 在電腦中,我們都知道只有
- 當然,這只是其中最核心的原因,磁碟同樣也會對速度有影響,同時也對我們連接數配置有影響。
- 例如我們使用的機械硬碟,我們要透過旋轉,尋址到某個位置,再進行
I/O
操作,這個時候,CPU
就可以把時間,分片給其他線程
,以提升處理效率和速度 - 所以,如果你用的是機械硬碟,我們通常可以多加一些連接數,保持高並發
- 但如果你用的是SSD 呢,因為
I/O
等待時間非常短,所以我們就無法加入太多連線數
- 例如我們使用的機械硬碟,我們要透過旋轉,尋址到某個位置,再進行
- 透過來說你需要遵循這麼一個公式:
執行緒數= ((核心數* 2) 有效磁碟數)
。例如一台i7 4core 1hard disk
的機器,就是4 * 2 1 = 9 - 看到這個公式不知道大家是不是很眼熟,這不僅適用於資料庫連接,也適用於任何
很多CPU運算與I/O的場景
例如:設定最大執行緒數等
#二、資料庫整體設計方案
第三方快取
如果並發非常大,就不能讓他們全打到資料庫上,在客戶端連接資料庫查詢時,加入如Redis
這種三方快取
叢集方式部署資料庫
既然我們一個資料庫承受不了巨大的並發,那為什麼不多再增加幾台機器呢? 主從複製原理圖
從圖中我們不難看出、Mysql主從複製讀寫分離
異步複製
的特性。
- tips: 在把
Binary Log
寫入relay log
之後,slave
都會把最新讀取到的Binary Log Position
記錄到master info
上,下次就直接從這個位置去取。
不同方式的主從複製
上面這種異步
的主從複製,很明顯的一個問題就是,更新不及時的問題。當寫入一個資料後,馬上有使用者讀取,讀取的還是之前的數據,也就是存在著延遲。
要解決延時的問題,就需要引入事務
- 全同步複製,事務方式執行,主節點先寫入,然後讓所有slave寫,必須從節點把資料寫完,才回傳寫成功,這樣的話會大大影響寫入的效能
- 半同步複製,只要有一個salve寫入數據,就算成功。 (如果需要半同步複製,主從節點都需要安裝semisync_mater.so和semisync_slave.so插件)
- GTID(global transaction identities)複製,主庫並行複製的時候,從庫也並行複製,解決主從同步複製延遲,實現自動的
failover
動作,即主節點掛掉,選舉從節點後,能快速自動避免資料遺失。
叢集高可用方案
- 主從HAPrxoy keeplive
- NDB
- Glaera Cluster for MySQL
- #MHA (Master-Mater replication manager for MySQL),MMM(MySQL Master High Available)
- MGR(MySQL Group Replication) => MySQL Cluster
#分錶
將資料分類劃分,分成不同表,減少對單一表造成過多鎖定操作
影響效能
表格結構
- 設計合理欄位類型
- 設計合理欄位長度
三、最佳化器與執行引擎
#慢日誌
開啟show_query_log
,執行時間超過變數long_query_time
的SQL會被記錄下來。
可以使用mysqldumpslow /var/lib/mysql/mysql-slow.log
,還有很多外掛可以提供比這個更優雅的分析,這裡就不詳細講了。
explain分析SQL
任何SQL在寫完之後都應該explain
一下
1. 驅動表 - 例如濫用left/right join
導致效能低
- 使用
left/right join
會直接指定驅動表,在MYSQL中,預設使用Nest loop join
進行表格關聯(即透過驅動表
的結果集作為循環基礎數據,然後透過此集合中的每個數據篩選下一個關聯表的數據,最後合併結果,得出我們常說的臨時表
)。 - 如果
驅動表
的資料是百萬千萬
等級的,可想而知這聯表查詢得有多慢。但反過來,如果以小表
作為驅動表
,借助千萬級表
的索引
查詢就能變得很快。 - 如果你不確定到底該用誰來作為
驅動表
,那麼請交給優化器來決定,例如:select xxx from table1, table2, table3 where ·· ·
,優化器會將查詢記錄行數少的表當作驅動表。 - 如果你就是想自己指定
驅動表
,那麼請拿好Explain
武器,在Explain
的結果中,第一個就是基礎驅動表
- 排序。同樣的,對不同
表
排序也是有很大的效能差異,我們盡量對驅動表
進行排序,而不要對臨時表,也就是合併後的結果集
進行排序。即執行計劃中出現了using temporary
,就需要進行最佳化。
2. 執行計劃各參數意義
- select_type(查詢的類型):
普通查詢
和複雜查詢
(聯合查詢、子查詢等)-
SIMPLE
,查詢不包含子查詢或UNION -
PRIMARY
,如果查詢包含複雜查詢
的子結構,那麼就需要用到主鍵查詢 -
SUBQUERY
,在select
或where
中包含子查詢
-
DERIVED
,在from
中包含子查詢 -
UNION RESULT
,從union
表格查詢子查詢
-
- table 使用到的表格名稱
- type(存取類型),找到所需行的方式,從上往下,查詢速度
越來越快
-
const或system
常數等級的掃描,查詢表最快的一種,system是const的特殊情況(表中只有一條資料) -
eq_ref
唯一性索引掃描 -
ref
非唯一性索引掃描 -
range
索引的範圍掃描,例如between、等範圍查詢 -
#index
(index full)掃描全部索引樹 - ##ALL
掃描全表
- NULL
,不需要存取表或索引
possible_keys,給予使用哪個索引能找到表中的記錄。這裡被列出的索引 -
- 不一定使用
- 哪一個索引被真正使用
到了。如果沒有則為NULL
key_len:使用的索引所佔用的位元組數 - #ref:哪個欄位或常數和
- 索引(key)
一起被使用
rows:一共掃描了多少行 - filtered(百分比):有多少資料在server層還進行了過濾
- Extra:額外資訊
- # #only index
- 資訊只需要從索引中查出,可能用到了覆蓋索引,查詢非常快
- 如果查詢沒有使用索引,這裡會在
server
層過濾再使用where
來過濾結果集 impossible where - 啥也沒查出來
- ,只要沒有透過索引來排序,而是使用了其他排序的方式就是filesort
- (需要透過臨時表來對結果集進行暫時存儲,然後再進行計算。)一般來說這種情況都是進行了
DISTINCT、排序、分組
#using index condition - 索引下推,上文講過,就是把
server層
這個過濾操作下推到引擎層
#四、儲存引擎- 資訊只需要從索引中查出,可能用到了覆蓋索引,查詢非常快
-
-
##當僅僅是
插入與查詢 - 比較多的時候,可以使用
MyISAM
存儲引擎當只是使用臨時數據,可以使用
memory
插入、更新、查詢
等並發數很多時,可以使用- InnoDB
- 總結
- 從五個層次回答MYSQL最佳化,由上至下
- SQL與索引
#相關免費學習推薦:mysql影片教學
以上是一篇文章讓你去懂MYSQL底層原理的詳細內容。更多資訊請關注PHP中文網其他相關文章!

如何有效監控MySQL性能?使用mysqladmin、SHOWGLOBALSTATUS、PerconaMonitoringandManagement(PMM)和MySQLEnterpriseMonitor等工具。 1.使用mysqladmin查看連接數。 2.用SHOWGLOBALSTATUS查看查詢數。 3.PMM提供詳細性能數據和圖形化界面。 4.MySQLEnterpriseMonitor提供豐富的監控功能和報警機制。

MySQL和SQLServer的区别在于:1)MySQL是开源的,适用于Web和嵌入式系统,2)SQLServer是微软的商业产品,适用于企业级应用。两者在存储引擎、性能优化和应用场景上有显著差异,选择时需考虑项目规模和未来扩展性。

在需要高可用性、高級安全性和良好集成性的企業級應用場景下,應選擇SQLServer而不是MySQL。 1)SQLServer提供企業級功能,如高可用性和高級安全性。 2)它與微軟生態系統如VisualStudio和PowerBI緊密集成。 3)SQLServer在性能優化方面表現出色,支持內存優化表和列存儲索引。

mySqlManagesCharacterSetsetSandCollationsyutusututf-8asthEdeFault,允許ConfigurationAtdataBase,table和columnlevels,AndrequiringCarefullageLignmentToavoidMismatches.1)setDefeaultCharactersetTercharactersetEtCollacterSeteTandColletationForAdataBase.2)conformentcollecharactersettersetertersetcollatertersetcollationcollation

MySQL觸發器是與表相關聯的自動執行的存儲過程,用於在特定數據操作時執行一系列操作。 1)觸發器定義與作用:用於數據校驗、日誌記錄等。 2)工作原理:分為BEFORE和AFTER,支持行級觸發。 3)使用示例:可用於記錄薪資變更或更新庫存。 4)調試技巧:使用SHOWTRIGGERS和SHOWCREATETRIGGER命令。 5)性能優化:避免複雜操作,使用索引,管理事務。

在MySQL中創建和管理用戶賬戶的步驟如下:1.創建用戶:使用CREATEUSER'newuser'@'localhost'IDENTIFIEDBY'password';2.分配權限:使用GRANTSELECT,INSERT,UPDATEONmydatabase.TO'newuser'@'localhost';3.修正權限錯誤:使用REVOKEALLPRIVILEGESONmydatabase.FROM'newuser'@'localhost';然後重新分配權限;4.優化權限:使用SHOWGRA

MySQL適合快速開發和中小型應用,Oracle適合大型企業和高可用性需求。 1)MySQL開源、易用,適用於Web應用和中小型企業。 2)Oracle功能強大,適合大型企業和政府機構。 3)MySQL支持多種存儲引擎,Oracle提供豐富的企業級功能。

MySQL相比其他關係型數據庫的劣勢包括:1.性能問題:在處理大規模數據時可能遇到瓶頸,PostgreSQL在復雜查詢和大數據處理上表現更優。 2.擴展性:水平擴展能力不如GoogleSpanner和AmazonAurora。 3.功能限制:在高級功能上不如PostgreSQL和Oracle,某些功能需要更多自定義代碼和維護。


熱AI工具

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

Video Face Swap
使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱門文章

熱工具

PhpStorm Mac 版本
最新(2018.2.1 )專業的PHP整合開發工具

MantisBT
Mantis是一個易於部署的基於Web的缺陷追蹤工具,用於幫助產品缺陷追蹤。它需要PHP、MySQL和一個Web伺服器。請查看我們的演示和託管服務。

SublimeText3 Mac版
神級程式碼編輯軟體(SublimeText3)

MinGW - Minimalist GNU for Windows
這個專案正在遷移到osdn.net/projects/mingw的過程中,你可以繼續在那裡關注我們。 MinGW:GNU編譯器集合(GCC)的本機Windows移植版本,可自由分發的導入函式庫和用於建置本機Windows應用程式的頭檔;包括對MSVC執行時間的擴展,以支援C99功能。 MinGW的所有軟體都可以在64位元Windows平台上運作。

WebStorm Mac版
好用的JavaScript開發工具