一个非常大的表的 SQL 分区

Posted

技术标签:

【中文标题】一个非常大的表的 SQL 分区【英文标题】:SQL Partitioning of a very large table 【发布时间】:2019-10-03 21:50:57 【问题描述】:

我正在尝试对名为 companyScores 的非常大的 mysql 表(6000 万行和 50 列)进行分区。 基本上,该表包含公司(列 varchar “company_idx”,唯一 ID 从 0 到 10,000 个公司)及其各自的时间戳(列“timestamp”)和分数“Scores”(列“Scores”)。 我想在每个分区中包含大约 500 家公司。 请让我知道以下是否可以完成这项工作?

ALTER TABLE `companyScores`
PARTITION BY RANGE( company_idx ) (
    PARTITION p0 VALUES LESS THAN (500),
    PARTITION p1 VALUES LESS THAN (1000),
    PARTITION p2 VALUES LESS THAN (1500),
    PARTITION p3 VALUES LESS THAN (2000),
    and so on...
);

以上方法有用吗?

另外,一旦这个数据库被分区,我们是否可以轻松地将新值插入到这个数据库中?

【问题讨论】:

【参考方案1】:

以上方法有用吗?

没有。有几个原因。

如果company_idx 是varchar,则需要使用RANGE COLUMNSRANGE 分区仅适用于整数。如果您尝试在 varchar 上使用 RANGE 分区,则会收到以下错误:

ERROR 1659 (HY000): Field 'company_idx' is of a not allowed type for this type of partitioning

假设你改正了,你还有另一个问题:

您的分区子句使用整数值,而不是带引号的字符串值。这些是不同的类型,分区引擎不会使用它们来定义分区。如果你尝试,你会出现这个错误:

ERROR 1654 (HY000): Partition column values of incorrect type

假设您通过引用数字来纠正这一点,您还有另一个问题:

您在字符串 1000 之前列出了 500 的分区,但在词法上,字符串 '500' 应该在字符串 '1000' 之后。 RANGE 或 RANGE COLUMNS 分区必须按升序声明。如果您尝试按照您的顺序执行此操作,您将收到此错误:

ERROR 1493 (HY000): VALUES LESS THAN value must be strictly increasing for each partition

假设您更正了订单,它可以工作,但它可能无法达到您想要的效果:

CREATE TABLE `companyScores` (
  `company_idx` varchar(10) NOT NULL,
  PRIMARY KEY (`company_idx`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4
/*!50500 PARTITION BY RANGE  COLUMNS(company_idx)
(PARTITION p1 VALUES LESS THAN ('1000') ENGINE = InnoDB,
 PARTITION p2 VALUES LESS THAN ('1500') ENGINE = InnoDB,
 PARTITION p3 VALUES LESS THAN ('2000') ENGINE = InnoDB,
 PARTITION p0 VALUES LESS THAN ('500') ENGINE = InnoDB) */

现在你又问了一个问题:

另外,一旦它被分区,我们是否可以轻松地将新值插入到这个数据库中?

如果你插入一个未被你定义的分区覆盖的新值,你会得到这个错误:

mysql> insert into companyScores set company_idx = '700';
ERROR 1526 (HY000): Table has no partition for value from column_list

这是为什么呢?您的 company_idx 分区小于 1000 对吗?

没有。您的 company_idx 分区小于 string '1000'。您尝试插入字符串“700”,它在词法上大于“500”,以及所有其他分区。因此它超出了定义的任何分区。

如果将 customer_idx 更改为整数列,则可以解决上述所有问题。

【讨论】:

感谢您所做的一切,它现在运行良好。不过我还有一个问题,当我想向特定分区插入新行时,我该怎么做?我是否说“INSERT INTO companyScores PARTITION (p500) ...”它是否也添加到了整个表格中?还是只有分区? 新行仅存储在一个分区中,具体取决于您为表声明的分区方案。没有“整表”——表只是其分区的总和。 所以我总是需要声明将我的新数据插入到哪个分区? 不,您从不需要声明哪个分区。它由您插入的行中的值决定。

以上是关于一个非常大的表的 SQL 分区的主要内容,如果未能解决你的问题,请参考以下文章

在 PLSQL 中,如何迭代更新一个非常大的表的字段?

如何使用python有效地填充给定一个非常大的表的矩阵?

SQL Server 2008 分区函数和分区表

Mysql优化-分区

SQL Server 聚合非常大的表

索引分区表上的查询计划。避免顺序扫描