MySQL 優化無銀彈,但有「八大妙招」覆蓋 90% 場景。本文從字段設計、查詢重寫、索引策略、事務控制、分頁優化、配置調優、架構分層、監控閉環八個維度給出可落地的優化清單。
CHAR;變長用 VARCHAR,**長度剛好夠用** (如手機號 VARCHAR(11))。TINYINT + 查找表 或 CHECK 约束 (8.0.16+)。-- 子查詢 (MySQL 5.6+ 優化器可轉換,但不穩定)
SELECT * FROM customer WHERE id NOT IN (SELECT customer_id FROM orders);
-- LEFT JOIN + IS NULL (確定性高、可用索引)
SELECT c.* FROM customer c
LEFT JOIN orders o ON c.id = o.customer_id
WHERE o.customer_id IS NULL;
原理:JOIN 避免臨時表創建,直接利用索引關聯;子查詢在舊版本易產生 DEPENDENT SUBQUERY 全表掃描。
-- 多源彙總:手動建臨時表 INSERT → 查詢 → DROP
-- UNION 一條龍 (4.0+ 支援)
SELECT name, phone FROM client
UNION ALL
SELECT name, birth_date FROM author
UNION ALL
SELECT name, supplier FROM product;
注意:UNION 去重 (排序開銷大);UNION ALL 不去重,**無特殊去重需求必用 UNION ALL**。所有 SELECT 列數、類型須一致。
BEGIN;
INSERT INTO orders (...) VALUES (...);
SET @order_id = LAST_INSERT_ID();
INSERT INTO order_items (order_id, ...) VALUES (@order_id, ...);
UPDATE products SET stock = stock - 1 WHERE id = ...;
DELETE FROM cart WHERE user_id = ...;
COMMIT; -- 或 ROLLBACK
原則:事務要短 (避免長鎖)、要快 (少查詢)、要少 (少表)、死鎖捕獲重試 (應用層或 ProxySQL)。
SELECT a,b FROM t WHERE c=1 → 索引 (c,a,b),Using index 避免回表。(a,b,c) 支援 a / a,b / a,b,c,不支援 b / c / b,c。COUNT(DISTINCT col)/COUNT(*) > 0.1 才值得建索引;性別、狀態、是否刪除區分度極低,**單列索引無效**,需組合索引。-- 深分頁 LIMIT 1000000, 20 掃描 100 萬行再丟棄
-- 延遲關聯 (覆蓋索引定位 ID 再回表)
SELECT t.* FROM `table` t
JOIN (SELECT id FROM `table` WHERE cond ORDER BY id LIMIT 1000000, 20) tmp USING (id);
-- 游標式 / Keyset Pagination (無總頁數、適合無限滾動)
SELECT * FROM `table` WHERE id > 1000000 ORDER BY id LIMIT 20;
innodb_buffer_pool_size = 0.7 * RAM
innodb_log_file_size = 1G
innodb_flush_log_at_trx_commit = 1
innodb_flush_method = O_DIRECT
innodb_io_capacity = 20000 (NVMe)
max_connections = 3000
table_open_cache = 10000
sort_buffer_size = 4M
join_buffer_size = 4M
read_rnd_buffer_size = 8M
long_query_time=0.5, log_queries_not_using_indexes=ON。pt-query-digest 分析 Top 20。八大妙招環環相扣:字段設計是基石,索引是加速器,JOIN/UNION/事務/分頁是查詢層技巧,配置是硬件放大器,監控是持續改進引擎。建議團隊建立「優化清單 + 負責人 + 截止日期 + 效果驗證」機制,將優化從救火變為常態化工程。