MySQL - 使用键分区时数据在分区中的分布不均匀

MySQL - Uneven Distribution of Data into Partitions When Using Key Partitioning

  1. 我在 MySQL 5.7.

  2. 上使用 InnoDB 引擎
  3. 我有一个 table,其中一列是(非唯一的)三字母国家代码(例如 "SGP" 代表新加坡,"JPN"日本等)。

  4. 对于我的大部分查询,这个国家代码列是我过滤的第一个 WHERE 子句(例如 WHERE COUNTRY_CODE = 'SGP'

  5. 因此,我想按此列对 table 进行(子)分区。由于我的大部分查询都针对一个国家代码,因此它们只会以这种方式命中一个分区。

  6. 但是,由于有大量不同的国家/地区代码,我不想使用 LIST 分区,因为我必须明确满足每个国家/地区代码的要求。

  7. 所以我用的是KEY分区,有8个分区。我认为键分区,即值被散列,会给我一个或多或少的均匀分布在 8 个分区上(不必是完美的)。

  8. 但是,我遇到的情况是,在8个分区中,其中4个完全没有动过。

这是我的 CREATE TABLE 语句的摘要:

CREATE TABLE TBL_EATING_PLACES (
    ID INT UNSIGNED AUTO_INCREMENT NOT NULL,
    TYPE_OF_FOOD SMALLINT UNSIGNED NOT NULL,
    SUBTYPE_OF_FOOD SMALLINT UNSIGNED NOT NULL,
    COUNTRY_CODE CHAR(3) NOT NULL,
    ADDRESS VARCHAR(255),
    ...
    OTHER_NON_RELEVANT_COLUMNS ...,
    ...,
    CONSTRAINT PKEY PRIMARY KEY (ID, TYPE_OF_FOOD, SUBTYPE_OF_FOOD, COUNTRY_CODE)
)
ENGINE = InnoDB
PARTITION BY LIST COLUMNS(TYPE_OF_FOOD, SUBTYPE_OF_FOOD) SUBPARTITION BY KEY(COUNTRY_CODE) SUBPARTITIONS 8 (
    PARTITION P_1_1 VALUES IN ((1, 1)),
    PARTITION P_1_2 VALUES IN ((1, 2)),
    PARTITION P_2_1 VALUES IN ((2, 1)),
    PARTITION P_1_2 VALUES IN ((2, 2)),
    PARTITION P_1_3 VALUES IN ((2, 2)),
);

我进行 KEY 分区的方式是否有任何问题,以至于它最终只命中了一半的分区?

键分区有什么问题?它提供零收益。不要使用它。相反,提供与您的查询相匹配的合适的复合索引。

(添加以解决评论中的问题...)

通常复合索引可以做与分区相同的事情。 "partition key" 做 "partition pruning" 来选择一个(或几个)分区来查看。通过将 "partition key" 作为索引中的第一列,您可以获得相同的效果。 (是的,也有例外。)

分区有一些开销。每个分区都是一个文件;打开文件是昂贵的。在某些情况下,在进行修剪之前会打开所有分区。以前是INSERT上没有剪枝。 (讨厌!)(其中一些问题已在较新版本中得到解决,但仍有一些开销。)

我看过很多子分区和非 RANGE 分区的例子。我只看到 4 种情况下索引不会将 "as good" 作为分区。我假设您找到了我的博客,其中列出了 4 个。这是一个副本:Partition Maintenance.

二维搜索需要"reduce the search space"。这是4个案例之一。 RANGE 分区处理一个维度,PRIMARY KEY 处理另一个维度。这对 Find the 10 nearest pizza parlors.

有效(但代码混乱)

BY RANGE 是唯一可以处理 'range' 值(例如日期范围)的分区。 HASH 将简单地搜索 所有 个分区。

BY LIST 可能 与 BY RANGE 一样好,但仅限于精确值。然后我回头说 "why not put the partition key on the front of whatever index you would otherwise use"!

如果有人能找到第 5 个用例,如果没有分区我无法提供同等性能,我会很高兴地扩充我的博客。