这个优化被称为分区修剪是基于一个相对简单的概念,可以描述为”不扫描没有匹配值的分区”.假设有一个分区表t1
由以下语句创建:
CREATE TABLE t1 (fname VARCHAR(50) NOT NULL, lname VARCHAR(50) NOT NULL, region_code TINYINT UNSIGNED NOT NULL, dob DATE NOT NULL)分区范围(region_code)(分区p0值小于(64),分区p1值小于(128),分区p2值小于(192),分区p3值小于MAXVALUE);
假设您希望从一个选择
这样的陈述:
SELECT t1 WHERE region_code > 125 AND region_code < 130;
很容易看出,应该返回的行都不在两个分区中p0
或p3
;也就是说,我们只需要在分区中进行搜索p1
而且p2
查找匹配的行。通过限制搜索,与扫描表中的所有分区相比,查找匹配行花费的时间和精力可能要少得多。这”割掉”不需要的分区称为修剪.当优化器在执行此查询时可以使用分区修剪时,查询的执行速度可能比对包含相同列定义和数据的非分区表执行相同查询快一个数量级。
优化器可以执行修剪每当在哪里
Condition可以简化为以下两种情况之一:
partition_column
=常数
partition_column
在(constant1
,constant2
、……constantN
)
在第一种情况下,优化器只计算给定值的分区表达式,确定哪个分区包含该值,并只扫描该分区。在许多情况下,等号可以替换为另一种算术比较,包括<
,>
,< =
,> =
,<>
.一些查询使用之间的
在在哪里
子句还可以利用分区修剪。请参阅本节后面的示例。
在第二种情况下,优化器为列表中的每个值计算分区表达式,创建匹配分区的列表,然后只扫描该分区列表中的分区。
选择
,删除
,更新
语句支持分区修剪。一个插入
语句也只能访问每个插入行的一个分区;即使对于由分割的表也是如此哈希
或关键
虽然这目前没有显示在的输出中解释
.
修剪也可以应用于较短的范围,优化器可以将其转换为等价的值列表。例如,在前面的例子中在哪里
子句可以转换为WHERE region_code IN (126, 127, 128, 129)
.然后优化器可以确定列表中的前两个值在分区中找到p1
,分区中剩下的两个值p2
其他分区不包含相关值,因此不需要搜索匹配的行。
的优化器还可以执行修剪在哪里
使用的表的多个列上涉及前面类型的比较的条件范围列
或名单列
分区。
当分区表达式包含一个等式或一个可以简化为一组等式的范围时,或者当分区表达式表示递增或递减关系时,就可以应用这种类型的优化。修剪还可以应用于在a上分区的表日期
或DATETIME
列时,分区表达式使用年()
或TO_DAYS ()
函数。类时,还可以对这类表应用修剪TO_SECONDS ()
函数。
假设表t2
在a上分割日期
列,使用如下所示的语句创建:
CREATE TABLE t2 (fname VARCHAR(50) NOT NULL, lname VARCHAR(50) NOT NULL, region_code TINYINT UNSIGNED NOT NULL, dob DATE NOT NULL) PARTITION BY RANGE(YEAR(dob))(分区d0值小于(1970),分区d1值小于(1975),分区d2值小于(1980),分区d3值小于(1985),分区d4值小于(1990),分区d5值小于(2000),分区d6值小于(2005),分区d7值小于MAXVALUE);
以下语句使用t2
可以用分区做修剪:
SELECT * FROM t2 WHERE dob = '1982-06-23';SET region_code = 8 WHERE dob BETWEEN '1991-02-15' AND '1997-04-25';WHERE dob >= '1984-06-21' AND dob <= '1999-06-21'
在最后一条语句的情况下,优化器还可以执行如下操作:
找到包含范围低端的分区.
(“1984-06-21”)
收益率的值1984
,在分区中找到d3
.找到包含范围的高端的分区.
(“1999-06-21”)
计算结果为1999
,在分区中找到d5
.只扫描这两个分区和它们之间的任何分区.
在本例中,这意味着只有分区
d3
,d4
,d5
扫描。其余的分区可以被安全地忽略(也可以被忽略)。
无效的日期
而且DATETIME
中引用的在哪里
的条件被处理为零
.这意味着查询,例如SELECT * FROM
不返回任何值(参见Bug #40972)。partitioned_table
在哪里date_column
<“2008-12-00”
到目前为止,我们只看了使用范围
分区,但修剪也可以应用于其他分区类型。
考虑一个由。分割的表列表
,其中分区表达式正在增加或减少,如表t3
这里显示。(在本例中,为了简洁起见,我们假设region_code
列的值限制在1到10之间(包括在内)。
CREATE TABLE t3 (fname VARCHAR(50) NOT NULL, lname VARCHAR(50) NOT NULL, region_code TINYINT UNSIGNED NOT NULL, dob DATE NOT NULL) PARTITION BY LIST(region_code) (PARTITION r0 VALUES IN (1,3), PARTITION r1 VALUES IN (2,5,8), PARTITION r2 VALUES IN (4,9), PARTITION r3 VALUES IN (6,7,10));
对于这样的语句SELECT * FROM t3 WHERE region_code在1和3之间
,优化器确定在哪些分区中找到值1、2和3 (r0
而且r1
)并跳过其余的(r2
而且r3
).
对于由。划分的表哈希
或(线性)的关键
的情况下,分区修剪也是可能的在哪里
子句使用了简单的=
与分区表达式中使用的列的关系。考虑一个这样创建的表:
CREATE TABLE t4 (fname VARCHAR(50) NOT NULL, lname VARCHAR(50) NOT NULL, region_code TINYINT UNSIGNED NOT NULL, dob DATE NOT NULL)
比较列值和常量的语句可以被修剪:
UPDATE t4 WHERE region_code = 7;
修剪也可以用于短范围,因为优化器可以把这样的条件变成在
关系。例如,使用同一个表t4
正如前面定义的,这样的查询可以被修剪:
SELECT * FROM t4 WHERE region_code < 6 AND region_code < 6;SELECT * FROM t4 WHERE region_code BETWEEN 3 AND 5;
在这两种情况下在哪里
子句由优化器转换为WHERE region_code IN (3,4,5)
.
只有当范围大小小于分区数量时,才使用此优化。考虑一下这句话:
WHERE region_code在4到12之间
这个范围在哪里
子句涵盖了9个值(4,5,6,7,8,9,10,11,12),但是t4
只有8个分区。这意味着删除
无法修剪。
当一个表被哈希
或(线性)的关键
,修剪只能在整数列上使用。例如,这个语句不能使用修剪,因为强加于人
是一个日期
专栏:
SELECT * FROM t4 WHERE dob >= '2001-04-14' AND dob <= '2005-10-15';
但是,如果表将年值存储在INT
列,则查询有WHERE year_col >= 2001 AND year_col <= 2005
可以修剪。
表使用提供自动分区的存储引擎,例如NDB
MySQL集群使用的存储引擎如果是显式分区,可以被修剪。