MySQL分区表–hash分区
哈希分区最主要的用法是用来保证数据的平均分布。使用范围分区和列表分区时必须显示地定义分区值或者值列表;但是使用哈希分区时,我们只需要对列值或者基于列值的表达式进行哈希运算,就可以进行分区了。
在进行哈希分区是,我们需要在CREATE TABLE
语句后加上PARTITION BY HASH(expr)
, expr是一个返回整型的表达式。更简单的,我们可以往HASH()
里传递一个列名,这个列的类型必须是MySQL中的整型类型。另外,我们可以在语句后面加上一个PARTITIONS num
来显示的指定分区底层表的数量, num必须是一个整型数字。
在下面的例子中,我们创建一个分区表,用store_id
列进行哈希分区,分成4个底层表:
CREATE TABLE employees (
id INT NOT NULL,
fname VARCHAR(30),
lname VARCHAR(30),
hired DATE NOT NULL DEFAULT '1970-01-01',
separated DATE NOT NULL DEFAULT '9999-12-31',
job_code INT,
store_id INT
)
PARTITION BY HASH(store_id)
PARTITIONS 4;
如果不指定PARTITIONS
, 默认为底层表的数量为1.如果不给PARTITIONS
指定数量,会导致一个语法错误。
我们也可以使用返回整型的SQL表达式。例如,我们希望对员工按年进行分区:
CREATE TABLE employees (
id INT NOT NULL,
fname VARCHAR(30),
lname VARCHAR(30),
hired DATE NOT NULL DEFAULT '1970-01-01',
separated DATE NOT NULL DEFAULT '9999-12-31',
job_code INT,
store_id INT
)
PARTITION BY HASH( YEAR(hired) )
PARTITIONS 4;
expr的返回值必须是非常量、非随机的整型,也就是说这个返回值必须是不同的但是又具有确定性的一个整型数值,不能包含分区约束和限制的结构。当每次修改或者插入数据时,都会对这个表达式求值(删除也有可能);这就意味着,当现实中我们执行批注里操作时,复杂的表达式可能会引起性能问题。
当对单个列进行哈希分区时,这个列的值是按正序或者倒序排列的,这中哈希分区的效率会比较高。表达式使用的列值变化幅度越小,MySQL使用这个表达式进行哈希分区的效率越高。
例如,date_col
列的类型是DATE
, 表达式TO_DAYS(date_col)
会随着date_col
列值的变化而变化,因为date_col
列值的每一个变化,都会引起表达式以一致的方式变化。YEAR(date_col)
的变化则不会像TO_DAYS(date_col)
那么大,因为不是每个date_col
可能的变化都会导致YEAR(date_col)
产生不一样的结果。所以YEAR(date_col)
是一个好的分区候选。
假设我们有一个int类型的列int_col
, 表达式POW(5-int_col, 3) + 6
就不是一个好的分区表达式。原因是int_col
列的没一个变化都会引起表达式大范围的变化。
使用哈希分区时,MySQL通过对表达式的值进行N = MOD(expr, num)
运算来决定使用num个分区中的第N个分区。假设表t1
分成4个分区:
CREATE TABLE t1 (col1 INT, col2 CHAR(5), col3 DATE)
PARTITION BY HASH( YEAR(col3) )
PARTITIONS 4;
现在我们往t1
里插入数据,其中col3
的值为2005-09-15
,分区的判断是这样的:
MOD(YEAR('2005-09-01'),4)
= MOD(2005,4)
= 1