MySql分区问题,用于非常细分的数据

问题描述

这里有很多分区问题,很多时候人们警告说,这样做通常对性能没有帮助。我想看看我的用例是否是少数几个用例之一,并且还要弄清楚一些内容

在我的用例中,每个用户都将分配到一个存储桶。存储桶中的每个用户都无法看到其他存储桶中的用户。因此,应用程序运行的几乎每个查询都将包含WHERE bucket = X。

因此,即使表中有10亿行,任何给定的查询也只关心其中的一小部分。

我的问题是

  1. 这是一个真正的分区性能提升用例吗?

  2. 当我将分区列添加到每个唯一键时,该索引将看起来像(列A,分区列)。如果我还记得,在复合索引中,您自己不会在第二索引上获得免费索引。因此,如果我对分区5中由非唯一列C排序的每个单个用户进行查询,那么分区列没有自己的索引这一事实是否重要?

  3. 这些分区可能有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),19);

这可能不是您想要的,但这就是复合唯一索引的工作方式。只要列的 set 具有在其他任何行上都不会出现的唯一值,就允许新行。

关于使用索引,是的,查询可以使用其他一些不包括分区列的索引,即使在进行分区修剪之后。

如果使用显示的RANGE partitioning,则需要大量的显式分区列表。

您也可以使用HASH partitioning

ALTER TABLE XXX PARTITION BY HASH(PartitionColumn) PARTITIONS 200;

然后,您不必明确列出每个分区。数据将根据分区表达式的模数自动插入到相应分区中。分区表达式必须返回一个整数。

您还可以使用KEY partitioning,它不仅限于单列,也不限于整数列。这些值被级联和散列,并确定用于查找正确分区的整数。哈希的方法取决于表的存储引擎。


评论:

我将仅在主键上创建一个附加的唯一约束,以实现跨分区的唯一性

那是行不通的。分区列必须是 all 唯一键的一部分。

这是大多数想要使用分区的人决定不能这样做的最常见原因。

是否保证只有1个数字将映射到1个分区(假设我没有超过200个),并且一旦我在此列中为某人分配了一个值,除非我对其进行更改,否则它们将始终位于同一位置分区。

是的,HASH分区使用确定性操作:模数。如果您有200个分区,并且所有值均小于200,则每个分区将仅具有一个值的行。并且具有该值的行将不会占用一个以上的分区。