TINYINT(1 byte) > SMALLINT(2) > MEDIUMINT(3) > INT(4) > BIGINT(8)。能用 MEDIUMINT 別用 INT。CHAR,可變用 VARCHAR,郵遞區號 CHAR(6) 而非 VARCHAR(255)。NOT NULL,省 1 bit 判斷、索引更緊湊、統計更準。ENUM,內部存整數,比較快、空間小。-- 子查詢(建立臨時表,慢)
SELECT * FROM customer WHERE id NOT IN (SELECT customer_id FROM sales);
-- LEFT JOIN + IS NULL(無臨時表,快)
SELECT c.* FROM customer c
LEFT JOIN sales s ON c.id = s.customer_id
WHERE s.customer_id IS NULL;
原理: MySQL 子查詢常物化成臨時表,JOIN 直接走索引巢狀迴圈。
SELECT name, phone FROM client
UNION
SELECT name, birth FROM author
UNION
SELECT name, supplier FROM product;
UNION ALL 保留重複、更快)。BEGIN;
INSERT INTO sales SET customer_id=14;
UPDATE inventory SET qty=11 WHERE item='book';
COMMIT;
-- 任一失敗 → ROLLBACK 回滾
LOCK TABLE inventory WRITE;
SELECT qty FROM inventory WHERE item='book';
UPDATE inventory SET qty=11 WHERE item='book';
UNLOCK TABLES;
WRITE 鎖:阻擋其他讀寫,獨佔。CREATE TABLE sales (
id INT PRIMARY KEY,
customer_id INT,
FOREIGN KEY (customer_id) REFERENCES customer(id) ON DELETE CASCADE
) ENGINE=InnoDB;
InnoDB。ON DELETE CASCADE 級聯刪除,防孤兒資料。INDEX (a,b,c) 支援 a、a,b、a,b,c。FULLTEXT 僅 MyISAM/InnoDB 5.6+,大量文字搜尋考慮 Elasticsearch。ALTER TABLE ... ADD INDEX),比邊載邊建快數倍。| 反模式 | 優化寫法 | 理由 |
|---|---|---|
WHERE YEAR(dt) = 2023 | WHERE dt >= '2023-01-01' AND dt < '2024-01-01' | 函數破壞索引 |
WHERE amount/7 < 24 | WHERE amount < 24*7 | 運算破壞索引 |
WHERE name LIKE '%abc' | WHERE name >= 'abc' AND name < 'abd'(前綴) | 左邊 % 無法走索引 |
WHERE varchar_col = 123 | WHERE varchar_col = '123' | 隱式轉換失效索引 |
SELECT * | SELECT id, col1(覆蓋索引) | 減少回表 I/O |