MySql 非常细分数据的分区问题
MySql Partitioning questions for very segmented data
这里有很多分区问题,很多时候人们警告说它通常对性能没有帮助。我想看看我的用例是否是为数不多的用例之一,并澄清一些事情。
在我的用例中,每个用户都将被分配到一个存储桶。存储桶中的每个用户对其他存储桶中的用户都是不可见的。因此,应用程序运行的几乎每个查询都将包含 WHERE bucket = X.
因此,即使 table 中有 10 亿行,任何给定的查询也只关心其中的一小部分。
我的问题是
这个用例真的是一个很好的分区性能助推器吗?
当我将分区列添加到每个唯一键时,该索引看起来像(列 A,分区列)。如果我记得,在复合索引中,您不会单独获得第二个索引的免费索引。因此,如果我对按某些非唯一 C 列排序的分区 5 中的每个用户进行查询,分区列没有自己的索引这一事实是否重要?
根据进入系统的用户数量,可能有 100-200 个这样的分区。我正在查看一个庞大而令人讨厌的分区范围表达式,如下所示
ALTER TABLE XXX
PARTITION BY RANGE(the_thing) (
PARTITION p0 VALUES LESS THAN (1),
PARTITION p1 VALUES LESS THAN (2),
PARTITION p2 VALUES LESS THAN (3),
PARTITION p3 VALUES LESS THAN (4),
PARTITION p3 VALUES LESS THAN (5),
PARTITION p3 VALUES LESS THAN (6),
PARTITION p3 VALUES LESS THAN (7),
PARTITION p3 VALUES LESS THAN (8),
AND ON AND ON AND ON....
PARTITION p3 VALUES LESS THAN (200),
PARTITION p3 VALUES LESS THAN MAX_VALUE);
这看起来真的很尴尬和丑陋。就是这样吗?
是的,这听起来像是一个很好的分区案例,因为您要优化的查询都将搜索特定的分区。通常的问题是许多应用程序混合查询,因此只有其中一些应用程序从分区修剪中受益,而其他应用程序有一些额外的开销,用于对分区进行 N 次查询并统一结果。
如果您将唯一索引定义为像 (ColumnA, PartitionColumn)
这样的复合索引,请记住 ColumnA
仅在给定分区内是唯一的。其他分区中的其他行在 ColumnA
中可以具有相同的值。
例如,即使使用唯一索引,也允许以下内容:
INSERT INTO XXX (ColumnA, PartitionColumn)
VALUES
('abc', 5),
('abc', 6),
('abc', 19);
这可能不是您想要的,但这就是复合唯一索引的工作方式。只要 组 列具有不出现在任何其他行上的唯一值,就允许新行。
至于使用索引,是的,查询可以使用一些不包括分区列的其他索引,即使在进行分区修剪之后也是如此。
如果您使用 RANGE partitioning,则需要庞大的显式分区列表。
您也可以使用 HASH partitioning
ALTER TABLE XXX PARTITION BY HASH(PartitionColumn) PARTITIONS 200;
那么您就不必明确列出每个分区。数据会根据分区表达式的取模自动插入到相应的分区中。分区表达式必须 return 一个整数。
也可以使用KEY partitioning,不限于单列,也不限于整数列。值被连接和散列,并确定用于查找正确分区的整数。散列的方法取决于 table.
的存储引擎
评论:
I will have to create an additional unique constraint on the primary key alone to enforce cross-partition uniqueness
那是行不通的。分区列必须是 all 个唯一键的一部分。
这是大多数想要使用分区的人决定不能使用的最常见原因。
is it guaranteed that only 1 number will map to only 1 partition (assuming I don't go over 200) and that once I assign somebody a value in this column, unless I change it, they would always be on the same partition.
是的,HASH 分区使用确定性操作:取模。如果您有 200 个分区并且所有值都小于 200,则每个分区将只有具有一个值的行。具有该值的行不会占用超过一个分区。
这里有很多分区问题,很多时候人们警告说它通常对性能没有帮助。我想看看我的用例是否是为数不多的用例之一,并澄清一些事情。
在我的用例中,每个用户都将被分配到一个存储桶。存储桶中的每个用户对其他存储桶中的用户都是不可见的。因此,应用程序运行的几乎每个查询都将包含 WHERE bucket = X.
因此,即使 table 中有 10 亿行,任何给定的查询也只关心其中的一小部分。
我的问题是
这个用例真的是一个很好的分区性能助推器吗?
当我将分区列添加到每个唯一键时,该索引看起来像(列 A,分区列)。如果我记得,在复合索引中,您不会单独获得第二个索引的免费索引。因此,如果我对按某些非唯一 C 列排序的分区 5 中的每个用户进行查询,分区列没有自己的索引这一事实是否重要?
根据进入系统的用户数量,可能有 100-200 个这样的分区。我正在查看一个庞大而令人讨厌的分区范围表达式,如下所示
ALTER TABLE XXX PARTITION BY RANGE(the_thing) ( PARTITION p0 VALUES LESS THAN (1), PARTITION p1 VALUES LESS THAN (2), PARTITION p2 VALUES LESS THAN (3), PARTITION p3 VALUES LESS THAN (4), PARTITION p3 VALUES LESS THAN (5), PARTITION p3 VALUES LESS THAN (6), PARTITION p3 VALUES LESS THAN (7), PARTITION p3 VALUES LESS THAN (8), AND ON AND ON AND ON.... PARTITION p3 VALUES LESS THAN (200), PARTITION p3 VALUES LESS THAN MAX_VALUE);
这看起来真的很尴尬和丑陋。就是这样吗?
是的,这听起来像是一个很好的分区案例,因为您要优化的查询都将搜索特定的分区。通常的问题是许多应用程序混合查询,因此只有其中一些应用程序从分区修剪中受益,而其他应用程序有一些额外的开销,用于对分区进行 N 次查询并统一结果。
如果您将唯一索引定义为像 (ColumnA, PartitionColumn)
这样的复合索引,请记住 ColumnA
仅在给定分区内是唯一的。其他分区中的其他行在 ColumnA
中可以具有相同的值。
例如,即使使用唯一索引,也允许以下内容:
INSERT INTO XXX (ColumnA, PartitionColumn)
VALUES
('abc', 5),
('abc', 6),
('abc', 19);
这可能不是您想要的,但这就是复合唯一索引的工作方式。只要 组 列具有不出现在任何其他行上的唯一值,就允许新行。
至于使用索引,是的,查询可以使用一些不包括分区列的其他索引,即使在进行分区修剪之后也是如此。
如果您使用 RANGE partitioning,则需要庞大的显式分区列表。
您也可以使用 HASH partitioning
ALTER TABLE XXX PARTITION BY HASH(PartitionColumn) PARTITIONS 200;
那么您就不必明确列出每个分区。数据会根据分区表达式的取模自动插入到相应的分区中。分区表达式必须 return 一个整数。
也可以使用KEY partitioning,不限于单列,也不限于整数列。值被连接和散列,并确定用于查找正确分区的整数。散列的方法取决于 table.
的存储引擎评论:
I will have to create an additional unique constraint on the primary key alone to enforce cross-partition uniqueness
那是行不通的。分区列必须是 all 个唯一键的一部分。
这是大多数想要使用分区的人决定不能使用的最常见原因。
is it guaranteed that only 1 number will map to only 1 partition (assuming I don't go over 200) and that once I assign somebody a value in this column, unless I change it, they would always be on the same partition.
是的,HASH 分区使用确定性操作:取模。如果您有 200 个分区并且所有值都小于 200,则每个分区将只有具有一个值的行。具有该值的行不会占用超过一个分区。