MySQL索引失效场景,索引优化,索引原理

矫情吗;* 2024-03-01 03:15 172阅读 0赞

文章主要有以下内容:MySQL性能优化、索引优化、索引失效,索引原理、索引分类。

索引是一个用于提高数据库查询速度的数据结构。不必搜索整个数据库,通过使用索引,数据库系统可以直接找到存储在磁盘上的特定行的地址。没有索引,查询大型数据库可能非常缓慢。

一 索引分类

按照字段类型分类,MySQL索引可以分为以下几种:

1. 普通索引:

这是最基本的索引,没有任何特殊的限制。

  1. CREATE INDEX idx_name ON table_name(column_name);

2. 唯一索引:

与普通索引类似,但要求索引列的所有值都是唯一的(不包括NULL值,因为在MySQL中,多个NULL值是被视为相互不同的)。

  1. CREATE UNIQUE INDEX idx_unique_name ON table_name(column_name);

3. 主键索引:

每个表只能有一个主键索引。

它要求所有的主键列的值都是唯一的。

InnoDB存储引擎的表中,数据的物理存储顺序与主键的顺序相同,也即主键索引是聚簇索引。

  1. ALTER TABLE table_name ADD PRIMARY KEY (column_name);

4. 全文索引:

专门用于全文搜索。

仅在MyISAM和InnoDB(从MySQL 5.6版本开始)存储引擎的CHAR、VARCHAR和TEXT列上支持。

允许使用`MATCH AGAINST`语法来执行全文搜索。

  1. CREATE FULLTEXT INDEX idx_fulltext_name ON table_name(column_name);
  2. SELECT * FROM table_name WHERE MATCH(column_name) AGAINST('keyword');

5. 空间索引:

专门为地理空间数据类型设计,如`GEOMETRY`、`POINT`、`LINESTRING`、`POLYGON`等。

使用R-Tree算法。

允许进行空间位置的查询。

  1. CREATE SPATIAL INDEX idx_spatial_name ON table_name(column_name);SELECT * FROM table_name WHERE MBRContains(column_name, GeomFromText('Polygon(...)'));

6. 前缀索引:

不是整列作为索引,而是使用列值的前缀部分。

适用于字符串类型的列,尤其是当文本内容很长时。

  1. CREATE INDEX idx_prefix_name ON table_name(column_name(10)); -- 只使用column_name的前10个字符作为索引

二 索引失效场景

索引失效指的是在进行数据库查询时,虽然存在合适的索引,但由于某种原因,查询并没有使用该索引,从而可能导致性能下降。以下是常见的索引失效的例子及代码示例:

  1. 使用LIKE操作符并以通配符开头:

    SELECT * FROM users WHERE name LIKE ‘%John’;

  2. 使用NOT操作符:

    SELECT * FROM users WHERE NOT age = 25;

3. 列与列的计算:

  1. SELECT * FROM users WHERE salary - tax > 5000;

4. 使用函数处理列:

  1. SELECT * FROM users WHERE MONTH(birthdate) = 5;

5. 隐式类型转换:

  1. SELECT * FROM users WHERE age = '25'; -- age是整数列

6. 使用OR操作符连接不在同一索引中的列:

  1. SELECT * FROM users WHERE age = 25 OR name = 'John';

7. 单独查询复合索引的非最左部分:

  1. -- 假设存在复合索引(age, name) SELECT * FROM users WHERE name = 'John';

8. 使用JOIN但未索引的列:

  1. SELECT * FROM users u JOIN orders o ON u.userID = o.clientID; -- 如果clientID未被索引

9. 对列使用不等式操作符:

  1. SELECT * FROM users WHERE age <> 25;

10. 使用DISTINCT关键字但没有相应的索引:

  1. SELECT DISTINCT city FROM users;

11. 对已索引列进行算数操作:

  1. SELECT * FROM products WHERE price * 0.9 > 100;

12. 使用IS NULL和IS NOT NULL但没有对应的索引:

  1. SELECT * FROM users WHERE address IS NULL;

13. 使用IN操作符的列表过大:

  1. SELECT * FROM users WHERE age IN (25, 26, 27, ... , 50);

14. 在JOIN操作中连接类型不匹配的列:

  1. SELECT * FROM users u JOIN details d ON u.id = CAST(d.user_id AS CHAR);

15. 查询范围过大,使得全表扫描更为高效:

  1. SELECT * FROM users WHERE age > 10;

16. 索引列上使用负操作:

  1. SELECT * FROM products WHERE NOT price = 100;

17. 复合索引中某一列使用范围查询:

  1. -- 假设存在复合索引(age, score) SELECT * FROM users WHERE age > 25 AND score = 100;

18. 使用COALESCE函数:

  1. SELECT * FROM users WHERE COALESCE(name, 'Unknown') = 'John';
  1. 使用UNION操作:

    1. SELECT name FROM users WHERE age = 25 UNION SELECT name FROM users WHERE city = 'Paris';

20. 查询不在索引范围内的数据:

  1. SELECT * FROM users WHERE age = 500; -- 如果数据库中年龄不可能为500

21. 在HAVING子句中使用未被索引的列:

  1. SELECT age, COUNT(*) FROM users GROUP BY age HAVING COUNT(*) > 5;

22. 查询结果集太大,导致索引回表:

  1. SELECT * FROM users WHERE age BETWEEN 20 AND 30;

23. 在ORDER BY子句中使用多个未被索引的列:

  1. SELECT * FROM users ORDER BY age, name;

24. 使用外部参数进行查询:

  1. SET @name = 'John'; SELECT * FROM users WHERE name = @name;

25. 使用多个JOIN且索引未被优化:

  1. SELECT * FROM users u JOIN orders o ON u.id = o.user_id JOIN details d ON o.id = d.order_id;

26. 在WHERE子句中使用CASE语句:

  1. SELECT * FROM users WHERE (CASE WHEN age = 25 THEN 1 ELSE 0 END) = 1;

27. 对JSON类型的数据进行查询:

  1. SELECT * FROM users WHERE profile->'$.age' = 25;

28. 查询含有较多重复值的列:

  1. SELECT * FROM users WHERE gender = 'male'; -- 如果90%的用户都是male

29. 使用非确定性函数:

  1. SELECT * FROM users WHERE birthdate = NOW();

30. 使用存储过程中的动态SQL:

  1. CALL search_users('John'); -- 如果存储过程内部使用了动态SQL进行查询

发表评论

表情:
评论列表 (有 0 条评论,172人围观)

还没有评论,来说两句吧...

相关阅读

    相关 MySQL索引优化失效

    MySQL索引优化失效通常有以下几个原因: 1. 数据量过大:当表数据超过某个阈值时,频繁的全表扫描会导致索引优化失效。 2. 索引选择不合理:如果建的索引覆盖了查询但不完

    相关 MySQL索引失效场景

    常见的导致索引失效的场景: 1、不使用索引列进行过滤:当查询中没有使用索引列作为过滤条件时,索引将无法发挥作用。例如,对于一个有索引的name列,如果查询中没有使用name作