面經梳理-mysql

fattree發表於2024-06-26

題目

資料庫的常用儲存引擎有哪些?能重點介紹innodb和myisam的區別?

innodb

InnoDB儲存引擎支援事務,其設計目標主要面向線上事務處理(OLTP)的應用。其特點是行鎖設計、支援外來鍵,並支援類似於Oracle的非鎖定讀,即預設讀取操作不會產生鎖。從MySQL資料庫5.5.8版本開始,InnoDB儲存引擎是預設的儲存引擎。
InnoDB透過使用多版本併發控制(MVCC)來獲得高併發性,並且實現了SQL標準的4種隔離級別,預設為REPEATABLE級別。同時,使用一種被稱為next-keylocking的策略來避免幻讀(phantom)現象的產生。除此之外,InnoDB儲存引擎還提供了插入緩衝緩衝(insertbuffer)、二次寫(doublewrite)、自適應雜湊索引(adaptivehashindex)、預讀(readahead)等高效能和高可用的功能。對於表中資料的儲存,InnoDB儲存引擎採用了聚集(clustered)的方式,因此每張表的儲存都是按主鍵的順序進行存放。如果沒有顯式地在表定義時指定主鍵,InnoDB儲存引擎會為每一行生成一個6位元組的ROWID,並以此作為主鍵。

MyISAM

MyISAM儲存引擎不支援事務、表鎖設計,支援全文索引,主要面向一些OLAP資料庫應用。
此外,MyISAM儲存引擎的另一個與眾不同的地方是它的緩衝池只快取(cache)索引檔案,而不緩衝資料檔案,這點和大多數的資料庫都非常不同。

NDB

純記憶體儲存引擎

比較

除非有非常特別的原因需要使用其他的儲存引擎,否則應該優先考慮InnoDB引擎。對於只讀的資料,或者表比較小,可以忍受修復操作,則依然可以使用MyISAM(但請不要預設使用MyISAM,而是應該預設使用InnoDB)。

參考:
Mysql 中 MyISAM 和 InnoDB 的區別有哪些?
《MySQL技術內幕:InnoDB儲存引擎(第2版)》 姜承堯 機械工業出版社

B+樹和hash索引的區別是什麼?

B+樹多層,hash索引一層加連結串列

B+樹是樹,hash索引不是

hash索引複雜度O1,B+樹更高

雜湊索引只能用來搜尋等值的查詢,B+樹可以範圍查詢

自適應雜湊索引是由InnoDB儲存引擎自己控制的,DBA本身並不能對其進行干預,B+樹索引可以人為設定。

參考:
《MySQL技術內幕:InnoDB儲存引擎(第2版)》 姜承堯 機械工業出版社

索引在什麼時候會失效?

在某些情況下,當執行EXPLAIN命令進行SQL語句的分析時,會發現最佳化器並沒有選擇索引去查詢資料,而是透過掃描聚集索引,也就是直接進行全表的掃描來得到資料。這種情況多發生於範圍查詢、JOIN連結操作等情況下。

參考:
《MySQL技術內幕:InnoDB儲存引擎(第2版)》 姜承堯 機械工業出版社

瞭解聚集索引和非聚集索引的區別麼?覆蓋索引是什麼?

聚集索引(clustered index)就是按照每張表的主鍵構造一棵B+樹,同時葉子節點中存放的即為整張表的行記錄資料,也將聚集索引的葉子節點稱為資料頁。

輔助索引(Secondary Index,也稱非聚集索引),葉子節點並不包含行記錄的全部資料。葉子節點除了包含鍵值以外,每個葉子節點中的索引行中還包含了一個書籤(bookmark)。該書籤用來告訴InnoDB儲存引擎哪裡可以找到與索引相對應的行資料。由於InnoDB儲存引擎表是索引組織表,因此InnoDB儲存引擎的輔助索引的書籤就是相應行資料的聚集索引鍵。

輔助索引的存在並不影響資料在聚集索引中的組織,因此每張表上可以有多個輔助索引。當透過輔助索引來尋找資料時,InnoDB儲存引擎會遍歷輔助索引並透過葉級別的指標獲得指向主鍵索引的主鍵,然後再透過主鍵索引來找到一個完整的行記錄。舉例來說,如果在一棵高度為3的輔助索引樹中查詢資料,那需要對這棵輔助索引樹遍歷3次找到指定主鍵,如果聚集索引樹的高度同樣為3,那麼還需要對聚集索引樹進行3次查詢,最終找到一個完整的行資料所在的頁,因此一共需要6次邏輯IO訪問以得到最終的一個資料頁。

InnoDB儲存引擎支援覆蓋索引(covering index,或稱索引覆蓋),即從輔助索引中就可以得到查詢的記錄,而不需要查詢聚集索引中的記錄。使用覆蓋索引的一個好處是輔助索引不包含整行記錄的所有資訊,故其大小要遠小於聚集索引,因此可以減少大量的IO操作。覆蓋索引可以理解為輔助索引的特殊的用法。

參考:
《MySQL技術內幕:InnoDB儲存引擎(第2版)》 姜承堯 機械工業出版社

B+樹的優點是什麼?為什麼mysql的索引使用b+樹,為什麼不使用B樹或者紅黑樹呢?

  • B+樹的特徵

有m個子樹的中間節點包含有m個元素(B樹中是k-1個元素),每個元素不儲存資料,只用來索引;
所有的葉子結點中包含了全部關鍵字的資訊,及指向含有這些關鍵字記錄的指標,且葉子結點本身依關鍵字的大小自小而大的順序連結。 (而B 樹的葉子節點並沒有包括全部需要查詢的資訊);
所有的非終端結點可以看成是索引部分,結點中僅含有其子樹根結點中最大(或最小)關鍵字。 (而B 樹的非終節點也包含需要查詢的有效資訊);

  • 為什麼說B+樹比B樹更適合資料庫索引

1)B+樹的磁碟讀寫代價更低

  B+樹的內部結點並沒有指向關鍵字具體資訊的指標。因此其內部結點相對B樹更小。如果把所有同一內部結點的關鍵字存放在同一盤塊中,那麼盤塊所能容納的關鍵字數量也越多。一次性讀入記憶體中的需要查詢的關鍵字也就越多。相對來說IO讀寫次數也就降低了;

2)B+樹查詢效率更加穩定

  由於非終結點並不是最終指向檔案內容的結點,而只是葉子結點中關鍵字的索引。所以任何關鍵字的查詢必須走一條從根結點到葉子結點的路。所有關鍵字查詢的路徑長度相同,導致每一個資料的查詢效率相當;

3)B+樹便於範圍查詢(最重要的原因,範圍查詢是資料庫的常態)

  B樹在提高了IO效能的同時並沒有解決元素遍歷的我效率低下的問題,正是為了解決這個問題,B+樹應用而生。B+樹只需要去遍歷葉子節點就可以實現整棵樹的遍歷。而且在資料庫中基於範圍的查詢是非常頻繁的,而B樹不支援這樣的操作或者說效率太低;

  • 相比紅黑樹的優勢

紅黑樹的出度為2,B+樹的出度一般非常大,B+樹會明顯低很多,有利於減少IO次數。

參考:
B樹、B+樹詳解
MySQL
圖解:什麼是B樹?

索引怎麼建立比較合適

對於什麼時候新增B+樹索引,一般的經驗是,在訪問表中很少一部分時使用B+樹索引才有意義。

如果某個欄位的取值範圍很廣,幾乎沒有重複,即屬於高選擇性,則此時使用B+樹索引是最適合的。

怎樣檢視索引是否是高選擇性的呢?可以透過SHOWINDEX結果中的列Cardinality來觀察。Cardinality值非常關鍵,表示索引中不重複記錄數量的預估值。同時需要注意的是,Cardinality是一個預估值,而不是一個準確值,基本上使用者也不可能得到一個準確的值。在實際應用中,Cardinality/n_rows_in_table應儘可能地接近1。如果非常小,那麼使用者需要考慮是否還有必要建立這個索引。

Cardinality是透過抽樣的方式統計出來的,可以透過show index from tablexxx看到每個索引的Cardinality。

參考:
《MySQL技術內幕:InnoDB儲存引擎(第2版)》 姜承堯 機械工業出版社

Innodb的行鎖有哪幾種?分別是怎麼實現的?

InnoDB儲存引擎實現瞭如下兩種標準的行級鎖:

  • 共享鎖(S Lock),允許事務讀一行資料。
  • 排他鎖(X Lock),允許事務刪除或更新一行資料。
    如果一個事務T1已經獲得了行r的共享鎖,那麼另外的事務T2可以立即獲得行r的共享鎖,因為讀取並沒有改變行r的資料,稱這種情況為鎖相容(Lock Compatible)。但若有其他的事務T3想獲得行r的排他鎖,則其必須等待事務T1、T2釋放行r上的共享鎖——這種情況稱為鎖不相容。

InnoDB儲存引擎不存在鎖升級的問題。因為其不是根據每個記錄來產生行鎖的,相反,其根據每個事務訪問的每個頁對鎖進行管理的,採用的是點陣圖的方式。因此不管一個事務鎖住頁中一個記錄還是多個記錄,其開銷通常都是一致的。

參考:
《MySQL技術內幕:InnoDB儲存引擎(第2版)》 姜承堯 機械工業出版社

一致性非鎖定讀、一致性鎖定讀

一致性非鎖定讀

一致性的非鎖定讀(consistent nonlocking read)是指InnoDB儲存引擎透過行多版本控制(multiversioning)的方式來讀取當前執行時間資料庫中行的資料。如果讀取的行正在執行DELETE或UPDATE操作,這時讀取操作不會因此去等待行上鎖的釋放。相反地,InnoDB儲存引擎會去讀取行的一個快照資料。

快照資料是指該行的之前版本的資料,該實現是透過undo段來完成。而undo用來在事務中回滾資料,因此快照資料本身是沒有額外的開銷。此外,讀取快照資料是不需要上鎖的,因為沒有事務需要對歷史的資料進行修改操作。

非鎖定讀機制極大地提高了資料庫的併發性。在InnoDB儲存引擎的預設設定下,這是預設的讀取方式,即讀取不會佔用和等待表上的鎖。但是在不同事務隔離級別下,讀取的方式不同,並不是在每個事務隔離級別下都是採用非鎖定的一致性讀。此外,即使都是使用非鎖定的一致性讀,但是對於快照資料的定義也各不相同。

在事務隔離級別READ COMMITTED和REPEATABLE READ(InnoDB儲存引擎的預設事務隔離級別)下,InnoDB儲存引擎使用非鎖定的一致性讀。然而,對於快照資料的定義卻不相同。在READ COMMITTED事務隔離級別下,對於快照資料,非一致性讀總是讀取被鎖定行的最新一份快照資料。而在REPEATABLE READ事務隔離級別下,對於快照資料,非一致性讀總是讀取事務開始時的行資料版本。

一致性鎖定讀

在預設配置下,即事務的隔離級別為REPEATABLE READ模式下,InnoDB儲存引擎的SELECT操作使用一致性非鎖定讀。但是在某些情況下,使用者需要顯式地對資料庫讀取操作進行加鎖以保證資料邏輯的一致性。而這要求資料庫支援加鎖語句,即使是對於SELECT的只讀操作。InnoDB儲存引擎對於SELECT語句支援兩種一致性的鎖定讀(lockingread)操作:

  • SELECT…FOR UPDATE
  • SELECT…LOCK IN SHAREMODE
    SELECT…FOR UPDATE對讀取的行記錄加一個X鎖,其他事務不能對已鎖定的行加上任何鎖。SELECT…LOCK IN SHARE MODE對讀取的行記錄加一個S鎖,其他事務可以向被鎖定的行加S鎖,但是如果加X鎖,則會被阻塞。
    對於一致性非鎖定讀,即使讀取的行已被執行了SELECT…FOR UPDATE,也是可以進行讀取的,這和之前討論的情況一樣。此外,SELECT…FORUPDATE,SELECT…LOCK IN SHARE MODE必須在一個事務中,當事務提交了,鎖也就釋放了。因此在使用上述兩句SELECT鎖定語句時,務必加上BEGIN,START TRANSACTION或者 SET AUTOCOMMIT= 0。

參考:
《MySQL技術內幕:InnoDB儲存引擎(第2版)》 姜承堯 機械工業出版社

資料庫的樂觀鎖和悲觀鎖的區別?Select*from table for update,select *from table in share mode分別加的是什麼鎖?

樂觀鎖類似CAS操作,一般會比較和自旋,適用於併發量小的場景;悲觀鎖會直接加鎖,適用於併發量大的場景;

Select*from table for update,select *from table in share mode 都是主動加鎖,應該屬於悲觀鎖。

參考:
mysql 悲觀鎖與樂觀鎖的詳解

資料庫會死鎖麼?Innodb是怎麼解決死鎖的?

解決死鎖問題最簡單的一種方法是超時,即當兩個事務互相等待時,當一個等待時間超過設定的某一閾值時,其中一個事務進行回滾,另一個等待的事務就能繼續進行。在InnoDB儲存引擎中,引數innodb_lock_wait_timeout用來設定超時的時間。

超時機制雖然簡單,但是其僅透過超時後對事務進行回滾的方式來處理,或者說其是根據FIFO的順序選擇回滾物件。但若超時的事務所佔權重比較大,如事務操作更新了很多行,佔用了較多的undolog,這時採用FIFO的方式,就顯得不合適了,因為回滾這個事務的時間相對另一個事務所佔用的時間可能會很多。因此,除了超時機制,當前資料庫還都普遍採用wait-forgraph(等待圖)的方式來進行死鎖檢測。較之超時的解決方案,這是一種更為主動的死鎖檢測方式。InnoDB儲存引擎也採用的這種方式。

wait-forgraph要求資料庫儲存以下兩種資訊:

-鎖的資訊連結串列
-事務等待連結串列

透過上述連結串列可以構造出一張圖,而在這個圖中若存在迴路,就代表存在死鎖,因此資源間相互發生等待。

wait-forgraph是一種較為主動的死鎖檢測機制,在每個事務請求鎖併發生等待時都會判斷是否存在迴路,若存在則有死鎖,通常來說InnoDB儲存引擎選擇回滾undo量最小的事務。

參考:
《MySQL技術內幕:InnoDB儲存引擎(第2版)》 姜承堯 機械工業出版社

如何安全的更改一行資料?

加鎖,一致性鎖定讀;增加隔離級別,SERIALIZABLE

參考:
《MySQL技術內幕:InnoDB儲存引擎(第2版)》 姜承堯 機械工業出版社

什麼是幻讀?Mysql的innodb儲存引擎是怎麼解決幻讀的?

Phantom Problem是指在同一事務下,連續執行兩次同樣的SQL語句可能導致不同的結果,第二次的SQL語句可能會返回之前不存在的行。

InnoDB儲存引擎採用Next-Key Locking的演算法避免Phantom Problem。對於上述的SQL語句SELECT * FROM t WHERE a > 2 FOR UPDATE,其鎖住的不是5這單個值,而是對(2,+∞)這個範圍加了X鎖。因此任何對於這個範圍的插入都是不被允許的,從而避免Phantom Problem。

InnoDB儲存引擎預設的事務隔離級別是REPEATABLE READ,在該隔離級別下,其採用Next-Key Locking的方式來加鎖。而在事務隔離級別READ COMMITTED下,其僅採用Record Lock。

參考:
《MySQL技術內幕:InnoDB儲存引擎(第2版)》 姜承堯 機械工業出版社

Mysql的事務有那幾個特性?ACID分別是怎麼實現的?

A(Atomicity),原子性。原子性指整個資料庫事務是不可分割的工作單位。只有使事務中所有的資料庫操作都執行成功,才算整個事務成功。事務中任何一個SQL語句執行失敗,已經執行成功的SQL語句也必須撤銷,資料庫狀態應該退回到執行事務前的狀態。

C(consistency),一致性。一致性指事務將資料庫從一種狀態轉變為下一種一致的狀態。在事務開始之前和事務結束以後,資料庫的完整性約束沒有被破壞。

I(isolation),隔離性。隔離性還有其他的稱呼,如併發控制(concurrency control)、可序列化(serializability)、鎖(locking)等。事務的隔離性要求每個讀寫事務的物件對其他事務的操作物件能相互分離,即該事務提交前對其他事務都不可見,通常這使用鎖來實現。

D(durability),永續性。事務一旦提交,其結果就是永久性的。即使發生當機等故障,資料庫也能將資料恢復。

事務隔離性由鎖來實現。原子性、一致性、永續性透過資料庫的redo log和undo log來完成。redo log稱為重做日誌,用來保證事務的原子性和永續性,適用於資料落盤過程,先寫日誌後落盤。undo log用來保證事務的一致性,適用於操作回滾過程。

參考:
《MySQL技術內幕:InnoDB儲存引擎(第2版)》 姜承堯 機械工業出版社

SQL有幾種隔離級別?InnoDB預設的隔離級別是?分別是怎麼實現的?

SQL有幾種隔離級別

SQL 標準 定義 的 四個 隔離 級別 為:

  • READ UNCOMMITTED
  • READ COMMITTED
  • REPEATABLE READ
  • SERIALIZABLE。

READ UNCOMMITTED稱為瀏覽訪問(browse access),僅僅針對事務而言的。READ COMMITTED稱為遊標穩定(cursor stability)。REPEATABLE READ是2.9999°的隔離,沒有幻讀的保護。SERIALIZABLE稱為隔離,或3°的隔離。SQL和SQL2標準的預設事務隔離級別是SERIALIZABLE。

InnoDB預設的隔離級別

InnoDB儲存引擎預設支援的隔離級別是REPEATABLE READ,但是與標準SQL不同的是,InnoDB儲存引擎在REPEATABLE READ事務隔離級別下,使用Next-Key Lock鎖的演算法,因此避免幻讀的產生。這與其他資料庫系統(如Microsoft SQL Server資料庫)是不同的。所以說,InnoDB儲存引擎在預設的REPEATABLE READ的事務隔離級別下已經能完全保證事務的隔離性要求,即達到SQL標準的SERIALIZABLE隔離級別。
隔離級別越低,事務請求的鎖越少或保持鎖的時間就越短。這也是為什麼大多數資料庫系統預設的事務隔離級別是READ COMMITTED。
據瞭解,大部分的使用者質疑SERIALIZABLE隔離級別帶來的效能問題,但是根據Jim Gray在《Transaction Processing》一書中指出,兩者的開銷幾乎是一樣的,甚至SERIALIZABLE可能更優!!!因此在InnoDB儲存引擎中選擇REPEATABLE READ的事務隔離級別並不會有任何效能的損失。同樣地,即使使用READ COMMITTED的隔離級別,使用者也不會得到效能的大幅度提升。

分別是怎麼實現的

READ UNCOMMITTED ,事務中的修改,即使沒有提交,對其它事務也是可見的。
READ COMMITTED ,一個事務只能讀取已經提交的事務所做的修改。換句話說,一個事務所做的修改在提交之前對其它事務是不可見的。在 READ COMMITTED 的 事務 隔離級別下,除了唯一性的約束檢查及外來鍵約束的檢查需要gap lock,InnoDB儲存引擎不會使用gap lock的鎖演算法,事務提交後才可讀到最新的資料(mvcc);
REPEATABLE READ,使用Next-KeyLock鎖的演算法,因此避免幻讀的產生,事務提交後才可讀到提交的資料,但是每次讀取的都是事務開始的快照(mvcc)。
SERIALIZABLE,在SERIALIABLE的事務隔離級別,InnoDB儲存引擎會對每個SELECT語句後自動加上LOCK IN SHARE MODE,即為每個讀取操作加一個共享鎖。因為InnoDB儲存引擎在REPEATABLE READ隔離級別下就可以達到3°的隔離,因此一般不在本地事務中使用SERIALIABLE的隔離級別。SERIALIABLE的事務隔離級別主要用於InnoDB儲存引擎的分散式事務。

如果不同事務採取不同隔離級別,各自遵從各自的協議即可

參考:
《MySQL技術內幕:InnoDB儲存引擎(第2版)》 姜承堯 機械工業出版社
資料庫系統原理

Mysql怎麼最佳化,explain指令有了解過??

Mysql怎麼最佳化

使用EXPLAIN語句讓MySQL解釋它將如何執行一條SELECT語句。
應該總是使用正確的資料型別。
決不要檢索比需求還要多的資料。換言之,不要用SELECT*(除非你真正需要每個列)。
只返回必要的行:使用LIMIT語句來限制返回的資料。
必須索引資料庫表以改善資料檢索的效能。確定索引什麼不是一件微不足道的任務,需要分析使用的SELECT語句以找出重複的WHERE和ORDERBY子句。如果一個簡單的WHERE子句返回結果所花的時間太長,則可以斷定其中使用的列(或幾個列)就是需要索引的物件。
你的SELECT語句中有一系列複雜的OR條件嗎?透過使用多條SELECT語句和連線它們的UNION語句,你能看到極大的效能改進。
LIKE很慢。一般來說,最好是使用FULLTEXT而不是LIKE。

explain指令

Explain用來分析SELECT查詢語句,開發人員可以透過分析Explain結果來最佳化查詢語句。

接下來我們將展示explain中每個列的資訊。

  1. id列

id列的編號是 select 的序列號,有幾個 select 就有幾個id。

  1. select_type列

select_type 表示對應行是是簡單還是複雜的查詢,如果是複雜的查詢,又是上述三種複雜查詢中的哪一種。

1)simple:簡單查詢。查詢不包含子查詢和union

2)primary:複雜查詢中最外層的 select

3)subquery:包含在 select 中的子查詢(不在 from 子句中)

4)derived:包含在 from 子句中的子查詢。MySQL會將結果存放在一個臨時表中,也稱為派生表(derived的英文含義)

5)union:在 union 中的第二個和隨後的 select

6)union result:從 union 臨時表檢索結果的 select

  1. table列

這一列表示 explain 的一行正在訪問哪個表。

  1. type列

這一列表示關聯型別或訪問型別,即MySQL決定如何查詢表中的行。

依次從最優到最差分別為:system > const > eq_ref > ref > fulltext > ref_or_null > index_merge > unique_subquery > index_subquery > range > index > ALL

NULL:mysql能夠在最佳化階段分解查詢語句,在執行階段用不著再訪問表或索引。例如:在索引列中選取最小值,可以單獨查詢索引來完成,不需要在執行時訪問表

const, system:mysql能對查詢的某部分進行最佳化並將其轉化成一個常量(可以看show warnings 的結果)。用於 primary key 或 unique key 的所有列與常數比較時,所以表最多有一個匹配行,讀取1次,速度比較快。

eq_ref:primary key 或 unique key 索引的所有部分被連線使用 ,最多隻會返回一條符合條件的記錄。這可能是在 const 之外最好的聯接型別了,簡單的 select 查詢不會出現這種 type。

ref:相比 eq_ref,不使用唯一索引,而是使用普通索引或者唯一性索引的部分字首,索引要和某個值相比較,可能會找到多個符合條件的行。

ref_or_null:類似ref,但是可以搜尋值為NULL的行。

index_merge:表示使用了索引合併的最佳化方法。 例如下表:id是主鍵,tenant_id是普通索引。or 的時候沒有用 primary key,而是使用了 primary key(id) 和 tenant_id 索引

range:範圍掃描通常出現在 in(), between ,> ,<, >= 等操作中。使用一個索引來檢索給定範圍的行。

index:和ALL一樣,不同就是mysql只需掃描索引樹,這通常比ALL快一些。

ALL:即全表掃描,意味著mysql需要從頭到尾去查詢所需要的行。通常情況下這需要增加索引來進行最佳化了

  1. possible_keys列

這一列顯示查詢可能使用哪些索引來查詢。

  1. key列

這一列顯示mysql實際採用哪個索引來最佳化對該表的訪問。如果沒有使用索引,則該列是 NULL。如果想強制mysql使用或忽視possible_keys列中的索引,在查詢中使用 force index、ignore index。

  1. key_len列

這一列顯示了mysql在索引裡使用的位元組數,透過這個值可以算出具體使用了索引中的哪些列。

  1. ref列

這一列顯示了在key列記錄的索引中,表查詢值所用到的列或常量,常見的有:const(常量),func,NULL,欄位名(例:film.id)

  1. rows列

這一列是mysql估計要讀取並檢測的行數,注意這個不是結果集裡的行數。

  1. Extra列

這一列展示的是額外資訊。常見的重要值如下:

distinct: 一旦mysql找到了與行相聯合匹配的行,就不再搜尋了

Using index:這發生在對錶的請求列都是同一索引的部分的時候,返回的列資料只使用了索引中的資訊,而沒有再去訪問表中的行記錄。是效能高的表現。

Using where:mysql伺服器將在儲存引擎檢索行後再進行過濾。就是先讀取整行資料,再按 where 條件進行檢查,符合就留下,不符合就丟棄。

Using temporary:mysql需要建立一張臨時表來處理查詢。出現這種情況一般是要進行最佳化的,首先是想到用索引來最佳化。

Using filesort:mysql 會對結果使用一個外部索引排序,而不是按索引次序從表裡讀取行。此時mysql會根據聯接型別瀏覽所有符合條件的記錄,並儲存排序關鍵字和行指標,然後排序關鍵字並按順序檢索行資訊。這種情況下一般也是要考慮使用索引來最佳化的。

參考:
《MySQL技術內幕:InnoDB儲存引擎(第2版)》 姜承堯 機械工業出版社
資料庫系統原理
MySQL explain詳解

pg和mysql的差別

pg和mysql對比

MySQL與PostgreSQL的區別:
MySQL是應用開發者建立出來的DBMS;MySQL傾向於使用者的角度,回答的問題是“你想解決的是什麼問題”。
PostgreSQL是由資料庫開發者建立出來的DBMS;傾向於理論角度,回答的問題是“資料庫應該如何來解決問題”。
MySQL一般會將資料合法性驗證交給客戶;PostgreSQL在合法性方面做得比較嚴格。
在架構上,MySQL分為兩層:上層的SQL層和幾個儲存引擎(比如InnoDB,MyISAM)。PostgreSQL只有一個儲存引擎提供這兩個功能。
這兩個資料庫系統都可以針對應用的情境被最佳化、定製。MySQL專案一開始焦點在速度上,而PostgreSQL一開始焦點在特性和規範標準上。

PG相對於MySQL的優勢:
1、在SQL的標準實現上要比MySQL完善,而且功能實現比較嚴謹;
2、儲存過程的功能支援要比MySQL好,具備本地快取執行計劃的能力;
3、對錶連線支援較完整,最佳化器的功能較完整,支援的索引型別很多,複雜查詢能力較強;
4、PG主表採用堆表存放,MySQL採用索引組織表,能夠支援比MySQL更大的資料量;
5、PG的主備複製屬於物理複製,相對於MySQL基於binlog的邏輯複製,資料的一致性更加可靠,複製效能更高,對主機效能的影響也更小;
6、MySQL的儲存引擎外掛化機制,存在鎖機制複雜影響併發的問題,而PG不存在。

MySQL相對於PG的優勢:
1、innodb的基於回滾段實現的MVCC機制,相對PG新老資料一起存放的基於XID的MVCC機制是佔優的;
2、MySQL採用索引組織表,這種儲存方式非常適合基於主鍵匹配的查詢、刪改操作,但是對錶結構設計存在約束;
3、MySQL的最佳化器較簡單,系統表、運算子、資料型別的實現都很精簡,非常適合簡單的查詢操作;
4、MySQL分割槽表的實現要優於PG的基於繼承表的分割槽實現,主要體現在分割槽個數達到上千上萬後的處理效能差異較大;
5、MySQL的儲存引擎外掛化機制,使得它的應用場景更加廣泛,比如除了innodb適合事務處理場景外,myisam適合靜態資料的查詢場景。

重點差別:
PG在SQL的標準實現上要比MySQL完善,而且功能實現比較嚴謹。
PG儲存過程的功能支援要比MySQL好,具備本地快取執行計劃的能力;
PG的主備複製屬於物理複製,相對於MySQL基於binlog的邏輯複製,資料的一致性更加可靠,複製效能更高,對主機效能的影響也更小;
innodb的基於回滾段實現的MVCC機制,相對PG新老資料一起存放的基於XID的MVCC機制是佔優的;
MySQL的儲存引擎外掛化機制,使得它的應用場景更加廣泛;PostgreSQL只有一個儲存引擎提供功能。
MySQL採用索引組織表,這種儲存方式非常適合基於主鍵匹配的查詢、刪改操作,但是對錶結構設計存在約束;

直觀差別:
簡單易用速度快用mysql;複雜嚴謹效率查詢效率略低用pg

堆表和索引表對比

堆表(heap table)資料插入時時儲存位置是隨機的,主要是資料庫內部塊的空閒情況決定,獲取資料是按照命中率計算,全表掃表時不見得先插入的資料先查到。

索引表(iot)資料儲存是把表按照索引的方式儲存的,資料是有序的,資料的位置是預先定好的,與插入的順序沒有關係。

索引表的查詢效率逼堆表高(相當於查詢索引的效率),插入資料的速度比堆錶慢。

索引表適用場景:

適用於資訊檢索、空間和OLAP程式。
1、 程式碼查詢表。
2、 經常透過主碼訪問的表。
3、 構建自己的索引結構。
4、 加強資料的共同定位,要資料按特定順序物理儲存。
5、 經常用between…and…對主碼或唯一碼進行查詢。資料物理上分類查詢。如一張訂單表,按日期裝載資料,想查單個客戶不同時期的訂貨和統計情況。

常用資料庫支援情況:

Oracle支援堆表,也支援索引組織表

PostgreSQL只支援堆表,不支援索引組織表

Innodb只支援索引組織表

參考:
PostgreSQL與MySQL之間的區別
堆表和索引組織表區別

你們專案有使用分庫分表?如何實現?如果要擴資料庫節點的話,怎麼實現?

專案沒有分庫分表

相關學習資料參考https://blog.csdn.net/weixin_42208959/article/details/115289497、https://www.cyc2018.xyz/資料庫/MySQL.html#三、儲存引擎

參考:
PostgreSQL與MySQL之間的區別
分庫分表面試題及答案

相關文章