mysql怎么优化条件 mysql优化十大技巧( 二 )


范围条件提取算法可以处理任意深度嵌套的 AND/OR 构造,并且它的输出不取决于条件在 WHERE 子句中出现的顺序
MySQL不支持为空间索引的 range 访问合并多个范围 。要解决此限制,可以在相同的 SELECT 语句中使用 UNION 语句,将每个空间谓词放在不同的 SELECT 中 。
多列索引的范围条件是单列索引的扩展 , 多列索引的范围条件将索引行限制在一个或多个索引元组的间隔中 。索引元组间隔是一个按照索引顺序的 , 索引元组的集合 。
假设有一个多列索引 key1(key_part1,key_part2,key_part3) ,按照索引顺序,具有以下键值元组列表
key_part1 = 1定义了一个间隔: (1,-inf,-inf) = (key_part1,key_part2,key_part3)(1,+inf,+inf),这个间隔包括上面的第4、5、6个元组并且可以被用来进行范围访问 。
但是, key_part3 = 'abc' 没有定义间隔并且不能被范围访问方法使用 。
就是索引的最左前缀原则,B树索引是有序的,多列索引是首先按照第一列进行排序,然后在第一列排序的基础上,再对第二列数据进行排序,所以后面的列的顺序独立来看不是有序的 , 就不能单独用后面的列来进行排序或者范围访问的操作 。
对于 HASH 索引,只能使用包含相同值的每个间隔 。这意味着只能针对以下形式的条件生成间隔:
这里 ,  const1,const2... 是常量,cmp 是比较表达式: =,=,IS NULL ,并且条件覆盖所有的索引部分(就是说,如果有 N 个条件,那么每个条件都需要是一个 N列 索引的一部分) 。例如:以下是一个三列 HASH 索引的一个范围条件
对于 BTREE 索引,一个间隔可以是使用 AND 组成的多个范围条件的集合,每个条件都将索引的一部分和一个常量使用 =,=,IS NULL,,,=,=,!=,,BETWEENT,LIKE 'pattern'(pattern不以通配符开始) 进行比较 。只要可以确定与条件匹配的一个索引元组,就可以使用一个间隔( !=, 使用两个间隔)
当比较运算符是 =,=,IS NULL 时,优化器尝试使用索引的其他部分来确定间隔 。如果比较运算符是 , , =, =, !=, , BETWEEN, LIKE ,优化器使用索引,但不考虑索引中的其他列 。
对于以下表达式,优化器使用第一个 = ,也会使用第二个 = ,但是忽略其他索引部分,并且不将第三部分用作间隔构造 。
key_part1 = 'foo' AND key_part2 = 10 AND key_part310
单个间隔为:
创建的间隔中可能包括比原始条件更多的行,比如,前面这个间隔可能会包括 ('foo',11,0) 这个值 ,  010 ,这个值不满足原始条件
如果覆盖间隔中的行集合的条件使用 OR 进行组合,则他们会形成间隔的并集 。
如果条件使用 AND 进行组合,他们形成一个包括间隔交集的行集合 。
示例:
这个在两列索引上的条件:
(key_part1 = 1 AND key_part22) OR (key_part15)
间隔是:
可以查看 EXPLAIN 输出中的 key_len 部分查看使用的索引前缀的最大长度 。
在某些情况下,key_len 包括已使用的索引列,但是这个列可能不是你期望的,假设 key_part1 和 key_part2 可以为 NULL ,然后,key_len 显示以下条件的两个索引部分长度:
key_part1 = 1 AND key_part22
但是实际上,这个条件被转换为:
key_part1 = 1 AND key_part2 IS NOT NULL
假设以下表达式, col_name 是一个索引的列
只要 col_name 等同于这些值中的任意一个 , 这个表达式结果就是 true。这种比较是等值范围比较(其中的“范围”是一个单独的值) 。
优化器按照以下方法,估算读取相等的值来进行等值范围比较的成本:
当使用 index dive 时,优化器在每个范围的末端进行 dive 并且使用该范围中的行数作为估算值 。例如: col_name IN (10, 20, 30) 具有三个等值范围,优化器对每个范围进行两次 dive 以生成估算值 。每次 dive 都会得出具有给定值的行数的估算值 。

推荐阅读