mysql分区错误主键必须包含表中的所有列';s分配函数
在MySQL 8上,我有一个表:mysql分区错误主键必须包含表中的所有列';s分配函数,mysql,laravel,partitioning,Mysql,Laravel,Partitioning,在MySQL 8上,我有一个表: CREATE TABLE `float_values` ( `id` bigint UNSIGNED NOT NULL, `attribute_id` bigint UNSIGNED NOT NULL, `value` double(8,2) NOT NULL, `created_at` date NOT NULL, `updated_at` date NOT NULL ) ENGINE=InnoDB DEFAULT CHARSET=utf8
CREATE TABLE `float_values` (
`id` bigint UNSIGNED NOT NULL,
`attribute_id` bigint UNSIGNED NOT NULL,
`value` double(8,2) NOT NULL,
`created_at` date NOT NULL,
`updated_at` date NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
ALTER TABLE `float_values`
ADD PRIMARY KEY (`id`),
ADD UNIQUE KEY `float_values_created_at_unique` (`created_at`);
ALTER TABLE `float_values`
MODIFY `id` bigint UNSIGNED NOT NULL AUTO_INCREMENT;
COMMIT;
使用此模式:
Schema::create('float_values', function (Blueprint $table) {
$table->bigIncrements('id');
$table->unsignedBigInteger('attribute_id');
$table->float('value');
$table->date('created_at');
$table->date('updated_at');
});
Schema::create('float_values', function (Blueprint $table) {
$table->unsignedBigInteger('id');
$table->unsignedBigInteger('attribute_id');
$table->float('value');
$table->date('created_at');
$table->primary(['id', 'created_at']);
$table->date('updated_at');
});
在创建表之后,我在列中创建的_上进行了分区:
ALTER TABLE float_values
PARTITION BY HASH( YEAR(created_at) )
PARTITIONS 4
但我得到了这个错误:
静态分析:
1分析中发现错误
无法识别的alter操作。(位置0处的“”附近)SQL查询:
更改表浮点值按哈希分区(年(创建时))
分区4
MySQL说:文档
1503-主键必须包括表分区函数中的所有列
我知道这个问题是重复的,但答案对我没有帮助
错误表示我们必须将created_at宣布为primary,但我们不能将created_at的两个主键更改为unique,但问题仍然存在,原因是:
分区表的分区表达式中使用的所有列必须是该表可能具有的每个唯一键的一部分
换句话说,表上的每个唯一键都必须使用表分区表达式中的每一列。这还包括表的主键,因为根据定义它是唯一的键
对于许多想要在MySQL中使用表分区的人来说,这是一个拦截器。您不能总是按要分区的列进行分区,因为它不是在唯一键中,或者表中有其他唯一(或主)键
记住:分区表达式必须是表的每个唯一键的一部分
即使要使created_at
成为唯一键,此表的主键仍然位于id
列上
如果您同时拥有主键和唯一键,并且这两个键没有共同的列,则无法在MySQL表上使用分区。说:
分区表的分区表达式中使用的所有列必须是该表可能具有的每个唯一键的一部分
换句话说,表上的每个唯一键都必须使用表分区表达式中的每一列。这还包括表的主键,因为根据定义它是唯一的键
对于许多想要在MySQL中使用表分区的人来说,这是一个拦截器。您不能总是按要分区的列进行分区,因为它不是在唯一键中,或者表中有其他唯一(或主)键
记住:分区表达式必须是表的每个唯一键的一部分
即使要使created_at
成为唯一键,此表的主键仍然位于id
列上
如果您同时拥有主键和唯一键,并且这两个键没有共同的列,则无法在MySQL表上使用分区。我找到了答案
当我迁移表时,它在id上创建了一个主增量列,所以当我执行alter partition查询时,它告诉我分区列必须是主键!
我将要做的是在我的模式中创建一个没有主键和增量列的表,然后在创建一个没有主键的简单表之后,我创建了一个主键包含id,在列处创建,如下所示:
首先:
CREATE TABLE `float_values` (
`id` bigint UNSIGNED NOT NULL,
`attribute_id` bigint UNSIGNED NOT NULL,
`value` double(8,2) NOT NULL,
`created_at` date NOT NULL,
`updated_at` date NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
使用此模式:
Schema::create('float_values', function (Blueprint $table) {
$table->bigIncrements('id');
$table->unsignedBigInteger('attribute_id');
$table->float('value');
$table->date('created_at');
$table->date('updated_at');
});
Schema::create('float_values', function (Blueprint $table) {
$table->unsignedBigInteger('id');
$table->unsignedBigInteger('attribute_id');
$table->float('value');
$table->date('created_at');
$table->primary(['id', 'created_at']);
$table->date('updated_at');
});
然后这个查询:
alter TABLE float_values add primary key (`id`, `created_at`)
我找到了答案
当我迁移表时,它在id上创建了一个主增量列,所以当我执行alter partition查询时,它告诉我分区列必须是主键!
我将要做的是在我的模式中创建一个没有主键和增量列的表,然后在创建一个没有主键的简单表之后,我创建了一个主键包含id,在列处创建,如下所示:
首先:
CREATE TABLE `float_values` (
`id` bigint UNSIGNED NOT NULL,
`attribute_id` bigint UNSIGNED NOT NULL,
`value` double(8,2) NOT NULL,
`created_at` date NOT NULL,
`updated_at` date NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
使用此模式:
Schema::create('float_values', function (Blueprint $table) {
$table->bigIncrements('id');
$table->unsignedBigInteger('attribute_id');
$table->float('value');
$table->date('created_at');
$table->date('updated_at');
});
Schema::create('float_values', function (Blueprint $table) {
$table->unsignedBigInteger('id');
$table->unsignedBigInteger('attribute_id');
$table->float('value');
$table->date('created_at');
$table->primary(['id', 'created_at']);
$table->date('updated_at');
});
然后这个查询:
alter TABLE float_values add primary key (`id`, `created_at`)
通过散列进行分区
是无用的;不要费心想办法让它工作
此外,作为一般规则,除非至少有一百万行,否则分区是没有用的。由于您要求将日期
设置为唯一
,因此我怀疑您的行数不会超过几千行
如果您想解释表的用途、它的最终大小、使用哈希的目标以及您将使用的一些选择,我可能可以解释如何在不进行分区的情况下实现您的目标
场景:
对于这些查询:
... WHERE id = 111 AND created_at BETWEEN ... AND ... -- case 1
... WHERE attribute_id = 222 -- case 2
... WHERE attribute_id = 333 AND created_at BETWEEN ... AND ... -- case 3
那么您的表可能是非分区的:
CREATE TABLE `float_values` (
`id` bigint UNSIGNED NOT NULL AUTO_INCREMENT, -- debatable
`attribute_id` bigint UNSIGNED NOT NULL,
`value` double(8,2) NOT NULL,
`created_at` date NOT NULL,
`updated_at` date NOT NULL
PRIMARY KEY(id), -- for case 1
INDEX(attribute_id, created_at) -- for cases 2, 3
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
通过散列进行分区
是无用的;不要费心想办法让它工作
此外,作为一般规则,除非至少有一百万行,否则分区是没有用的。由于您要求将日期
设置为唯一
,因此我怀疑您的行数不会超过几千行
如果您想解释表的用途、它的最终大小、使用哈希的目标以及您将使用的一些选择,我可能可以解释如何在不进行分区的情况下实现您的目标
场景:
对于这些查询:
... WHERE id = 111 AND created_at BETWEEN ... AND ... -- case 1
... WHERE attribute_id = 222 -- case 2
... WHERE attribute_id = 333 AND created_at BETWEEN ... AND ... -- case 3
那么您的表可能是非分区的:
CREATE TABLE `float_values` (
`id` bigint UNSIGNED NOT NULL AUTO_INCREMENT, -- debatable
`attribute_id` bigint UNSIGNED NOT NULL,
`value` double(8,2) NOT NULL,
`created_at` date NOT NULL,
`updated_at` date NOT NULL
PRIMARY KEY(id), -- for case 1
INDEX(attribute_id, created_at) -- for cases 2, 3
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
引用那个人的话,“不要麻烦使用散列。”引用那个人的话,“不要麻烦使用散列。”谢谢比尔,我只是不知道如何添加一个包含两列的主键,我发现最后我只需要创建一个表,然后将这些主键添加到一起,我现在只是不知道是否可以将id和日期字段作为主键!这意味着不再保证id
本身是唯一的。可以有许多行具有相同的id
值,只要它们具有不同的时间戳。这解决了分区问题,但这意味着表约束作为主键是非常无用的