Используя разбиение MySQL по полю AUTO INCREMENT, как я могу гарантировать, что операторы INSERT/LOAD DATA обращаются только к указанным разделам?

Общий контекст

Я хочу иметь возможность определить при вставке в несбалансированные RANGE-разделенные таблицы MySQL с AUTO INCREMENT первичными ключами, заставляют ли мои вставки MySQL каким-либо образом взаимодействовать с разделами, отличными от тех, которые я указал. Это полезно для планирования будущей емкости для крупномасштабной загрузки данных; с такой уверенностью я мог гораздо точнее предсказать производительность и стоимость аппаратных ресурсов для загрузки данных в базу данных.

Я использую MySQL 5.6.

Конкретный контекст

Скажем, у меня есть следующая таблица в MySQL (5.6):

CREATE TABLE foo (
  `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
  `data` varchar(6) COLLATE utf8_bin NOT NULL
) ENGINE=InnoDB AUTO_INCREMENT=9001 DEFAULT CHARSET=utf8 COLLATE=utf8_bin
/*!12345 PARTITION BY RANGE (id)
(PARTITION cold VALUES LESS THAN (8000) ENGINE = InnoDB,
 PARTITION hot VALUES LESS THAN (9000) ENGINE = InnoDB,
 PARTITION overflow VALUES LESS THAN MAXVALUE ENGINE = InnoDB) */

Предположим, что таблица не разреженная: ни одна строка не была удалена, поэтому count(*) = max(id) = 9001.

Вопросы

  • Если я выполню INSERT INTO foo (data) PARTITION (hot) VALUES ('abc') или эквивалентный оператор LOAD DATA с включенным предложением PARTITION, будут ли доступны какие-либо разделы, кроме выбранного раздела hot?

  • Как узнать, к каким разделам обращаются эти операторы DML?

Что я пробовал

документация по выбору раздела гласит:

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

Кроме того, говорится:

Блокировки, налагаемые операторами LOAD DATA на многораздельные таблицы, не могут быть удалены.

Эти операторы не помогают выяснить, к каким разделам обращаются запросы DML, которые явно указывают раздел.

Я пытался сделать EXPLAIN PARTITIONS INSERT INTO foo ..., но столбец partitions вывода всегда NULL.


person Zac B    schedule 15.06.2018    source источник


Ответы (1)


Согласно документации,

Для операторов, которые вставляют строки, поведение отличается тем, что неудача в поиске подходящего раздела приводит к сбою оператора. Это справедливо как для операторов INSERT, так и для REPLACE.

Поэтому, когда вы пытаетесь вставить строку, которая не соответствует указанному разделу, вы получите

Код ошибки: 1748. Найдена строка, не соответствующая заданному набору разделов.

Это включает операторы, в которых некоторые строки совпадают, а некоторые нет, поэтому вы не можете использовать это для заполнения «горячих» и отбрасывания строк, которые перейдут в «переполнение» (поскольку весь запрос завершится ошибкой).

Выходной файл explain для MySQL 5.6 не включает отдельную строку для insert; значение для partition относится к источнику данных, которые вы вставляете (в случаях, когда вы, например, используете insert ... select ... partition ...), даже если вы используете values() (тогда вы используете «без таблицы», и соответствующий раздел просто null). Для MySQL 5.7+ существует тип «вставка», и он действительно будет отображать только указанный вами раздел.

person Solarflare    schedule 17.06.2018