Возможно ли ускорить копирование данных между таблицами?

Рейтинг: 1Ответов: 1Опубликовано: 14.08.2023

Есть две таблицы А и B. A - 300 млн. и B - 30 млн записей. Нужно скопировать из таблицы A в B записи за день, ~100 тысяч.

Если использовать стандартный подход INSERT + SELECT данный запрос занимает несколько часов. Есть ли другие варианты выполнить данные действия, которые существенно увеличат скорость выполнения?

p.s. в доп. таблице C ~100к записей, запрос в условии возвращает ~50к.

Текущий запрос

INSERT INTO B
SELECT
       id,
       col1,
       col2,
       day,
       ...
FROM A
WHERE day = '2023-08-14' AND col1 IN (
       SELECT col1 FROM C WHERE col1 IS NOT NULL
);

Explain

id select_type table partitions type possible_keys key key_len ref rows filtered Extra
1 INSERT B null ALL null null null null null null null
1 SIMPLE C null range col_1 col_1 9 null 14604 100 Using where; Using index; Start temporary
1 SIMPLE A null ref ci1 ci1 40 const 146884 10 Using where; End temporary

Таблица А

create table A
(
    id    int unsigned auto_increment primary key,
    day   char(10)                       not null,
    col_1  varchar(32)                    null,
    col_2  varchar(48)                    null,
    col_3  varchar(48)                    null,
    col_4  varchar(128)                   null,
    col_5  varchar(48)      default ''    null,
    col_6  varchar(32)                    null,
    col_7  char(2)          default 'NA'  not null,
    col_8  varchar(256)                   not null,
    col_11 int unsigned                   not null,
    col_12 int unsigned     default '0'   not null,
    col_13 int unsigned     default '0'   not null,
    col_14 int unsigned     default '0'   not null,
    col_15 decimal(12, 3)   default 0.000 not null,
    col_16 decimal(12, 3)   default 0.000 not null,
    col_17 decimal(12, 3)   default 0.000 not null,
    col_18 decimal(12, 3)   default 0.000 not null,
    col_19 decimal(12, 3)   default 0.000 not null,
    col_20 tinyint unsigned default '50'  not null,
    col_21 tinyint unsigned default '0'   not null,
    col_9  tinyint unsigned default '1'   not null,
    col_22 tinyint unsigned default '0'   not null
)
    collate = utf8mb4_general_ci;

create index ci1
    on A (day, col_6, col_9);

Таблица B

create table B
(
    id    int unsigned           not null primary key,
    day   char(10)               not null,
    col_1  varchar(32)            null,
    col_2  varchar(48)            null,
    col_3  varchar(48)            null,
    col_4  varchar(128)           null,
    col_5  varchar(48) default '' null,
    col_6  varchar(32)            null,
    col_7  char(2)                not null,
    col_8  varchar(256)           not null,
    col_9  tinyint unsigned       not null,
    col_10 tinyint unsigned       null
)
    collate = utf8mb4_general_ci;

create index ci1
    on B (day, col_1, col_6, col_9);

create index col10
    on B (col_10);

create index day_col1
    on B (day, col_1);

Таблица С

create table C
(
    id    int unsigned auto_increment primary key,
    col_1 bigint unsigned null,
    constraint col_1
        unique (col_1)
)
    collate = utf8mb4_general_ci;

Ответы

▲ 0

А если вместо IN сделать JOIN?

INSERT INTO B
SELECT
       id,
       col1,
       col2,
       day,
       ...
FROM A INNER JOIN C ON A.col1=C.col1
WHERE day = '2023-08-14' AND col1 NOT NULL;

Не уверен, понадобится "AND col1 NOT NULL" или нет. Зависит от содержимого A.