Под «оптимизированным» вы подразумеваете «самый быстрый»? Или «наименьшее влияние на другие запросы»?
В старых версиях оптимальным способом (без надстроек) было поместить все ADD COLUMNs
в один ALTER TABLE
; затем подождите, пока он не закончится.
В любой версии pt-online-schema-change
добавит все столбцы с коротким временем простоя.
Поскольку вы упомянули ALGORITHM=INPLACE, LOCK=NONE
, я предполагаю, что вы используете более новую версию? Таким образом, может быть оптимальным 8 ALTERs
. Будут некоторые помехи, но, возможно, не "слишком сильные".
ALGORITHM=DEFAULT
позволяет серверу выбрать «лучший». Это почти всегда действительно «лучший». То есть редко нужно говорить что-то кроме DEFAULT
.
Вы никогда не можете получить повреждение данных. В худшем случае запрос может завершиться ошибкой из-за тайм-аута из-за помех ALTER(s)
. Вы всегда должны проверять наличие ошибок (включая тайм-ауты) и обрабатывать их в своем приложении.
Для обсуждения вопросов...
insert into table;
По одному ряду? Или пакетно? (Пакетная обработка более эффективна — возможно, в 10 раз лучше.)
select * from table;
Конечно нет! Это даст вам все столбцы для миллионов строк. Почему вы должны это делать?
select count(column) from table where pk=id and date<NOW();
COUNT(col)
проверяет col
на то, что ему NOT NULL
-- Вам это нужно? Если нет, то просто сделайте COUNT(*)
.
WHERE pk=id
дает вам только одну строку; так зачем еще квалифицироваться с date<NOW()
? PRIMARY KEY
делает запрос максимально быстрым.
Единственный индекс PRIMARY KEY
? Это кажется необычным для таблицы с миллионом строк. Это таблица «Фактов» в приложении «Хранилище данных»?
Внутреннее устройство
(Предостережение: большая часть этого обсуждения Внутреннего происходит косвенно и может быть неверным.)
Для некоторых ALTERs
работа, по сути, заключается только в схеме. Например: добавление опций в конце ENUM
; увеличение размера файла VARCHAR
.
Для некоторых ALTERs
с INPLACE
обработка по существу изменяет данные на месте - без необходимости их копирования. Например: добавление столбца в конце.
PRIMARY KEY
изменения (в InnoDB) обязательно включают перестроение BTree, содержащего данные; их нельзя сделать INPLACE
.
Многие вторичные INDEX
операции можно выполнять, не касаясь (кроме чтения) данных. DROP INDEX
отбрасывает BTree и вносит некоторые мета-изменения. ADD INDEX
читает всю таблицу, строит индекс BTree сбоку, а затем объявляет о своем существовании. Изменения CHARACTER SET
и COLLATION
требуют перестроения индекса.
Если таблица должна быть скопирована, это значит, что таблица заблокирована. Любой ALTER
, которому необходимо прочитать все данные, имеет косвенное влияние из-за операций ввода-вывода и/или ЦП и/или кратковременных блокировок блоков/строк/и т. д.
Неясно, достаточно ли умен код, чтобы справиться с многозадачностью ALTER
наиболее эффективным способом. Добавление 8 столбцов за один INPLACE
проход должно быть возможным, но если это делает код слишком сложным, эту операцию может преобразовать в КОПИРОВАНИЕ.
Возможно, многозадачность ALTER
подойдет в худшем случае. Например, изменение PRIMARY KEY
и увеличение ENUM
просто сделает и то, и другое в одном COPY
. Поскольку COPY
— это оригинальный способ выполнения всех ALTERs
, к настоящему времени он хорошо отлажен и оптимизирован. (Но это медленно и агрессивно.)
COPY
действительно довольно просто реализовать, в основном используя существующие примитивы:
- Заблокируйте
real
, чтобы на него никто не писал
CREATE TABLE new LIKE real;
ALTER TABLE new ...
-- все, что вы просили
- скопируйте все строки от
real
до new
- это медленная часть
RENAME TABLE real TO old, new TO real;
-- быстрый, атомарный и т. д.
- Разблокировать
DROP TABLE old;
INPLACE
более сложен, потому что он должен выбирать среди множества различных алгоритмов и уровней блокировки. DEFAULT
должен переместиться на COPY
, если он не может сделать INPLACE
.
person
Rick James
schedule
29.10.2017