兩個看似基礎、實則易誤用的知識點:VARCHAR(N) 中 N 的真實含義隨版本演進;LIMIT offset, rows 深分頁性能崩塌原理與優化方案。本文基於 MySQL 5.6 實測數據,還原真相。
CREATE TABLE `test` (
`name` VARCHAR(5) NOT NULL DEFAULT '',
`info` CHAR(5) NOT NULL DEFAULT '',
PRIMARY KEY (`name`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;

VARCHAR(5) 成功存入 5 個漢字「中文測試a」→ N = 字符數。
MySQL 4.1 前:「length is interpreted as number of bytes」 →
VARCHAR(5)= 5 字節 = 2.5 個漢字(GBK)。MySQL 4.1+:「maximum number of characters you want to store」 →
VARCHAR(5)= 5 字符(字母/數字/漢字等同)。
結論:生產環境均為 5.6+,**直接按字符數設計長度**,無需換算字節。utf8mb4 下 1 字符最多 4 字節,VARCHAR(255) 最大佔 1020 字節 + 2 字節長度前綴,遠小於 65535 行長上限。
LIMIT offset, rows vs LIMIT rowstime 列有索引SET GLOBAL query_cache_size=0; SET @@query_cache_type=OFF;SET profiling=1;-- A: 深分頁 offset=2000
SELECT id, time, title FROM cnblogs WHERE time >= 1315646940 ORDER BY time ASC LIMIT 2000, 10;
-- B: 淺分頁 offset=0
SELECT id, time, title FROM cnblogs WHERE time >= 1315646940 ORDER BY time ASC LIMIT 10;
-- C: 無 WHERE 深分頁
SELECT id, time, title FROM cnblogs ORDER BY time ASC LIMIT 3000, 10;

| 查詢 | 耗時 | 慢倍數 |
|---|---|---|
| A (LIMIT 2000,10) | ~0.015s | 基準 |
| B (LIMIT 10) | ~0.0005s | 30x 快 |
| C (LIMIT 3000,10) | ~0.022s | 更慢 |
LIMIT offset, rows:MySQL 必須掃描並丟棄前 offset 行,再取 rows 行。Offset 越大,掃描/丟棄成本線性增長。LIMIT rows(等價 LIMIT 0, rows):直接取前 N 行,無丟棄開銷。記住上一頁最後一條記錄的排序鍵值,下頁查詢用 WHERE sort_key > last_val ORDER BY sort_key LIMIT page_size。
-- 首頁
SELECT id, time, title FROM cnblogs WHERE time >= 1315646940 ORDER BY time ASC LIMIT 10;
-- 假設最後一條 time = 1315647000
-- 次頁
SELECT id, time, title FROM cnblogs
WHERE time >= 1315646940 AND time > 1315647000
ORDER BY time ASC LIMIT 10;
WHERE (time, id) > (last_time, last_id))。VARCHAR(N) 直接按字符數定義,拒絕手動換算字節。cursor/after_id + page_size。offset 上限(如 < 1000),超限拒絕或異步導出。SELECT id, time, title 全在二級索引 (time, id, title) 中 → 避免回表,極致加速。基礎不等於簡單。搞懂 VARCHAR 語義演進與 LIMIT 執行機制,是寫出高性能 SQL 的必修課。