SQL笔记 -- 索引失效情况

1.联合索引

对于多列索引,过滤条件要使用索引必须按照索引建立时的顺序,依次满足,一旦跳过某个字段,索引后面的字段都无法被使用。
例如以下情况,索引从左到右的顺序为age,classId,name,但是在查询时跳过了age,因此该查询无法使用索引。

CREATE INDEX idx_age_classid_name ON student(age,classId,name);
SELECT SQL_NO_CACHE * FROM student WHERE student.classId=1 AND student.name = 'abcd';

2. 使用函数

查询条件中使用了函数会导致索引失效
例如以下情况,使用了函数导致索引失效

SELECT SQL_NO_CACHE * FROM student WHERE LEFT(student.name,3) = 'abc';

3. 含有计算

查询条件中含有计算会导致索引失效
例如以下情况:

SELECT SQL_NO_CACHE id, stuno, NAME FROM student WHERE stuno+1 = 900001;

4. 类型转换

查询条件两边类型不同,需要自动或主动的进行类型转换,会导致索引失效。例如以下情况,name字段假设为字符串,但查询条件右边为数字123,这时会自动进行类型转换进行比较,因此无法使用索引。

-- 假设name字段有索引且name字段类型为字符串
SELECT SQL_NO_CACHE * FROM student WHERE name=123;

5. 范围条件右边的列索引失效

当有联合索引且查询条件含有范围比较时,比如:(<) (<=) (>) (>=) 和 between 等,索引中被比较范围的列的右边的不能使用。
例如下列情况,索引从左到右包含age,classId,name,但在查询条件中classId为范围比较,因此索引中的name列无法使用,因为在索引中name在列classId的右边。

create index idx_age_name_classId on student(age,classId,name);
SELECT SQL_NO_CACHE * FROM student 
WHERE student.age=30 AND student.classId>20 AND student.name = 'abc' ;

6. 不等于(!= 或者<>)索引失效

查询条件中包含不等于的判断时,索引无法使用。
例如:

CREATE INDEX idx_name ON student(NAME);
SELECT SQL_NO_CACHE * FROM student WHERE student.name != 'abc';

7. is null可以使用索引,is not null无法使用索引

在查询条件中,IS NULL可以使用索引,而IS NOT NULL 无法使用索引。例如:

SELECT SQL_NO_CACHE * FROM student WHERE age IS NOT NULL;

8. like以通配符%开头索引失效

在使用LIKE关键字进行查询的查询语句中,如果匹配字符串的第一个字符为’%‘,索引就不会起作用。只有’%'不在第一个位置,索引才会起作用。例如:

--可以使用索引
SELECT SQL_NO_CACHE * FROM student WHERE name LIKE 'ab%';
--无法使用索引
SELECT SQL_NO_CACHE * FROM student WHERE name LIKE '%ab%';

9. OR 前后存在非索引的列,索引失效

在WHERE子句中,如果在OR前的条件列进行了索引,而在OR后的条件列没有进行索引,那么索引会失效。也就是说,OR前后的两个条件中的列都是索引时,查询中才使用索引。
因为OR的含义就是两个只要满足一个即可,因此只有一个条件列进行了索引是没有意义的,只要有条件列没有进行索引,就会进行全表扫描,因此所以的条件列也会失效。
例如以下情况,如果classId字段上没有索引,那么该查询语句无法使用索引。

SELECT SQL_NO_CACHE * FROM student WHERE age = 10 OR classid = 100;

10. 字符集不同

统一使用utf8mb4( 5.5.3版本以上支持)兼容性更好,统一字符集可以避免由于字符集转换产生的乱码。不同的字符集进行比较前需要进行转换会造成索引失效。

注意:

(1)最好让主键自增 ,让存储引擎自己为表生成主键,而不是我们手动插入 ,这样在插入新的数据时不需要页面分裂,避免性能损耗。

(2)将范围查询条件放置语句最后,这样可以避免上述第五点情况。

(3)最好在设计数据库的时候就将字段设置为 NOT NULL 约束,比如你可以将 INT 类型的字段,默认值设置为0。将字符类型的默认值设置为空字符串(‘’)。

(4)对于单列索引,尽量选择针对当前query过滤性更好的索引。

(5)在选择组合索引的时候,当前query中过滤性最好的字段在索引字段顺序中,位置越靠前越好。

你可能感兴趣的:(SQL,sql,数据库)