組合索引
提到組合索引,大家都知道“最左前綴”原則。例如,創建索引 idx_name_age (name,age) ,通常情況下,where age=50 或者 where age>50 之類的,是不會使用到idx_a_b的。那有沒有特殊情況呢?
假設表是:
CREATE TABLE users
(
id
int(10) unsigned NOT NULL AUTO_INCREMENT,
name
varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
email
varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL,
password
varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL,
remember_token
varchar(100) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
created_at
timestamp NULL DEFAULT NULL,
updated_at
timestamp NULL DEFAULT NULL,
age
int(11) DEFAULT NULL,
PRIMARY KEY (id
),
UNIQUE KEY users_email_unique
(email
),
KEY idx_name_age
(name
,age
)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
覆蓋索引
innodb存儲引擎支持覆蓋索引(covering index),或稱索引覆蓋(index coverage),即從輔助索引中就能查到的記錄,而不需要查詢聚集索引中的記錄。
使用覆蓋索引的好處是輔助索引不包含整行記錄的所有信息,故其大小要遠小於聚集索引,因此可以減少大量的IO操作。
幾個sql語句的explain
- explain SELECT name FROM test.users where age>50
possible_keys是null,表示確實沒啥索引可用。
key卻是idx_name_age,表示優化器出動了,它選擇了idx_name_age這個二級索引。
注意select的字段是name,在idx_name_age這個二級索引中就能完成where的查找以及拿到select 的字段 name
- explain SELECT name,age FROM test.users where age>50
同上
- explain SELECT name,age,id FROM test.users where age>50
同上(注意二級索引都包含了主鍵[ 樣例表主鍵字段是id]以便通過主鍵去聚簇索引查找其他字段。但是顯然上述SQL語句並不需要,因為要select的字段在idx_name_age里都有了。)
- explain SELECT name,age,id,email FROM test.users where age>50
這次沒有使用到idx_name_age,因為要select的字段包含了email,在idx_name_age里面是沒有的
- explain SELECT count(1) FROM test.users where age>50
對於(a,b)這樣的聯合索引,對於b列的查詢條件進行統計,如果是覆蓋索引的,優化器也會選擇該聯合索引。