很用心的為你寫了 9 道 MySQL 面試題

程式設計師cxuan發表於2020-04-18

MySQL 一直是本人很薄弱的部分,後面會多輸出 MySQL 的文章貢獻給大家,畢竟 MySQL 涉及到資料儲存、鎖、磁碟尋道、分頁等作業系統概念,而且網際網路對 MySQL 的注重程度是不言而喻的,後面要加緊對 MySQL 的研究。寫的如果不好,還請大家見諒。

非關係型資料庫和關係型資料庫區別,優勢比較

非關係型資料庫(感覺翻譯不是很準確)稱為 NoSQL,也就是 Not Only SQL,不僅僅是 SQL。非關係型資料庫不需要寫一些複雜的 SQL 語句,其內部儲存方式是以 key-value 的形式存在可以把它想象成電話本的形式,每個人名(key)對應電話(value)。常見的非關係型資料庫主要有 Hbase、Redis、MongoDB 等。非關係型資料庫不需要經過 SQL 的重重解析,所以效能很高;非關係型資料庫的可擴充套件性比較強,資料之間沒有耦合性,遇見需要新加欄位的需求,就直接增加一個 key-value 鍵值對即可。

關係型資料庫以表格的形式存在,以行和列的形式存取資料,關係型資料庫這一系列的行和列被稱為表,無數張表組成了資料庫,常見的關係型資料庫有 Oracle、DB2、Microsoft SQL Server、MySQL等。關係型資料庫能夠支援複雜的 SQL 查詢,能夠體現出資料之間、表之間的關聯關係;關係型資料庫也支援事務,便於提交或者回滾。

它們之間的劣勢都是基於對方的優勢來滿足的。

MySQL 事務四大特性

一說到 MySQL 事務,你肯定能想起來四大特性:原子性一致性隔離性永續性,下面再對這事務的四大特性做一個描述

  • 原子性(Atomicity): 原子性指的就是 MySQL 中的包含事務的操作要麼全部成功、要麼全部失敗回滾,因此事務的操作如果成功就必須要全部應用到資料庫,如果操作失敗則不能對資料庫有任何影響。

這裡涉及到一個概念,什麼是 MySQL 中的事務?

事務是一組操作,組成這組操作的各個單元,要不全都成功要不全都失敗,這個特性就是事務。

在 MySQL 中,事務是在引擎層實現的,只有使用 innodb 引擎的資料庫或表才支援事務。

  • 一致性(Consistency):一致性指的是一個事務在執行前後其狀態一致。比如 A 和 B 加起來的錢一共是 1000 元,那麼不管 A 和 B 之間如何轉賬,轉多少次,事務結束後兩個使用者的錢加起來還得是 1000,這就是事務的一致性。

  • 永續性(Durability): 永續性指的是一旦事務提交,那麼發生的改變就是永久性的,即使資料庫遇到特殊情況比如故障的時候也不會產生干擾。

  • 隔離性(Isolation):隔離性需要重點說一下,當多個事務同時進行時,就有可能出現髒讀(dirty read)不可重複讀(non-repeatable read)幻讀(phantom read) 的情況,為了解決這些併發問題,提出了隔離性的概念。

髒讀:事務 A 讀取了事務 B 更新後的資料,但是事務 B 沒有提交,然後事務 B 執行回滾操作,那麼事務 A 讀到的資料就是髒資料

不可重複讀:事務 A 進行多次讀取操作,事務 B 在事務 A 多次讀取的過程中執行更新操作並提交,提交後事務 A 讀到的資料不一致。

幻讀:事務 A 將資料庫中所有學生的成績由 A -> B,此時事務 B 手動插入了一條成績為 A 的記錄,在事務 A 更改完畢後,發現還有一條記錄沒有修改,那麼這種情況就叫做出現了幻讀。

SQL的隔離級別有四種,它們分別是讀未提交(read uncommitted)讀已提交(read committed)可重複讀(repetable read)序列化(serializable)。下面分別來解釋一下。

讀未提交:讀未提交指的是一個事務在提交之前,它所做的修改就能夠被其他事務所看到。

讀已提交:讀已提交指的是一個事務在提交之後,它所做的變更才能夠讓其他事務看到。

可重複讀:可重複讀指的是一個事務在執行的過程中,看到的資料是和啟動時看到的資料是一致的。未提交的變更對其他事務不可見。

序列化:顧名思義是對於同一行記錄,會加寫鎖會加讀鎖。當出現讀寫鎖衝突的時候,後訪問的事務必須等前一個事務執行完成,才能繼續執行。

這四個隔離級別可以解決髒讀、不可重複讀、幻象讀這三類問題。總結如下

事務隔離級別 髒讀 不可重複讀 幻讀
讀未提交 允許 允許 允許
讀已提交 不允許 允許 允許
可重複讀 不允許 不允許 允許
序列化 不允許 不允許 不允許

其中隔離級別由低到高是:讀未提交 < 讀已提交 < 可重複讀 < 序列化

隔離級別越高,越能夠保證資料的完整性和一致性,但是對併發的效能影響越大。大多數資料庫的預設級別是讀已提交(Read committed),比如 Sql Server、Oracle ,但是 MySQL 的預設隔離級別是 可重複讀(repeatable-read)

MySQL 常見儲存引擎的區別

MySQL 常見的儲存引擎,可以使用

SHOW ENGINES

命令,來列出所有的儲存引擎

可以看到,InnoDB 是 MySQL 預設支援的儲存引擎,支援事務、行級鎖定和外來鍵

MyISAM 儲存引擎的特點

在 5.1 版本之前,MyISAM 是 MySQL 的預設儲存引擎,MyISAM 併發性比較差,使用的場景比較少,主要特點是

  • 不支援事務操作,ACID 的特性也就不存在了,這一設計是為了效能和效率考慮的。

  • 不支援外來鍵操作,如果強行增加外來鍵,MySQL 不會報錯,只不過外來鍵不起作用。

  • MyISAM 預設的鎖粒度是表級鎖,所以併發效能比較差,加鎖比較快,鎖衝突比較少,不太容易發生死鎖的情況。

  • MyISAM 會在磁碟上儲存三個檔案,檔名和表名相同,副檔名分別是 .frm(儲存表定義).MYD(MYData,儲存資料)MYI(MyIndex,儲存索引)。這裡需要特別注意的是 MyISAM 只快取索引檔案,並不快取資料檔案。

  • MyISAM 支援的索引型別有 全域性索引(Full-Text)B-Tree 索引R-Tree 索引

    Full-Text 索引:它的出現是為了解決針對文字的模糊查詢效率較低的問題。

    B-Tree 索引:所有的索引節點都按照平衡樹的資料結構來儲存,所有的索引資料節點都在葉節點

    R-Tree索引:它的儲存方式和 B-Tree 索引有一些區別,主要設計用於儲存空間和多維資料的欄位做索引,目前的 MySQL 版本僅支援 geometry 型別的欄位作索引,相對於 BTREE,RTREE 的優勢在於範圍查詢。

  • 資料庫所在主機如果當機,MyISAM 的資料檔案容易損壞,而且難以恢復。

  • 增刪改查效能方面:SELECT 效能較高,適用於查詢較多的情況

InnoDB 儲存引擎的特點

自從 MySQL 5.1 之後,預設的儲存引擎變成了 InnoDB 儲存引擎,相對於 MyISAM,InnoDB 儲存引擎有了較大的改變,它的主要特點是

  • 支援事務操作,具有事務 ACID 隔離特性,預設的隔離級別是可重複讀(repetable-read)、通過MVCC(併發版本控制)來實現的。能夠解決髒讀不可重複讀的問題。
  • InnoDB 支援外來鍵操作。
  • InnoDB 預設的鎖粒度行級鎖,併發效能比較好,會發生死鎖的情況。
  • 和 MyISAM 一樣的是,InnoDB 儲存引擎也有 .frm檔案儲存表結構 定義,但是不同的是,InnoDB 的表資料與索引資料是儲存在一起的,都位於 B+ 數的葉子節點上,而 MyISAM 的表資料和索引資料是分開的。
  • InnoDB 有安全的日誌檔案,這個日誌檔案用於恢復因資料庫崩潰或其他情況導致的資料丟失問題,保證資料的一致性。
  • InnoDB 和 MyISAM 支援的索引型別相同,但具體實現因為檔案結構的不同有很大差異。
  • 增刪改查效能方面,果執行大量的增刪改操作,推薦使用 InnoDB 儲存引擎,它在刪除操作時是對行刪除,不會重建表。

MyISAM 和 InnoDB 儲存引擎的對比

  • 鎖粒度方面:由於鎖粒度不同,InnoDB 比 MyISAM 支援更高的併發;InnoDB 的鎖粒度為行鎖、MyISAM 的鎖粒度為表鎖、行鎖需要對每一行進行加鎖,所以鎖的開銷更大,但是能解決髒讀和不可重複讀的問題,相對來說也更容易發生死鎖
  • 可恢復性上:由於 InnoDB 是有事務日誌的,所以在產生由於資料庫崩潰等條件後,可以根據日誌檔案進行恢復。而 MyISAM 則沒有事務日誌。
  • 查詢效能上:MyISAM 要優於 InnoDB,因為 InnoDB 在查詢過程中,是需要維護資料快取,而且查詢過程是先定位到行所在的資料塊,然後在從資料塊中定位到要查詢的行;而 MyISAM 可以直接定位到資料所在的記憶體地址,可以直接找到資料。
  • 表結構檔案上: MyISAM 的表結構檔案包括:.frm(表結構定義),.MYI(索引),.MYD(資料);而 InnoDB 的表資料檔案為:.ibd和.frm(表結構定義);

MySQL 基礎架構

這道題應該從 MySQL 架構來理解,我們可以把 MySQL 拆解成幾個零件,如下圖所示

大致上來說,MySQL 可以分為 Server層和 儲存引擎層。

Server 層包括聯結器、查詢快取、分析器、優化器、執行器,包括大多數 MySQL 中的核心功能,所有跨儲存引擎的功能也在這一層實現,包括 儲存過程、觸發器、檢視等

儲存引擎層包括 MySQL 常見的儲存引擎,包括 MyISAM、InnoDB 和 Memory 等,最常用的是 InnoDB,也是現在 MySQL 的預設儲存引擎。儲存引擎也可以在建立表的時候手動指定,比如下面

CREATE TABLE t (i INT) ENGINE = <Storage Engine>; 

然後我們就可以探討 MySQL 的執行過程了

聯結器

首先需要在 MySQL 客戶端登陸才能使用,所以需要一個聯結器來連線使用者和 MySQL 資料庫,我們一般是使用

mysql -u 使用者名稱 -p 密碼

來進行 MySQL 登陸,和服務端建立連線。在完成 TCP 握手 後,聯結器會根據你輸入的使用者名稱和密碼驗證你的登入身份。如果使用者名稱或者密碼錯誤,MySQL 就會提示 Access denied for user,來結束執行。如果登入成功後,MySQL 會根據許可權表中的記錄來判定你的許可權。

查詢快取

連線完成後,你就可以執行 SQL 語句了,這行邏輯就會來到第二步:查詢快取。

MySQL 在得到一個執行請求後,會首先去 查詢快取 中查詢,是否執行過這條 SQL 語句,之前執行過的語句以及結果會以 key-value 對的形式,被直接放在記憶體中。key 是查詢語句,value 是查詢的結果。如果通過 key 能夠查詢到這條 SQL 語句,就直接返回 SQL 的執行結果。

如果語句不在查詢快取中,就會繼續後面的執行階段。執行完成後,執行結果就會被放入查詢快取中。可以看到,如果查詢命中快取,MySQL 不需要執行後面的複雜操作,就可以直接返回結果,效率會很高。

但是查詢快取不建議使用

為什麼呢?因為只要在 MySQL 中對某一張表執行了更新操作,那麼所有的查詢快取就會失效,對於更新頻繁的資料庫來說,查詢快取的命中率很低。

分析器

如果沒有命中查詢,就開始執行真正的 SQL 語句。

  • 首先,MySQL 會根據你寫的 SQL 語句進行解析,分析器會先做 詞法分析,你寫的 SQL 就是由多個字串和空格組成的一條 SQL 語句,MySQL 需要識別出裡面的字串是什麼,代表什麼。
  • 然後進行 語法分析,根據詞法分析的結果, 語法分析器會根據語法規則,判斷你輸入的這個 SQL 語句是否滿足 MySQL 語法。如果 SQL 語句不正確,就會提示 You have an error in your SQL syntax

優化器

經過分析器的詞法分析和語法分析後,你這條 SQL 就合法了,MySQL 就知道你要做什麼了。但是在執行前,還需要進行優化器的處理,優化器會判斷你使用了哪種索引,使用了何種連線,優化器的作用就是確定效率最高的執行方案。

執行器

MySQL 通過分析器知道了你的 SQL 語句是否合法,你想要做什麼操作,通過優化器知道了該怎麼做效率最高,然後就進入了執行階段,開始執行這條 SQL 語句

在執行階段,MySQL 首先會判斷你有沒有執行這條語句的許可權,沒有許可權的話,就會返回沒有許可權的錯誤。如果有許可權,就開啟表繼續執行。開啟表的時候,執行器就會根據表的引擎定義,去使用這個引擎提供的介面。對於有索引的表,執行的邏輯也差不多。

至此,MySQL 對於一條語句的執行過程也就完成了。

SQL 的執行順序

我們在編寫一個查詢語句的時候

SELECT DISTINCT
    < select_list >
FROM
    < left_table > < join_type >
JOIN < right_table > ON < join_condition >
WHERE
    < where_condition >
GROUP BY
    < group_by_list >
HAVING
    < having_condition >
ORDER BY
    < order_by_condition >
LIMIT < limit_number >

它的執行順序你知道嗎?這道題就給你一個回答。

FROM 連線

首先,對 SELECT 語句執行查詢時,對FROM 關鍵字兩邊的表執行連線,會形成笛卡爾積,這時候會產生一個虛表VT1(virtual table)

首先先來解釋一下什麼是笛卡爾積

現在我們有兩個集合 A = {0,1} , B = {2,3,4}

那麼,集合 A * B 得到的結果就是

A * B = {(0,2)、(1,2)、(0,3)、(1,3)、(0,4)、(1,4)};

B * A = {(2,0)、{2,1}、{3,0}、{3,1}、{4,0}、(4,1)};

上面 A * B 和 B * A 的結果就可以稱為兩個集合相乘的 笛卡爾積

我們可以得出結論,A 集合和 B 集合相乘,包含了集合 A 中的元素和集合 B 中元素之和,也就是 A 元素的個數 * B 元素的個數

再來解釋一下什麼是虛表

在 MySQL 中,有三種型別的表

一種是永久表,永久表就是建立以後用來長期儲存資料的表

一種是臨時表,臨時表也有兩類,一種是和永久表一樣,只儲存臨時資料,但是能夠長久存在的;還有一種是臨時建立的,SQL 語句執行完成就會刪除。

一種是虛表,虛表其實就是檢視,資料可能會來自多張表的執行結果。

ON 過濾

然後對 FROM 連線的結果進行 ON 篩選,建立 VT2,把符合記錄的條件存在 VT2 中。

JOIN 連線

第三步,如果是 OUTER JOIN(left join、right join) ,那麼這一步就將新增外部行,如果是 left join 就把 ON 過濾條件的左表新增進來,如果是 right join ,就把右表新增進來,從而生成新的虛擬表 VT3。

WHERE 過濾

第四步,是執行 WHERE 過濾器,對上一步生產的虛擬表引用 WHERE 篩選,生成虛擬表 VT4。

WHERE 和 ON 的區別

  • 如果有外部列,ON 針對過濾的是關聯表,主表(保留表)會返回所有的列;
  • 如果沒有新增外部列,兩者的效果是一樣的;

應用

  • 對主表的過濾應該使用 WHERE;
  • 對於關聯表,先條件查詢後連線則用 ON,先連線後條件查詢則用 WHERE;

GROUP BY

根據 group by 字句中的列,會對 VT4 中的記錄進行分組操作,產生虛擬機器表 VT5。果應用了group by,那麼後面的所有步驟都只能得到的 VT5 的列或者是聚合函式(count、sum、avg等)。

HAVING

緊跟著 GROUP BY 字句後面的是 HAVING,使用 HAVING 過濾,會把符合條件的放在 VT6

SELECT

第七步才會執行 SELECT 語句,將 VT6 中的結果按照 SELECT 進行刷選,生成 VT7

DISTINCT

在第八步中,會對 TV7 生成的記錄進行去重操作,生成 VT8。事實上如果應用了 group by 子句那麼 distinct 是多餘的,原因同樣在於,分組的時候是將列中唯一的值分成一組,同時只為每一組返回一行記錄,那麼所以的記錄都將是不相同的。

ORDER BY

應用 order by 子句。按照 order_by_condition 排序 VT8,此時返回的一個遊標,而不是虛擬表。sql 是基於集合的理論的,集合不會預先對他的行排序,它只是成員的邏輯集合,成員的順序是無關緊要的。

SQL 語句執行的過程如下

什麼是臨時表,何時刪除臨時表

什麼是臨時表?MySQL 在執行 SQL 語句的過程中,通常會臨時建立一些儲存中間結果集的表,臨時表只對當前連線可見,在連線關閉時,臨時表會被刪除並釋放所有表空間。

臨時表分為兩種:一種是記憶體臨時表,一種是磁碟臨時表,什麼區別呢?記憶體臨時表使用的是 MEMORY 儲存引擎,而臨時表採用的是 MyISAM 儲存引擎。

MEMORY 儲存引擎:memory 是 MySQL 中一類特殊的儲存引擎,它使用儲存在內容中的內容來建立表,而且資料全部放在記憶體中。每個基於 MEMORY 儲存引擎的表實際對應一個磁碟檔案。該檔案的檔名與表名相同,型別為 frm 型別。而其資料檔案,都是儲存在記憶體中,這樣有利於資料的快速處理,提高整個表的效率。MEMORY 用到的很少,因為它是把資料存到記憶體中,如果記憶體出現異常就會影響資料。如果重啟或者關機,所有資料都會消失。因此,基於 MEMORY 的表的生命週期很短,一般是一次性的。

MySQL 會在下面這幾種情況產生臨時表

  • 使用 UNION 查詢:UNION 有兩種,一種是 UNION ,一種是 UNION ALL ,它們都用於聯合查詢;區別是 使用 UNION 會去掉兩個表中的重複資料,相當於對結果集做了一下去重(distinct)。使用 UNION ALL,則不會排重,返回所有的行。使用 UNION 查詢會產生臨時表。

  • 使用 TEMPTABLE 演算法或者是 UNION 查詢中的檢視。TEMPTABLE 演算法是一種建立臨時表的演算法,它是將結果放置到臨時表中,意味這要 MySQL 要先建立好一個臨時表,然後將結果放到臨時表中去,然後再使用這個臨時表進行相應的查詢。

  • ORDER BY 和 GROUP BY 的子句不一樣時也會產生臨時表。

  • DISTINCT 查詢並且加上 ORDER BY 時;

  • SQL中用到 SQL_SMALL_RESULT 選項時;如果查詢結果比較小的時候,可以加上 SQL_SMALL_RESULT 來優化,產生臨時表

  • FROM 中的子查詢;

  • EXPLAIN 檢視執行計劃結果的 Extra 列中,如果使用 Using Temporary 就表示會用到臨時表。

MySQL 常見索引型別

索引是儲存在一張表中特定列上的資料結構,索引是在列上建立的。並且,索引是一種資料結構。

在 MySQL 中,主要有下面這幾種索引

  • 全域性索引(FULLTEXT):全域性索引,目前只有 MyISAM 引擎支援全域性索引,它的出現是為了解決針對文字的模糊查詢效率較低的問題。
  • 雜湊索引(HASH):雜湊索引是 MySQL 中用到的唯一 key-value 鍵值對的資料結構,很適合作為索引。HASH 索引具有一次定位的好處,不需要像樹那樣逐個節點查詢,但是這種查詢適合應用於查詢單個鍵的情況,對於範圍查詢,HASH 索引的效能就會很低。
  • B-Tree 索引:B 就是 Balance 的意思,BTree 是一種平衡樹,它有很多變種,最常見的就是 B+ Tree,它被 MySQL 廣泛使用。
  • R-Tree 索引:R-Tree 在 MySQL 很少使用,僅支援 geometry 資料型別,支援該型別的儲存引擎只有MyISAM、BDb、InnoDb、NDb、Archive幾種,相對於 B-Tree 來說,R-Tree 的優勢在於範圍查詢。

varchar 和 char 的區別和使用場景

MySQL 中沒有 nvarchar 資料型別,所以直接比較的是 varchar 和 char 的區別

char :表示的是定長的字串,當你輸入小於指定的數目,比如你指定的數目是 char(6),當你輸入小於 6 個字元的時候,char 會在你最後一個字元後面補空值。當你輸入超過指定允許最大長度後,MySQL 會報錯

varchar: varchar 指的是長度為 n 個位元組的可變長度,並且是非Unicode的字元資料。n 的值是介於 1 - 8000 之間的數值。儲存大小為實際大小。

Unicode 是一種字元編碼方案,它為每種語言中的每個字元都設定了統一唯一的二進位制編碼,以實現跨語言、跨平臺進行文字轉換、處理的要求

使用 char 儲存定長的資料非常方便、char 檢索效率高,無論你儲存的資料是否到了 10 個位元組,都要去佔用 10 位元組的空間

使用 varchar 可以儲存變長的資料,但儲存效率沒有 char 高。

什麼是 內連線、外連線、交叉連線、笛卡爾積

連線的方式主要有三種:外連線、內連結、交叉連線

  • 外連線(OUTER JOIN):外連線分為三種,分別是左外連線(LEFT OUTER JOIN 或 LEFT JOIN)右外連線(RIGHT OUTER JOIN 或 RIGHT JOIN)全外連線(FULL OUTER JOIN 或 FULL JOIN)

    左外連線:又稱為左連線,這種連線方式會顯示左表不符合條件的資料行,右邊不符合條件的資料行直接顯示 NULL

右外連線:也被稱為右連線,他與左連線相對,這種連線方式會顯示右表不符合條件的資料行,左表不符合條件的資料行直接顯示 NULL

MySQL 暫不支援全外連線

  • 內連線(INNER JOIN):結合兩個表中相同的欄位,返回關聯欄位相符的記錄。

  • 笛卡爾積(Cartesian product): 我在上面提到了笛卡爾積,為了方便,下面再列出來一下。

現在我們有兩個集合 A = {0,1} , B = {2,3,4}

那麼,集合 A * B 得到的結果就是

A * B = {(0,2)、(1,2)、(0,3)、(1,3)、(0,4)、(1,4)};

B * A = {(2,0)、{2,1}、{3,0}、{3,1}、{4,0}、(4,1)};

上面 A * B 和 B * A 的結果就可以稱為兩個集合相乘的 笛卡爾積

我們可以得出結論,A 集合和 B 集合相乘,包含了集合 A 中的元素和集合 B 中元素之和,也就是 A 元素的個數 * B 元素的個數

  • 交叉連線的原文是Cross join ,就是笛卡爾積在 SQL 中的實現,SQL中使用關鍵字CROSS JOIN來表示交叉連線,在交叉連線中,隨便增加一個表的欄位,都會對結果造成很大的影響。

    SELECT * FROM t_Class a CROSS JOIN t_Student b WHERE a.classid=b.classid
    

    或者不用 CROSS JOIN,直接用 FROM 也能表示交叉連線的效果

    SELECT * FROM t_Class a ,t_Student b WHERE a.classid=b.classid
    

    如果表中欄位比較多,不適宜用交叉連線,交叉連線的效率比較差。

  • 全連線:全連線也就是 full join,MySQL 中不支援全連線,但是可以使用其他連線查詢來模擬全連線,可以使用 UNIONUNION ALL 進行模擬。例如

    (select colum1,colum2...columN from tableA ) union (select colum1,colum2...columN from tableB )
    
    
    或 
    (select colum1,colum2...columN from tableA ) union all (select colum1,colum2...columN from tableB );
    

    使用 UNION 和 UNION ALL 的注意事項

    通過 union 連線的 SQL 分別單獨取出的列數必須相同

    使用 union 時,多個相等的行將會被合併,由於合併比較耗時,一般不直接使用 union 進行合併,而是通常採用 union all 進行合併

談談 SQL 優化的經驗

  • 查詢語句無論是使用哪種判斷條件 等於、小於、大於WHERE 左側的條件查詢欄位不要使用函式或者表示式
  • 使用 EXPLAIN 命令優化你的 SELECT 查詢,對於複雜、效率低的 sql 語句,我們通常是使用 explain sql 來分析這條 sql 語句,這樣方便我們分析,進行優化。
  • 當你的 SELECT 查詢語句只需要使用一條記錄時,要使用 LIMIT 1
  • 不要直接使用 SELECT *,而應該使用具體需要查詢的表欄位,因為使用 EXPLAIN 進行分析時,SELECT * 使用的是全表掃描,也就是 type = all
  • 為每一張表設定一個 ID 屬性
  • 避免在 WHERE 字句中對欄位進行 NULL 判斷
  • 避免在 WHERE 中使用 !=<> 操作符
  • 使用 BETWEEN AND 替代 IN
  • 為搜尋欄位建立索引
  • 選擇正確的儲存引擎,InnoDB 、MyISAM 、MEMORY 等
  • 使用 LIKE %abc% 不會走索引,而使用 LIKE abc% 會走索引
  • 對於列舉型別的欄位(即有固定羅列值的欄位),建議使用ENUM而不是VARCHAR,如性別、星期、型別、類別等
  • 拆分大的 DELETE 或 INSERT 語句
  • 選擇合適的欄位型別,選擇標準是 儘可能小、儘可能定長、儘可能使用整數
  • 欄位設計儘可能使用 NOT NULL
  • 進行水平切割或者垂直分割

水平分割:通過建立結構相同的幾張表分別儲存資料

垂直分割:將經常一起使用的欄位放在一個單獨的表中,分割後的表記錄之間是一一對應關係。

文章參考:

https://www.cnblogs.com/sharpest/p/10390035.html

https://blog.csdn.net/yl2isoft/article/details/17205413

https://www.cnblogs.com/jinianjun/archive/2011/11/08/2240525.html

https://www.cnblogs.com/huihuixi/p/12155165.html

https://www.php.cn/faq/418056.html

https://blog.csdn.net/w516162189/article/details/78914035

https://baike.baidu.com/item/聚集索引/11041381?fr=aladdin

https://blog.csdn.net/riemann_/article/details/90324846

https://blog.csdn.net/qq_39101581/article/details/82461076

https://blog.csdn.net/csdn_hklm/article/details/78394412

https://zhidao.baidu.com/question/307471035920165604.html

https://www.zhihu.com/question/24225007

https://baike.baidu.com/item/索引/5716853

https://www.cnblogs.com/ghostwu/p/8544333.html

https://www.cnblogs.com/yuxiuyan/p/6511837.html

https://www.jb51.net/article/147261.htm

https://www.cnblogs.com/zhangchaocoming/p/11380724.html

https://baike.baidu.com/item/myisam/8970102?fr=aladdin

https://segmentfault.com/a/1190000019400925

https://www.csdn.net/gather_2e/MtTaEg4sNDk5MC1ibG9n.html

《極客時間》- MySQL實戰45講

https://www.cnblogs.com/wyaokai/p/10921323.html

https://www.cnblogs.com/hhhhuanzi/p/12296776.html

https://zhidao.baidu.com/question/55127810.html

https://www.cnblogs.com/limuzi1994/p/9684083.html

相關文章