Перейти к содержимому
Последнее обновление

INSERT

Описание​

Этот оператор предназначен для вставки данных.

INSERT INTO table_name
[ PARTITION (p1, ...) ]
[ WITH LABEL label]
[ (column [, ...]) ]
[ [ hint [, ...] ] ]
{ VALUES ( { expression | DEFAULT } [, ...] ) [, ...] | query }

Параметры

tablet_name: Целевая таблица для загрузки данных. Можно указать в формате db_name.table_name

partitions: Указывает разделы для загрузки данных. Эти разделы должны существовать в table_name. Имена нескольких разделов разделяются запятыми

label: Указывает метку для задачи Insert

column_name: Указывает целевой столбец. Этот столбец должен существовать в table_name

expression: Выражение, значение которого нужно присвоить столбцу

DEFAULT: Позволяет использовать значение по умолчанию для соответствующего столбца

query: Обычный запрос, результат которого будет записан в целевую таблицу

hint: Подсказка, определяющая поведение при выполнении INSERT. Можно выбрать одно из следующих значений: /*+ STREAMING */, /*+ SHUFFLE */ или `/*+ NOSHUFFLE */.

  1. STREAMING: В настоящее время не оказывает практического воздействия и сохранена только для совместимости с предыдущими версиями. (В предыдущей версии добавление этой подсказки приводило к возврату метки, а теперь метка возвращается по умолчанию)
  2. SHUFFLE: Если целевая таблица разделена на разделы, включение этой подсказки приведет к перераспределению данных между разделами.
  3. NOSHUFFLE: Даже если целевая таблица разделена на разделы, перераспределение данных между ними не выполняется. Вместо этого выполняются другие операции, обеспечивающие корректное размещение данных в каждом разделе.

Для таблицы Unique с включенным merge-on-write оператор insert также позволяет обновлять отдельные столбцы. Для этого необходимо установить переменную сеанса enable_unique_key_partial_update в true (по умолчанию эта переменная имеет значение false, то есть обновление отдельных столбцов с помощью оператора insert по умолчанию запрещено). При обновлении отдельных столбцов в список вставляемых столбцов необходимо включить как минимум все столбцы Key и указать столбцы, которые требуется обновить. Если значения столбцов Key вставляемой строки уже существуют в исходной таблице, данные строки с такими же значениями ключевых столбцов будут обновлены. Если значения столбцов Key вставляемой строки отсутствуют в исходной таблице, в таблицу будет добавлена новая строка. В этом случае столбцы, не указанные в операторе insert, должны либо иметь значения по умолчанию, либо допускать null. Сначала для этих отсутствующих столбцов предпринимается попытка использовать значения по умолчанию. Если у столбца нет значения по умолчанию, он заполняется значением null. Если столбец не допускает null, операция вставки завершится ошибкой.

Обратите внимание: переменная сеанса enable_insert_strict, определяющая, работает ли оператор insert в строгом режиме, по умолчанию имеет значение true. Другими словами, оператор insert по умолчанию работает в строгом режиме, в котором при обновлении отдельных столбцов запрещено обновлять несуществующие ключи. Поэтому, если при обновлении отдельных столбцов с помощью оператора insert требуется вставлять строки с несуществующими ключами, необходимо установить enable_unique_key_partial_update в true и одновременно установить enable_insert_strict в false.

Примечание:

При выполнении оператора INSERT по умолчанию отфильтровываются данные, не соответствующие формату целевой таблицы, например слишком длинные строки. Однако в бизнес-сценариях, где отфильтровывание данных недопустимо, можно установить переменную сеанса enable_insert_strict в true, чтобы INSERT не завершался успешно, если какие-либо данные были отфильтрованы.

Пример​

Таблица test содержит два столбца: c1, c2.

  1. Загрузка одной строки данных в таблицу test
INSERT INTO test VALUES (1, 2);
INSERT INTO test (c1, c2) VALUES (1, 2);
INSERT INTO test (c1, c2) VALUES (1, DEFAULT);
INSERT INTO test (c1) VALUES (1);

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

  1. Загрузка нескольких строк данных в таблицу test за один раз
INSERT INTO test VALUES (1, 2), (3, 2 + 2);
INSERT INTO test (c1, c2) VALUES (1, 2), (3, 2 * 2);
INSERT INTO test (c1) VALUES (1), (3);
INSERT INTO test (c1, c2) VALUES (1, DEFAULT), (3, DEFAULT);

Первый и второй операторы дают одинаковый результат: загружают две строки данных в таблицу test за один раз. Третий и четвертый операторы также дают одинаковый результат: значение по умолчанию столбца c2 используется для загрузки двух строк данных в таблицу test.

  1. Загрузка результата запроса в таблицу test
INSERT INTO test SELECT * FROM test2;
INSERT INTO test (c1, c2) SELECT * from test2;
  1. Загрузка результата запроса в таблицу test с указанием раздела и метки
INSERT INTO test PARTITION(p1, p2) WITH LABEL `label1` SELECT * FROM test2;
INSERT INTO test WITH LABEL `label1` (c1, c2) SELECT * from test2;

Ключевые слова​

INSERT

Рекомендации​

  1. Просмотр возвращаемых результатов

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

    1. Выполнение успешно, набор результатов пуст

      Если набор результатов оператора select, используемого в insert, пуст, возвращается следующий результат:

      mysql> insert into tbl1 select * from empty_tbl;
      Query OK, 0 rows affected (0.02 sec)

      Query OK указывает на успешное выполнение. 0 rows affected означает, что данные не были загружены.

    2. Выполнение успешно, набор результатов не пуст

      Если набор результатов не пуст, возможны следующие варианты возвращаемых результатов:

      1. Операция Insert выполнена успешно, данные видимы:

        mysql> insert into tbl1 select * from tbl2;
        Query OK, 4 rows affected (0.38 sec)
        {'label':'insert_8510c568-9eda-4173-9e36-6adc7d35291c', 'status':'visible', 'txnId':'4005'}

        mysql> insert into tbl1 with label my_label1 select * from tbl2;
        Query OK, 4 rows affected (0.38 sec)
        {'label':'my_label1', 'status':'visible', 'txnId':'4005'}

        mysql> insert into tbl1 select * from tbl2;
        Query OK, 2 rows affected, 2 warnings (0.31 sec)
        {'label':'insert_f0747f0e-7a35-46e2-affa-13a235f4020d', 'status':'visible', 'txnId':'4005'}

        mysql> insert into tbl1 select * from tbl2;
        Query OK, 2 rows affected, 2 warnings (0.31 sec)
        {'label':'insert_f0747f0e-7a35-46e2-affa-13a235f4020d', 'status':'committed', 'txnId':'4005'}

        Query OK указывает на успешное выполнение. 4 rows affected означает, что всего было загружено 4 строки данных. 2 warnings указывает количество отфильтровываемых строк.

        Также возвращается строка JSON:

        {'label':'my_label1', 'status':'visible', 'txnId':'4005'}
        {'label':'insert_f0747f0e-7a35-46e2-affa-13a235f4020d', 'status':'committed', 'txnId':'4005'}
        {'label':'my_label1', 'status':'visible', 'txnId':'4005', 'err':'some other error'}

        label представляет собой метку, заданную пользователем или сгенерированную автоматически. Метка служит идентификатором этой задачи загрузки Insert Into. Каждая задача загрузки имеет уникальную метку в пределах одной базы данных.

        status указывает, видимы ли загруженные данные. Если данные видимы, отображается visible, если нет, отображается committed.

        txnId представляет собой идентификатор транзакции загрузки, соответствующей этой операции insert.

        Поле err содержит сведения о других непредвиденных ошибках.

        Для просмотра отфильтрованных строк можно выполнить следующий оператор:

        show load where label="xxx";

        URL в возвращаемом результате позволяет просмотреть ошибочные данные. Подробнее см. в описании просмотра ошибочных строк ниже.

        Невидимость данных является временным состоянием: в конечном итоге эта порция данных станет видимой

        Проверить видимость этой порции данных можно с помощью следующего оператора:

        show transaction where id=4005;

        Если столбец TransactionStatus в возвращаемом результате имеет значение visible, данные видимы.

    3. Выполнение завершилось ошибкой

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

      mysql> insert into tbl1 select * from tbl2 where k1 = "a";
      ERROR 1064 (HY000): all partitions have no load data. url: http://10.74.167.16:8042/api/_load_error_log?file=__shard_2/error_log_insert_stmt_ba8bb9e158e4879-ae8de8507c0bf8a2_ba8bb9e158e4879_ae8de8507c0

      Здесь ERROR 1064 (HY000): all partitions have no load data указывает причину ошибки. Следующий за ним URL можно использовать для просмотра ошибочных данных:

      show load warnings on "url";

      Так можно просмотреть конкретную строку с ошибкой.

  2. Время ожидания

    Время ожидания операции INSERT определяется значением max(insert_timeout, query_timeout). Обе величины являются переменными окружения: insert_timeout по умолчанию составляет 4 часа, а query_timeout составляет 5 минут. Если операция превышает время ожидания, задача отменяется. Переменная insert_timeout введена для того, чтобы у операторов INSERT было большее время ожидания по умолчанию и задачи загрузки не зависели от более короткого времени ожидания, обычно применяемого к обычным запросам.

  3. Метки и атомарность

    Операция INSERT также гарантирует атомарность загрузки. См. документацию Транзакции загрузки и атомарность.

    При использовании CTE(Common Table Expressions) в качестве запроса в операции insert необходимо указать части WITH LABEL и column.

  4. Порог фильтрации

    В отличие от других способов загрузки, операции INSERT не позволяют задать порог фильтрации (max_filter_ratio). По умолчанию порог фильтрации равен 1, что означает, что строки с ошибками можно игнорировать.

    В бизнес-сценариях, где отфильтровывание данных недопустимо, можно установить переменную сеанса enable_insert_strict в true, чтобы INSERT не завершался успешно, если какие-либо данные были отфильтрованы.

  5. Вопросы производительности

    Не вставляйте по одной строке с помощью метода VALUES. Если необходимо использовать этот способ, объединяйте несколько строк данных в один оператор INSERT для пакетной фиксации.