查詢關鍵字執行先后順序
-
FROM(及 JOIN
) -
WHERE
-
GROUP BY
-
HAVING
-
SELECT
-
DISTINCT
-
ORDER BY
-
LIMIT / OFFSET
CHAR 和 VARCHAR 的區別?使用場景?
特性 | CHAR | VARCHAR |
---|---|---|
?存儲方式?? | 定長,存儲時填充空格至定義長度 | 變長,存儲實際數據 + 長度前綴 |
?空間占用?? | 固定(可能浪費空間) | 動態(節省空間) |
??讀取性能?? | 高(無需解析長度,直接讀取固定長度) | 較低(需解析長度前綴) |
?適用場景?? | 長度固定的字段(如編碼、枚舉) | 長度不固定的文本(如描述、地址) |
MySQL窗口函數是什么
對數據集劃分窗口(比如按組、按排序范圍),在窗口內計算并返回每行對應的結果,??不聚合數據??,保留所有行
explain語句執行后生成的表重要字段含義
字段 | 含義 | 常見取值 / 說明 |
---|---|---|
type | 訪問類型(效率從好到差) | system > const > eq_ref > ref > range > index > ALL |
key | 實際使用的索引 | 索引名,如 idx_amount ;NULL 表示未命中索引(全表掃描) |
rows | 優化器估算需掃描的行數 | 數值越大,意味著掃描量越大,通常要盡量降低 |
Extra | 額外操作信息 | 如 Using where 、Using index (覆蓋索引)、Using filesort 、Using temporary 等 |
索引是什么?有什么好處?
-
是一種能高效獲取數據的數據結構
-
可以提高數據檢索效率,降低數據庫的
I/O
成本 -
可以對數據進行排序,降低數據排序的成本,減少CPU的消耗
MySQL 索引失效的情況
- 模糊匹配時
%
開頭
SELECT * FROM tbl WHERE name LIKE '%ohn';
- 對列進行函數運算或表達式計算
SELECT * FROM tbl WHERE DATE(created_at) = '2025-06-27';
- 字符串值不加引號,索引失效
-- phone 不加引號,索引失效
explain select * from tb_user where phone = 17799990015;
or
兩邊條件,一邊有索引,一邊無索引,索引失效
-- id 有索引、age 無索引,索引失效
explain select * from tb_user where id = 10 or age = 23;
MySQL索引使用會出現什么問題?該怎么解決?
問題:
-
索引維護成本高,影響寫入性能, 解決: 減少索引數量, 批量提交寫入操作,減少索引更新次數
-
索引未被使用(索引失效), 解決: 優化查詢語句
-
索引占用過多磁盤空間 , 解決: 精簡索引字段,清除無用索引
?
? 事務四大特性(ACID)及實現原理??
?特性?? | ?描述?? | ??實現原理?? |
---|---|---|
??原子性 | 事務要么全部成功,要么全部回滾 | 通過回滾日志(?Undo Log )實現?? |
?一致性 ? | 事務執行前后數據庫的完整性約束不變 | 通過持久性+原子性+隔離性實現 |
??隔離性 ? | 并發事務之間互不干擾 | ??通過鎖機制??和 ?MVCC ?(?多版本并發控制)實現 |
??持久性 ? | 事務提交后數據永久保存 | ?通過重做日志(Redo Log )實現 |
?并發事務問題??
并發事務可能導致臟讀、不可重復讀和幻讀
- 臟讀是指一個事務讀到了另一個事務未提交的“臟數據”
- 不可重復讀是指在一個事務內多次讀取同一數據,由于其他事務的修改導致數據不一致
- 幻讀是指一個事務讀取到了其他事務插入的“幻行”
?事務隔離級別及實現原理??
??隔離級別?? | ??臟讀?? | ?不可重復讀?? | ??幻讀?? | ??實現原理?? |
---|---|---|---|---|
??讀未提交 | ? | ? | ? | 無鎖,直接讀取最新數據(包括未提交的數據) |
?讀已提交 ?? | ? | ? | ? | ??MVCC??:每次查詢生成獨立的ReadView,僅讀取已提交的數據版本 |
??可重復讀 ?? | ? | ? | ? | ??MVCC??:事務首次查詢生成ReadView,后續復用該視圖(MySQL默認隔離級別 ) |
??串行化?? | ? | ? | ? | ??鎖機制??:所有操作加鎖,事務串行執行 |
事務隔離級別,每個級別會引發什么問題,MySQL 默認是哪個級別?
MySQL
默認事務隔離級別是可重復讀
事務隔離級別引發的問題:
隔離級別 | 描述 | 可能出現的問題 |
---|---|---|
READ UNCOMMITTED (讀未提交) | 允許讀取其他事務未提交的數據。 | 臟讀、不可重復讀、幻讀 |
READ COMMITTED (讀已提交) | 只能讀取其他事務已提交的數據。 | 不可重復讀、幻讀 |
REPEATABLE READ (可重復讀) | 同一事務中多次讀取的數據一致。 | 幻讀 |
SERIALIZABLE (串行化) | 強制事務串行執行,完全隔離。 | 無,但性能較低,可能導致并發性差 |
MySQL 常見的三種存儲引擎(InnoDB、MyISAM、MEMORY)的區別?
特性 | InnoDB | MyISAM | MEMORY |
---|---|---|---|
事務 | 支持 | 不支持 | 不支持 |
鎖機制 | 支持行級鎖, 適合高并發讀寫場景 | 支持表級鎖,適合讀多寫少、簡單查詢場景 | 支持表級鎖,適合臨時高速緩存表 |
外鍵與完整性 | 支持外鍵約束 | 不支持外鍵 | 不支持外鍵 |
崩潰恢復 | 支持崩潰恢復 | 無崩潰恢復機制 | 不支持恢復 |
-
InnoDB
從MySQL 5.5
開始為默認存儲引擎,綜合事務處理能力和恢復性能最好。適合高并發讀寫、事務處理要求高的場景 -
MyISAM
適合讀操作多、寫操作較少, 對事務和數據完整性要求不高的場景 -
MEMORY
引擎速度最快,只作為短期緩存或臨時表使用,不用于持久化業務數據
什么是聚簇索引什么是非聚簇索引?
-
聚簇索引是指數據與索引放在一起,
B+
樹的葉子節點保存了整行數據,通常只有一個聚簇索引,一般是由主鍵構成 -
非聚簇索引則是數據與索引分開存儲,B+樹的葉子節點保存的是主鍵值,可以有多個非聚簇索引
回表查詢是什么?
指的是通過二級索引找到對應的主鍵值,然后再通過主鍵值查詢聚簇索引中對應的整行數據的過程
MySQL 中為什么推薦使用連接查詢而不是子查詢?
連接查詢比子查詢更高效、可讀性更好, 因為連接查詢不需要額外的中間臨時表,但是子查詢有中間臨時表
什么叫覆蓋索引?
-
指的是在
SELECT
查詢中,返回的列都能在索引中找到 -
好處: 避免了回表查詢,提高了性能。使用覆蓋索引可以減少對主鍵索引的查詢次數,提高查詢效率
表的查詢速度很慢,怎么解決?
-
使用
explain
分析sql
語句,找出原因 -
創建, 優化索引
-
優化數據庫表,如果表數據量過大,可以拆成多張表
-
使用緩存
索引創建原則?
-
表中的數據量超過
10萬
以上時考慮創建索引 -
選擇查詢頻繁的字段作為索引,如查詢條件、排序字段或分組字段
-
對于內容較長的字段使用前綴索引
-
控制索引數量,雖然索引可以提高查詢速度,但會影響插入、更新的速度
-
盡量使用聯合索引,覆蓋
SQL
的返回值, 比如查詢WHERE user_id=100 AND status=1
,創建(user_id, status)
的聯合索引,比單獨給兩個字段建索引更能精準定位數據, 如果復合索引包含了 SELECT 語句需要返回的所有字段(如SELECT id, name FROM t WHERE user_id=100
,索引設為(user_id, id, name)
),數據庫可以直接從索引中獲取數據,無需再去表中查詢(避免 “回表” 操作),大幅減少 IO 開銷
SQL的優化手段
-
建表時選擇合適的字段類型
-
使用索引,優化索引
-
編寫高效的SQL語句,比如避免使用
SELECT *
,盡量使用UNION ALL
代替UNION
,以及在表關聯時使用INNER JOIN
-
采用主從復制和讀寫分離提高性能
-
在數據量大時考慮分庫分表
MySQL的binlog??
- ?二進制日志,記錄所有數據庫的?寫操作?(
DDL/DML
) - ??作用??:主從復制(數據同步), 數據恢復(通過
mysqlbinlog
工具回放日志)
undo log 和 redo log 的區別是什么?
redo log
記錄的是數據頁的物理變化,用于服務宕機后的恢復,保證事務的持久性undo log
記錄的是邏輯日志,用于事務回滾時恢復原始數據,保證事務的原子性和一致性
?為什么使用B+ 樹作為索引??而不用哈希表或二叉樹?
B+ 樹
優勢?:
-
B + 樹
的高度低, 磁盤IO
次數少 -
??查詢高效??, 葉子節點形成有序鏈表,能夠快速遍歷
-
??查詢效率穩定?, 所有查詢路徑長度相同,時間復雜度穩定為
O(log n)
?對比其他結構?:
-
哈希表?不支持范圍查詢,哈希沖突影響性能
-
二叉樹?:樹高較高,I/O次數多,可能退化為鏈表
??日志與恢復??
??日志?? | ??作用?? | ??應用場景?? |
---|---|---|
??Redo Log ?? | 記錄事務對數據頁的物理修改,保證持久性。 | 崩潰恢復時重放未刷盤的修改。 |
??Undo Log? ? | 記錄事務前的數據邏輯狀態,用于回滾和MVCC。 | 事務回滾、多版本讀。 |
??BinLog? | 記錄所有數據庫寫操作(邏輯日志),用于主從復制和數據恢復。 | 數據同步(如MySQL主從)、數據恢復。 |
事務中的隔離性是如何保證的呢?(解釋下MVCC)
事務的隔離性通過鎖和多版本并發控制(MVCC)來保證。MVCC 通過維護數據的多個版本來避免讀寫沖突。底層實現包括隱藏字段、undo log
和read view
。隱藏字段包括trx_id
和roll_pointer
。undo log
記錄了不同版本的數據,通過roll_pointer
形成版本鏈。read view
定義了不同隔離級別下的快照讀,決定了事務訪問哪個版本的數據。
MySQL主從同步原理是什么?
MySQL主從復制的核心是二進制日志(Binlog)。步驟如下:
-
主庫在事務提交時記錄數據變更到Binlog
-
從庫讀取主庫的Binlog并寫入中繼日志(Relay Log)
-
從庫重做中繼日志中的事件,反映到自己的數據中
?
? 執行一條SQL的流程??
- ??連接器??:驗證用戶權限,建立連接
- ??查詢緩存??:檢查緩存(MySQL 8.0已移除)
- ??解析器??:語法分析,生成抽象語法樹(AST)
- ??優化器??:選擇最優執行計劃(如索引選擇、JOIN順序)
- ??執行器??:調用存儲引擎接口執行計劃
- ??存儲引擎??(如InnoDB):
- 從內存(Buffer Pool)或磁盤讀取數據
- 寫入Redo Log和Undo Log
- ??返回結果??:將結果返回客戶端
如何在MySQL中查看慢查詢?
-
開啟慢查詢日志
-
使用
SHOW PROCESSLIST
實時監控?