索引是数据库中特殊的数据结构(如B+树),用于快速定位表中的数据行,类似于书籍的目录。其核心作用是加速查询(如SELECT、WHERE、JOIN操作),但会降低写操作(如INSERT、UPDATE、DELETE)的速度,因为写操作需要同步更新索引。
MariaDB支持多种索引类型,适用于不同场景:
NULL),用于避免重复数据(如用户邮箱)。NULL,用于唯一标识表中的每一行(如用户ID)。(user_id, order_date)索引可用于WHERE user_id=1或WHERE user_id=1 AND order_date='2025-01-01')。MATCH...AGAINST语法。CREATE TABLE语句中定义索引。CREATE TABLE users (
id INT AUTO_INCREMENT PRIMARY KEY,
username VARCHAR(50) NOT NULL,
email VARCHAR(100),
INDEX idx_username (username), -- 普通索引
UNIQUE INDEX idx_email (email), -- 唯一索引
FULLTEXT INDEX idx_content (content) -- 全文索引(仅MyISAM/InnoDB支持)
);
ALTER TABLE或CREATE INDEX语句。ALTER TABLE users ADD INDEX idx_phone (phone); -- 普通索引
CREATE UNIQUE INDEX idx_username_unique ON users (username); -- 唯一索引
CREATE FULLTEXT INDEX idx_description ON articles (description); -- 全文索引
SHOW INDEX命令查看表的索引详情:SHOW INDEX FROM users;
DESCRIBE(或DESC)命令快速查看表的索引信息:DESCRIBE users;
DROP INDEX命令删除指定索引:DROP INDEX idx_username ON users;
WHERE、ORDER BY、GROUP BY、JOIN关联列创建索引(如WHERE status=1中的status列)。user_id比gender更适合建索引,因为user_id的区分度更高)。(a,b,c)只能用于WHERE a=1、WHERE a=1 AND b=2或WHERE a=1 AND b=2 AND c=3,无法用于WHERE b=2(除非a是常数)。(user_id, order_date)比(order_date, user_id)更高效)。覆盖索引是指索引包含查询所需的所有列,无需回表查询(即直接从索引中获取数据,避免访问表数据文件)。例如:
-- 假设有复合索引 (username, email)
SELECT username, email FROM users WHERE username='john_doe';
-- 该查询可使用覆盖索引,无需访问表
WHERE UPPER(username)='JOHN_DOE'会导致索引失效,应改为WHERE username='john_doe'。WHERE id=100(id为INT)比WHERE CAST(id AS CHAR)='100'更高效,后者会导致索引失效。OR条件过多:如WHERE a=1 OR b=2 OR c=3(若a、b、c无联合索引)会导致全表扫描,建议用UNION ALL代替(如SELECT * FROM table WHERE a=1 UNION ALL SELECT * FROM table WHERE b=2 UNION ALL SELECT * FROM table WHERE c=3)。LIKE以%开头:如WHERE content LIKE '%keyword'会导致索引失效,建议用全文索引或LIKE 'keyword%'(后者可使用索引)。使用ANALYZE TABLE命令更新索引的统计信息,帮助优化器选择更优的执行计划:
ANALYZE TABLE users;
使用OPTIMIZE TABLE命令整理表的碎片,提高索引的查询效率(尤其适用于频繁更新的表):
OPTIMIZE TABLE users;
通过SHOW INDEX命令查看索引的Cardinality(基数,即列中不同值的数量),基数越高表示索引的选择性越好(如user_id的基数通常远高于gender)。
utf8mb4,子表也需为utf8mb4),否则会影响索引效率。