MySQL Study之(翻译)--分区键和唯一性索引及主键之关系

本文涉及的产品
云数据库 RDS MySQL Serverless,0.5-2RCU 50GB
简介:

以下文档翻译自MySQL官方文档,水平有限,翻译不当之处,请大家指正微笑

案例全部验证:

Partitioning Keys, Primary Keys, and Unique Keys

分区键、               主键、                     唯一性索引

This section discusses the relationship of partitioning keys with primary keys and unique keys. The rule governing this relationship can be expressed as follows: All columns used in the partitioning expression for a partitioned table must be part of every unique key that the table may have.

这一节将讨论分区键和主键索引及唯一性索引之间的关系:

可以这样说:

在分区表上,用于分区表达式里的每一个字段都必须是唯一性索引的一部分。

In other words, every unique key on the table must use every column in the table's partitioning expression. (This also includes the table's primary key, since it is by definition a unique key. This particular case is discussed later in this section.) For example, each of the following table creation statements is invalid:

换句话说,表上的每一个唯一性索引必须用于分区表的表达式上(其中包括主键索引)。

例如:以下案例,建立分区表是无效的。

1
2
3
4
5
6
7
8
9
mysql> CREATE TABLE t1 (
     ->     col1 INT NOT NULL,
     ->     col2 DATE NOT NULL,
     ->     col3 INT NOT NULL,
     ->     col4 INT NOT NULL,
     ->     UNIQUE KEY (col1, col2)
     -> )
     -> PARTITION BY HASH(col3)
     -> PARTITIONS  4 ;

ERROR 1503 (HY000): A PRIMARY KEY must include all columns in the table's partitioning function

1
2
3
4
5
6
7
8
9
10
mysql> CREATE TABLE t2 (
     ->     col1 INT NOT NULL,
     ->     col2 DATE NOT NULL,
     ->     col3 INT NOT NULL,
     ->     col4 INT NOT NULL,
     ->     UNIQUE KEY (col1),
     ->     UNIQUE KEY (col3)
     -> )
     -> PARTITION BY HASH(col1 + col3)
     -> PARTITIONS  4 ;

ERROR 1503 (HY000): A PRIMARY KEY must include all columns in the table's partitioning function

In each case, the proposed table would have at least one unique key that does not include all columns used in the partitioning expression.

  以上案例:对于唯一性索引键,至少有一个字段不包含在分区表达式里


Each of the following statements is valid, and represents one way in which the corresponding invalid table creation statement could be made to work:

1
2
3
4
5
6
7
8
9
mysql> CREATE TABLE t1 (
     ->     col1 INT NOT NULL,
     ->     col2 DATE NOT NULL,
     ->     col3 INT NOT NULL,
     ->     col4 INT NOT NULL,
     ->     UNIQUE KEY (col1, col2, col3)
     -> )
     -> PARTITION BY HASH(col3)
     -> PARTITIONS  4 ;

Query OK, 0 rows affected (4.70 sec)

1
2
3
4
5
6
7
8
9
mysql> CREATE TABLE t2 (
     ->     col1 INT NOT NULL,
     ->     col2 DATE NOT NULL,
     ->     col3 INT NOT NULL,
     ->     col4 INT NOT NULL,
     ->     UNIQUE KEY (col1, col3)
     -> )
     -> PARTITION BY HASH(col1 + col3)
     -> PARTITIONS  4 ;

Query OK, 0 rows affected (2.93 sec)

This example shows the error produced in such cases:

1
2
3
4
5
6
7
8
9
10
mysql> CREATE TABLE t3 (
     ->          col1 INT NOT NULL,
     ->          col2 DATE NOT NULL,
     ->          col3 INT NOT NULL,
     ->          col4 INT NOT NULL,
     ->          UNIQUE KEY (col1, col2),
     ->         UNIQUE KEY (col3)
     ->      )
     ->      PARTITION BY HASH(col1 + col3)
     ->     PARTITIONS  4 ;

ERROR 1503 (HY000): A PRIMARY KEY must include all columns in the table's partitioning function

1
2
3
4
5
6
7
8
9
10
mysql> CREATE TABLE t3a (
     ->          col1 INT NOT NULL,
     ->          col2 DATE NOT NULL,
     ->          col3 INT NOT NULL,
     ->          col4 INT NOT NULL,
     ->          UNIQUE KEY (col1, col2),
     ->         UNIQUE KEY (col3)
     ->      )
     ->      PARTITION BY HASH(col1 + col2)
     ->     PARTITIONS  4 ;

ERROR 1503 (HY000): A UNIQUE INDEX must include all columns in the table's partitioning function

1
2
3
4
5
6
7
8
9
10
CREATE TABLE t3 (
          col1 INT NOT NULL,
          col2 DATE NOT NULL,
          col3 INT NOT NULL,
          col4 INT NOT NULL,
          UNIQUE KEY (col1, col2),
         UNIQUE KEY (col3)
      )
      PARTITION BY HASH(col1 + col2+col3 )
     PARTITIONS  4 ;

ERROR 1503 (HY000): A PRIMARY KEY must include all columns in the table's partitioning function


The CREATE TABLE statement fails because both col1 and col3 are included in the proposed partitioning key, but neither of these columns is part of both of unique keys on the table. This shows one possible fix for the invalid table definition:

    以下cretate table语句失败了,是因为col1和col3不同时属于表里两个唯一性索引键。另外一个案例显示如何修复这个问题:

1
2
3
4
5
6
7
8
9
10
mysql> CREATE TABLE t3 (
     ->          col1 INT NOT NULL,
     ->          col2 DATE NOT NULL,
     ->          col3 INT NOT NULL,
     ->          col4 INT NOT NULL,
     ->          UNIQUE KEY (col1, col2,col3),
     ->         UNIQUE KEY (col3)
     ->      )
     ->      PARTITION BY HASH(col1 + col2+col3 )
     ->     PARTITIONS  4 ;

ERROR 1503 (HY000): A UNIQUE INDEX must include all columns in the table's partitioning function

1
2
3
4
5
6
7
8
9
10
11
mysql> CREATE TABLE t3 (
     ->          col1 INT NOT NULL,
     ->          col2 DATE NOT NULL,
     ->          col3 INT NOT NULL,
     ->          col4 INT NOT NULL,
     ->          UNIQUE KEY (col1, col2,col3),
     ->         UNIQUE KEY (col3)
     ->      )
     ->      PARTITION BY HASH(col3 )
     ->     PARTITIONS  4 ;
Query OK,  0  rows affected ( 3.11  sec)

In this case, the proposed partitioning key col3 is part of both unique keys, and the table creation statement succeeds.

以上可以看出,col3同时属于两个唯一性索引的键,所以create table执行成功。


The following table cannot be partitioned at all, because there is no way to include in a partitioning key any columns that belong to both unique keys:

   如下所示,此分区表是无法建立的,因为没有一个分区键,可以同时属于两个唯一性索引的键。

1
2
3
4
5
6
7
8
CREATE TABLE t4 (
     col1 INT NOT NULL,
     col2 INT NOT NULL,
     col3 INT NOT NULL,
     col4 INT NOT NULL,
     UNIQUE KEY (col1, col3),
     UNIQUE KEY (col2, col4)
);

Since every primary key is by definition a unique key, this restriction also includes the table's primary key, if it has one. For example, the next two statements are invalid:

主键也属于唯一性索引,所以以上规则适合于primary key

1
2
3
4
5
6
7
8
9
mysql> CREATE TABLE t5 (
     ->     col1 INT NOT NULL,
     ->     col2 DATE NOT NULL,
     ->     col3 INT NOT NULL,
     ->     col4 INT NOT NULL,
     ->     PRIMARY KEY(col1, col2)
     -> )
     -> PARTITION BY HASH(col3)
     -> PARTITIONS  4 ;

ERROR 1503 (HY000): A PRIMARY KEY must include all columns in the table's partitioning function

1
2
3
4
5
6
7
8
9
10
mysql> CREATE TABLE t6 (
     ->     col1 INT NOT NULL,
     ->     col2 DATE NOT NULL,
     ->     col3 INT NOT NULL,
     ->     col4 INT NOT NULL,
     ->     PRIMARY KEY(col1, col3),
     ->     UNIQUE KEY(col2)
     -> )
     -> PARTITION BY HASH( YEAR(col2) )
     -> PARTITIONS  4 ;

ERROR 1503 (HY000): A PRIMARY KEY must include all columns in the table's partitioning function

1
2
3
4
5
6
7
8
9
10
mysql> CREATE TABLE t6 (
     ->          col1 INT NOT NULL,
     ->          col2 DATE NOT NULL,
     ->          col3 INT NOT NULL,
     ->        col4 INT NOT NULL,
     ->          PRIMARY KEY(col1,col2, col3),
     ->          UNIQUE KEY(col2)
     ->      )
     ->      PARTITION BY HASH( YEAR(col2) )
     ->      PARTITIONS  4 ;

Query OK, 0 rows affected (2.88 sec)


1
2
3
4
5
6
7
8
9
mysql> CREATE TABLE t6a(
     ->          col1 INT NOT NULL,
     ->          col2 DATE NOT NULL,
     ->          col3 INT NOT NULL,
     ->        col4 INT NOT NULL,
     ->          PRIMARY KEY(col1,col2, col3)
     ->      )
     ->      PARTITION BY HASH( YEAR(col2) )
     ->      PARTITIONS  4 ;

Query OK, 0 rows affected (3.51 sec)

1
2
3
4
5
6
7
8
9
mysql> CREATE TABLE t6b(
     ->          col1 INT NOT NULL,
     ->          col2 DATE NOT NULL,
     ->          col3 INT NOT NULL,
     ->        col4 INT NOT NULL,
     ->          PRIMARY KEY(col1,col2, col3)
     ->      )
     ->      PARTITION BY HASH( col3)
     ->      PARTITIONS  4 ;

Query OK, 0 rows affected (4.26 sec)

In both cases, the primary key does not include all columns referenced in the partitioning expression. However, both of the next two statements are valid:

以上两个案例,分区表达式里的字段不包含所有的主键字段。

1
2
3
4
5
6
7
8
9
mysql> CREATE TABLE t7 (
     ->     col1 INT NOT NULL,
     ->     col2 DATE NOT NULL,
     ->     col3 INT NOT NULL,
     ->     col4 INT NOT NULL,
     ->     PRIMARY KEY(col1, col2)
     -> )
     -> PARTITION BY HASH(col1 + YEAR(col2))
     -> PARTITIONS  4 ;

Query OK, 0 rows affected (4.40 sec)

1
2
3
4
5
6
7
8
9
10
mysql> CREATE TABLE t8 (
     ->     col1 INT NOT NULL,
     ->     col2 DATE NOT NULL,
     ->     col3 INT NOT NULL,
     ->     col4 INT NOT NULL,
     ->     PRIMARY KEY(col1, col2, col4),
     ->     UNIQUE KEY(col2, col1)
     -> )
     -> PARTITION BY HASH(col1 + YEAR(col2))
     -> PARTITIONS  4 ;

Query OK, 0 rows affected (3.51 sec)


If a table has no unique keys—this includes having no primary key—then this restriction does not apply, and you may use any column or columns in the partitioning expression as long as the column type is compatible with the partitioning type.

对于没有建立主键或唯一性索引的表,可以将任何兼容分区表的字段放在分区表达式中。


For the same reason, you cannot later add a unique key to a partitioned table unless the key includes all columns used by the table's partitioning expression. Consider the partitioned table created as shown here:

基于同样的原因,你在分区表上添加唯一性索引时,必须符合以上规则。分区表表达式的键,必须包含在所有的唯一性索引中。

1
2
3
4
5
6
7
mysql> CREATE TABLE t_no_pk (c1 INT, c2 INT)
     ->     PARTITION BY RANGE(c1) (
     ->         PARTITION p0 VALUES LESS THAN ( 10 ),
     ->         PARTITION p1 VALUES LESS THAN ( 20 ),
     ->         PARTITION p2 VALUES LESS THAN ( 30 ),
     ->         PARTITION p3 VALUES LESS THAN ( 40 )
     ->     );

Query OK, 0 rows affected (0.12 sec)

It is possible to add a primary key to t_no_pk using either of these ALTER TABLE statements:

#  possible PK

mysql> ALTER TABLE t_no_pk ADD PRIMARY KEY(c1);

Query OK, 0 rows affected (0.13 sec)

Records: 0  Duplicates: 0  Warnings: 0

# drop this PK

mysql> ALTER TABLE t_no_pk DROP PRIMARY KEY;

Query OK, 0 rows affected (0.10 sec)

Records: 0  Duplicates: 0  Warnings: 0

#  use another possible PK

mysql> ALTER TABLE t_no_pk ADD PRIMARY KEY(c1, c2);

Query OK, 0 rows affected (0.12 sec)

Records: 0  Duplicates: 0  Warnings: 0

# drop this PK

mysql> ALTER TABLE t_no_pk DROP PRIMARY KEY;

Query OK, 0 rows affected (0.09 sec)

Records: 0  Duplicates: 0  Warnings: 0

However, the next statement fails, because c1 is part of the partitioning key, but is not part of the proposed primary key:

 然而,以下语句会失败,因为分区键 c1,不属于primary key

#  fails with error 1503

mysql> ALTER TABLE t_no_pk ADD PRIMARY KEY(c2);

ERROR 1503 (HY000): A PRIMARY KEY must include all columns in the table's partitioning function

Since t_no_pk has only c1 in its partitioning expression, attempting to adding a unique key on c2 alone fails. However, you can add a unique key that uses both c1 and c2.

These rules also apply to existing nonpartitioned tables that you wish to partition using ALTER TABLE ... PARTITION BY. Consider a table np_pk created as shown here:

1
2
3
4
5
6
mysql> CREATE TABLE np_pk (
     ->     id INT NOT NULL AUTO_INCREMENT,
     ->     name VARCHAR( 50 ),
     ->     added DATE,
     ->     PRIMARY KEY (id)
     -> );

Query OK, 0 rows affected (0.08 sec)

The following ALTER TABLE statement fails with an error, because the added column is not part of any unique key in the table:

以下,alter table语句将会失败,因为分区键,不包含于唯一性索引。

mysql> ALTER TABLE np_pk

    ->     PARTITION BY HASH( TO_DAYS(added) )

    ->     PARTITIONS 4;

ERROR 1503 (HY000): A PRIMARY KEY must include all columns in the table's partitioning function

However, this statement using the id column for the partitioning column is valid, as shown here:

以下语句将会成功:因为分区键id,包含于主键primary key

mysql> ALTER TABLE np_pk

    ->     PARTITION BY HASH(id)

    ->     PARTITIONS 4;

Query OK, 0 rows affected (0.11 sec)

Records: 0  Duplicates: 0  Warnings: 0

In the case of np_pk, the only column that may be used as part of a partitioning expression is id; if you wish to partition this table using any other column or columns in the partitioning expression, you must first modify the table, either by adding the desired column or columns to the primary key, or by dropping the primary key altogether.

  如以上案例,只有id字段可以作为分区表达式键,如果你还想使用其他的字段用于分区表达式中,你必须修改表结构,添加字段到你的主键里,或者删除主键。











本文转自 客居天涯 51CTO博客,原文链接:http://blog.51cto.com/tiany/1723307,如需转载请自行联系原作者
相关实践学习
基于CentOS快速搭建LAMP环境
本教程介绍如何搭建LAMP环境,其中LAMP分别代表Linux、Apache、MySQL和PHP。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助     相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
目录
相关文章
|
10天前
|
关系型数据库 MySQL 索引
mysql 分析5语句的优化--索引添加删除
mysql 分析5语句的优化--索引添加删除
11 0
|
15天前
|
存储 关系型数据库 MySQL
轻松入门MySQL:优化进销存管理,掌握MySQL索引,提升系统效率(11)
轻松入门MySQL:优化进销存管理,掌握MySQL索引,提升系统效率(11)
|
21天前
|
存储 自然语言处理 关系型数据库
ElasticSearch索引 和MySQL索引那个更高效实用那个更合适
ElasticSearch索引 和MySQL索引那个更高效实用那个更合适
35 0
|
21天前
|
SQL 存储 关系型数据库
MySQL not exists 真的不走索引么
MySQL not exists 真的不走索引么
24 0
|
25天前
|
SQL 存储 关系型数据库
对线面试官 - 如何理解MySQL的索引覆盖和索引下推
索引下推是MySQL 5.6引入的优化,允许部分WHERE条件在索引中处理,减少回表次数。例如,对于索引(zipcode, lastname, firstname),查询`WHERE zipcode='95054' AND lastname LIKE '%etrunia%'`时,索引下推先过滤zipcode,然后在索引中应用lastname条件,降低回表需求。索引下推可在EXPLAIN的`Using index condition`中看到。
对线面试官 - 如何理解MySQL的索引覆盖和索引下推
|
1月前
|
监控 关系型数据库 MySQL
MySQL创建索引的注意事项
在数据库设计和优化中,索引的合理使用是提高查询性能和加速数据检索的关键因素之一。通过选择适当的列、了解数据分布、定期维护和监控索引性能,我们能够最大程度地发挥索引的优势,提高数据库的效率和响应速度。
29 0
|
1月前
|
关系型数据库 MySQL 数据库
MySQL索引和查询优化
MySQL索引和查询优化
33 1
|
1月前
|
SQL 关系型数据库 MySQL
MySQL索引与事务
MySQL索引与事务
|
1月前
|
监控 关系型数据库 MySQL
MySQL创建索引的注意事项
在索引的世界中,权衡是关键。权衡读写性能,权衡索引的数量和类型,权衡查询的频率和数据分布。通过谨慎的设计、定期的维护和持续的监控,我们能够确保索引在数据库中的角色得到最大的发挥,为应用提供更加高效和可靠的数据访问服务。在数据库优化的旅途中,索引是我们的得力助手,正确使用它将使数据库系统更具竞争力和可维护性。
18 0
|
1月前
|
存储 关系型数据库 MySQL
最全MySQL面试60题(含答案):存储引擎+数据库锁+索引+SQL优化等
最全MySQL面试60题(含答案):存储引擎+数据库锁+索引+SQL优化等
162 0