mysql ошибка разбиения PRIMARY KEY должен включать все столбцы в функции разбиения таблицы - PullRequest
1 голос
/ 30 января 2020

Вкл. 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=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');
        });

после того, как таблица создана, я сделал это для разделения на столбец созданный_кат:

ALTER TABLE float_values 
PARTITION BY HASH( YEAR(created_at) )
PARTITIONS 4

но я получаю эту ошибку:

Stati c анализ:

1 ошибки были найдены во время анализа.

Нераспознанная операция изменения. (около "" в позиции 0) SQL запрос:

ALTER TABLE float_values ​​PARTITION HA SH (YEAR (create_at)) PARTITIONS 4

MySQL сказал: Документация

1503 - ПЕРВИЧНЫЙ КЛЮЧ должен включать все столбцы в функции разбиения таблицы

Я знаю, что вопрос повторяется, но ответы мне не помогли!

ошибка говорит, что мы должны объявить create_at как первичный, но у нас не может быть двух первичных ключей, я изменил созданный_натур на уникальный, но проблема все еще существует

Ответы [ 3 ]

3 голосов
/ 30 января 2020

https://dev.mysql.com/doc/refman/8.0/en/partitioning-limitations-partitioning-keys-unique-keys.html говорит:

Все столбцы, используемые в выражении разбиения для многораздельной таблицы, должны быть частью каждого уникального ключа, который может иметь таблица.

Другими словами, каждый уникальный ключ в таблице должен использовать каждый столбец в выражении разделения таблицы. Сюда также входит первичный ключ таблицы, поскольку по определению он является уникальным ключом.

Это блокировщик для многих людей, которые хотят использовать разбиение таблицы в MySQL. Вы не всегда можете разделить по столбцу, по которому хотите разделить, потому что он либо не содержит уникальный ключ, либо в таблице есть какой-то другой уникальный (или первичный) ключ.

Помните: выражение разделения должен быть частью КАЖДОГО уникального ключа таблицы.

Даже если вы сделаете created_at уникальным ключом, все еще существует тот факт, что первичный ключ этой таблицы включен столбец id.

Невозможно использовать разбиение таблицы MySQL, если у вас есть и PRIMARY KEY, и UNIQUE KEY, и эти два ключа не имеют общего столбца.

0 голосов
/ 01 февраля 2020

PARTITION BY HASH бесполезен; не пытайтесь понять, как заставить это работать.

Более того, как правило, разбиение на разделы бесполезно, если у вас не менее миллиона строк. Поскольку вы просите, чтобы DATE было UNIQUE, я подозреваю, что у вас будет не более нескольких тысяч строк.

Если вы хотите объяснить назначение таблицы, ее возможный размер, цель использования Ha sh и некоторые SELECTs, которые вы будете использовать, я, вероятно, могу объяснить, как достичь ваших целей без разделения.

Scenar ios:

Для этих запросов:

... 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;
0 голосов
/ 30 января 2020

Я нашел свой ответ.

, когда я переносил таблицу, он создал основной столбец приращения для идентификатора, поэтому, когда я выполнял запрос на изменение раздела, он говорил, что столбец разделения должен быть первичным ключом. ! Я должен был создать таблицу без первичных ключей и столбцов инкрементов в моей схеме, а затем, после создания простой таблицы без создания первичных ключей, создать первичный ключ, содержащий столбцы id, create_at , например:

Сначала это:

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->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`)
...