5.SQL优化之查询范围优化

xiaoxiao2025-05-20  29

介绍

范围扫描是指使用索引扫描包含一个或多个索引值内的表行的子集,他可以使用索引中的一部分或者多部分,这里主要是看创建索引时是不是复合索引。

1 单部分索引的范围访问方法

对于单部分索引,索引值间隔可以方便地由WHERE子句中的相应条件表示,表示为范围条件而不是“间隔”。

可以使用单一索引的条件:

对于BTREE和HASH索引,使用=,<=>,IN(),IS NULL或IS NOT NULL运算符时,关键字与常量值的比较是范围条件。另外,对于BTREE索引,关键字与常量值的比较是使用>,<,> =,<=,BETWEEN,!=或<>运算符时的范围条件,或者LIKE比较时的LIKE比较 是一个不以通配符开头的常量字符串。对于所有索引类型,多个范围条件与OR或AND组合形成范围条件。

前面描述中的“常量值”表示以下之一:

来自查询字符串的常量来自同一连接的const或系统表的列不相关子查询的结果完全由前面类型的子表达式组成的任何表达式

以下是一些样例

SELECT * FROM t1 WHERE key_col > 1 AND key_col < 10; SELECT * FROM t1 WHERE key_col = 1 OR key_col IN (15,18,20); SELECT * FROM t1 WHERE key_col LIKE 'ab%' OR key_col BETWEEN 'bar' AND 'foo';

在优化器常量传播阶段,一些非常量值可以转换为常量。

MySQL尝试从每个可能索引的WHERE子句中提取范围条件。 在提取过程期间,丢弃不能用于构建范围条件的条件,组合产生重叠范围的条件,并且去除产生空范围的条件。

请考虑以下语句,其中key1是索引列,而nonkey未编入索引:

SELECT * FROM t1 WHERE (key1 < 'abc' AND (key1 LIKE 'abcde%' OR key1 LIKE '%b')) OR (key1 < 'bar' AND nonkey = 4) OR (key1 < 'uux' AND key1 > 'z');

关键字key1的提取过程如下:

提取WHERE子句

(key1 < 'abc' AND (key1 LIKE 'abcde%' OR key1 LIKE '%b')) OR (key1 < 'bar' AND nonkey = 4) OR (key1 < 'uux' AND key1 > 'z')

删除nonkey = 4和key1 LIKE’%b’,因为它们不能用于索引范围扫描。 删除它们的正确方法是用TRUE替换它们,这样我们在进行范围扫描时不会错过任何匹配的行。 用TRUE替换它们会产生:

(key1 < 'abc' AND (key1 LIKE 'abcde%' OR TRUE)) OR (key1 < 'bar' AND TRUE) OR (key1 < 'uux' AND key1 > 'z')

跳出条件的真或假

(key1 LIKE ‘abcde%’ OR TRUE) 永为真(key1 < ‘uux’ AND key1 > ‘z’) 永为假

用常数替换这些条件会产生:

(key1 < 'abc' AND TRUE) OR (key1 < 'bar' AND TRUE) OR (FALSE)

删除不必要的TRUE和FALSE常量会产生:

(key1 < 'abc') OR (key1 < 'bar')

由于key1 < 'bar’肯定满足key1 < ‘abc’,所以将重叠间隔组合成一个会产生用于范围扫描的最终条件

(key1 < 'bar')

通常(并且如前面的示例所示),用于范围扫描的条件比WHERE子句的限制性更小。 MySQL执行额外的检查以过滤掉满足范围条件但不满足完整WHERE子句的行。

范围条件提取算法可以处理任意深度的嵌套AND/OR结构,其输出不依赖于条件在WHERE子句中出现的顺序。

MySQL不支持合并空间索引的范围访问方法的多个范围。

转载请注明原文地址: https://www.6miu.com/read-5030404.html

最新回复(0)