索引是資料庫高效查詢的基石。本文詳細對比單列與組合索引,深度解析五大索引類型的建立語法、適用場景與避坑指南,並給出索引建立時機與注意事項的最佳實踐。
單列索引: 一個索引僅包含單一欄位,一張表可建立多個單列索引,但它們獨立運作。
組合索引: 一個索引包含多個欄位,遵循「最左前綴」原則,查詢優化器僅能使用最左側連續欄位。
最基本的索引,無任何限制。
-- 方式一:CREATE INDEX
CREATE INDEX idx_username ON mytable(username(10));
-- 方式二:ALTER TABLE
ALTER TABLE mytable ADD INDEX idx_username (username(10));
-- 方式三:建表時指定
CREATE TABLE mytable (
ID INT NOT NULL,
username VARCHAR(16) NOT NULL,
INDEX idx_username (username(10))
);
-- 刪除
DROP INDEX idx_username ON mytable;
值必須唯一,允許 NULL。組合唯一索引要求欄位組合唯一。
CREATE UNIQUE INDEX idx_unique_user ON mytable(username(10));
ALTER TABLE mytable ADD UNIQUE idx_unique_user (username(10));
CREATE TABLE mytable (
ID INT NOT NULL,
username VARCHAR(16) NOT NULL,
UNIQUE idx_unique_user (username(10))
);
特殊的唯一索引:不允許 NULL,每表僅一個。
CREATE TABLE mytable (
ID INT NOT NULL,
username VARCHAR(16) NOT NULL,
PRIMARY KEY (ID)
);
-- 或
ALTER TABLE mytable ADD PRIMARY KEY (ID);
ALTER TABLE mytable ADD INDEX idx_name_city_age (name(10), city, age);
等價於建立三組索引:(name, city, age)、(name, city)、(name)。
生效查詢:
SELECT * FROM mytable WHERE username='admin' AND city='鄭州';
SELECT * FROM mytable WHERE username='admin';
失效查詢:
SELECT * FROM mytable WHERE age=20 AND city='鄭州'; -- 非最左列
SELECT * FROM mytable WHERE city='鄭州'; -- 非最左列
僅 MyISAM(5.6 前)與 InnoDB(5.6+)支援,針對長文本搜尋。
CREATE FULLTEXT INDEX idx_ft ON mytable(content);
SELECT t.Name FROM mytable t LEFT JOIN mytable m ON t.Name=m.username WHERE m.age=20 AND m.city='鄭州' → 需為 age、city、username 建索引username LIKE 'admin%' 可用索引;LIKE '%admin' 全表掃描YEAR(adddate) < 2007 → 改為 adddate < '2007-01-01'| 缺點 | 影響 | 對策 |
|---|---|---|
| 降低寫入效能 | INSERT/UPDATE/DELETE 需同步維護索引 | 僅為高頻查詢欄位建索引 |
| 佔用磁碟空間 | 大表多組合索引導致索引檔案膨脹 | 使用前綴索引、定期重建 |
| NULL 值不入索引 | 含 NULL 欄位的組合索引部分失效 | 設計時設定 NOT NULL DEFAULT '' |
VARCHAR(255) 僅索引前 10-20 字元WHERE 用到索引時,ORDER BY 不再使用索引;避免多欄排序,改用組合索引ANALYZE TABLE 更新統計資訊,讓優化器做出更好決策