Необходимо настроить запрос mysql

У меня есть запрос MySQL, для выполнения которого требуется более 6 дней, около 250 миллионов записей в таблице Activ_member и около 1,9 миллиона записей в таблице temp_message_split. Нужна помощь в настройке этого запроса:

UPDATE TEMP_MESSAGE_SPLIT A,
                            (SELECT

                                            ACTIVATION_MEMBER_KEY,
                                            dh_member_id,
                                            alt_id,
                                            drsn
                            FROM ACTIVATION_MEMBER AM )  B  
                            SET A.ACTIVATION_MEMBER_KEY = B.ACTIVATION_MEMBER_KEY, A.STATUS = 'U'
                            WHERE  A.DH_MEMBER_ID = B.DH_MEMBER_ID OR ( (A.ALT_ID = b.alt_id) AND (A.DRSN = b.drsn)) ;

Запрос на обновление предназначен для обновления TEMP_MESSAGE_SPLIT.STATUS = 'U' в таблице TEMP_MESSAGE_SPLIT для всех элементов, которые уже присутствуют в таблице Activ_member. Нам нужно оптимизировать этот запрос, чтобы он занимал минимум мин. максимально возможное время для исполнения.

Операторы создания таблицы:

  CREATE TABLE
activation_member
(
    ACTIVATION_MEMBER_KEY bigint NOT NULL AUTO_INCREMENT,
    PORTAL_STATEMENT_LOC_KEY bigint,
    FIRST_NAME VARCHAR(20),
    LAST_NAME VARCHAR(30),
    DOB DATE,
    EMPLOYEE_ID VARCHAR(20),
    CES_CUST_NUM VARCHAR(7),
    MED_POLICY_NUM VARCHAR(20),
    EMAIL_ADDR VARCHAR(50),
    DH_MEMBER_ID VARCHAR(9),
    ALT_ID VARCHAR(20),
    DRSN VARCHAR(2),
    SSN VARCHAR(9),
    EPIPHANY_MEMBER_ID bigint,
    SYSTEM_HIS_CNT mediumint,
    SYSTEM_USER VARCHAR(30),
    SYSTEM_TIMESTAMP DATETIME,
    PRIMARY KEY (ACTIVATION_MEMBER_KEY),
    CONSTRAINT ACTIVATION_MEMBER_FK1 FOREIGN KEY (PORTAL_STATEMENT_LOC_KEY) REFERENCES
    `portal_statement_loc` (`PORTAL_STATEMENT_LOC_KEY`),
    INDEX ACTIVATION_MEMBER_IDX1 (PORTAL_STATEMENT_LOC_KEY),
    INDEX ACTIVATION_MEMBER_IDX2 (DH_MEMBER_ID),
    INDEX ACTIVATION_MEMBER_IDX3 (EMPLOYEE_ID, FIRST_NAME, MED_POLICY_NUM, DOB),
    INDEX ACTIVATION_MEMBER_IDX4 (EPIPHANY_MEMBER_ID),
    INDEX ACTIVATION_MEMBER_IDX5 (ALT_ID, DRSN)
)
ENGINE=InnoDB DEFAULT CHARSET=utf8;

CREATE TABLE
portal_statement_loc
(
    PORTAL_STATEMENT_LOC_KEY bigint NOT NULL AUTO_INCREMENT,
    PORTAL_ADDRESS VARCHAR(200),
    STATEMENT_VENDOR VARCHAR(100),
    SYSTEM_HIS_CNT mediumint,
    SYSTEM_USER VARCHAR(30),
    SYSTEM_TIMESTAMP DATETIME,
    PRIMARY KEY (PORTAL_STATEMENT_LOC_KEY)
)
ENGINE=InnoDB DEFAULT CHARSET=utf8;

CREATE TABLE
temp_message_split
(
    FIRST_NAME VARCHAR(20),
    LAST_NAME VARCHAR(30),
    DOB VARCHAR(10),
    EMPLOYEE_ID VARCHAR(20),
    CES_CUST_NUM VARCHAR(7),
    MED_POLICY_NUM VARCHAR(20),
    EMAIL_ADDR VARCHAR(50),
    DH_MEMBER_ID VARCHAR(9),
    ALT_ID VARCHAR(20),
    DRSN VARCHAR(2),
    SSN VARCHAR(9),
    EPIPHANY_MEMBER_ID VARCHAR(18),
    PORTAL_ADDRESS VARCHAR(30),
    STATEMENT_VENDOR VARCHAR(20),
    CONTENT_KEY VARCHAR(18),
    EPIPHANY_COMMUNICATION_ID VARCHAR(200),
    PRIORITY VARCHAR(4),
    DAYS_UNTIL_EXPIRED VARCHAR(4),
    CONTENT_DTL_KEY VARCHAR(18),
    STATUS VARCHAR(1),
    ACTIVATION_MEMBER_KEY bigint,
    MESSAGE_BOARD_KEY bigint,
    PORTAL_STATEMENT_LOC_KEY bigint,
    temp_message_split_KEY bigint NOT NULL AUTO_INCREMENT,
    PRIMARY KEY (temp_message_split_KEY),
    INDEX EPIPHANY_COMMUNICATION_ID_IDX (EPIPHANY_COMMUNICATION_ID),
    INDEX TEMP_MESSAGE_SPLIT_IDX1 (DH_MEMBER_ID),
    INDEX TEMP_MESSAGE_SPLIT_IDX2 (ALT_ID),
    INDEX TEMP_MESSAGE_SPLIT_IDX3 (DRSN)
)
ENGINE=InnoDB DEFAULT CHARSET=utf8;

SO - это не сервис написания кода. Мы здесь, чтобы помочь другим программистам, когда они застряли. Если вам нужна помощь, вам нужно будет предоставить соответствующую информацию. Не уверен, что такое измерение * лак *, но если у вас есть запрос, который занимает 6 дней, чтобы заполнить только две таблицы с 25 строками и 19 строками, у вас есть серьезные проблемы с оборудованием / ОС.

Sloan Thrasher 27.12.2018 09:49

@sloanthrasher это 100000. Крор 10м.

Strawberry 27.12.2018 10:31

Помимо операторов SHOW CREATE TABLE для всех соответствующих таблиц, вопросы о производительности запросов всегда требуют EXPLAIN для данного запроса.

Strawberry 27.12.2018 10:33

25 крор - это 250 миллионов, а 19 лаков - это 1,9 миллиона, а также я отредактировал свой вопрос, чтобы добавить операторы создания таблиц и объяснение запроса.

Parul 27.12.2018 12:39

Я не вижу результатов EXPLAIN для запроса ...

Sloan Thrasher 28.12.2018 04:44
Освоение архитектуры микросервисов с Laravel: Лучшие практики, преимущества и советы для разработчиков
Освоение архитектуры микросервисов с Laravel: Лучшие практики, преимущества и советы для разработчиков
В последние годы архитектура микросервисов приобрела популярность как способ построения масштабируемых и гибких приложений. Laravel , популярный PHP...
Как построить CRUD-приложение в Laravel
Как построить CRUD-приложение в Laravel
Laravel - это популярный PHP-фреймворк, который позволяет быстро и легко создавать веб-приложения. Одной из наиболее распространенных задач в...
Освоение PHP и управление базами данных: Создание собственной СУБД - часть II
Освоение PHP и управление базами данных: Создание собственной СУБД - часть II
В предыдущем посте мы создали функциональность вставки и чтения для нашей динамической СУБД. В этом посте мы собираемся реализовать функции обновления...
Документирование API с помощью Swagger на Springboot
Документирование API с помощью Swagger на Springboot
В предыдущей статье мы уже узнали, как создать Rest API с помощью Springboot и MySql .
Роли и разрешения пользователей без пакета Laravel 9
Роли и разрешения пользователей без пакета Laravel 9
Этот пост изначально был опубликован на techsolutionstuff.com .
Как установить LAMP Stack - Security 5/5 на виртуальную машину Azure Linux VM
Как установить LAMP Stack - Security 5/5 на виртуальную машину Azure Linux VM
В предыдущей статье мы завершили установку базы данных, для тех, кто не знает.
2
5
39
2

Ответы 2

  • Используйте многотабличный UPDATEJOIN без подзапроса (если возможно).
  • Пожалуйста, используйте синтаксис JOIN ... ON вместо старого синтаксиса «соединение запятой».
  • Вместо использования OR сделайте два UPDATEs. Если мы можем разработать адекватные индексы для запроса, тогда каждое обновление будет выполняться намного быстрее.

Это мог бы - правильный синтаксис:

UPDATE  TEMP_MESSAGE_SPLIT A
    JOIN  ACTIVATION_MEMBER AM  ON A.DH_MEMBER_ID = B.DH_MEMBER_ID
                              AND  A.ALT_ID = b.alt_id
    SET A.ACTIVATION_MEMBER_KEY = B.ACTIVATION_MEMBER_KEY,
        A.STATUS = 'U';

UPDATE  TEMP_MESSAGE_SPLIT A
    JOIN  ACTIVATION_MEMBER AM  ON A.DH_MEMBER_ID = B.DH_MEMBER_ID
                              AND  A.DRSN = b.drsn
    SET A.ACTIVATION_MEMBER_KEY = B.ACTIVATION_MEMBER_KEY,
        A.STATUS = 'U';

и это для одной из таблиц (или добавьте к обеим таблицам, так как я не знаю, будет ли предпочтительна одна таблица):

INDEX(dh_member_id, alt_id)  -- in either order
INDEX(dh_member_id, dsrn)    -- in either order

Обработка должна будет полностью сканировать одну таблицу, а затем достигать («соединение вложенного цикла») в другую.

UPDATE (или DELETE) с большим количеством строк может занять много времени из-за сохранения строк для отмены в случае сбоя или ROLLBACK. Одна вещь, которую следует рассмотреть, - это сделать UPDATEs кусками, скажем, по 1000 строк за раз. Этот обсуждает, как это сделать эффективно.

но как это служит цели «или». В моем запросе WHERE A.DH_MEMBER_ID = B.DH_MEMBER_ID OR ((A.ALT_ID = b.alt_id) AND (A.DRSN = b.drsn)) мой запрос означает, что либо DH_MEMBER_ID равны в обеих таблицах, либо (ALT_ID и drsn ) вместе в обеих таблицах равны.

Parul 28.12.2018 08:14

@Parul - Ой. Я оставлю переписывание одного UPDATE на два, а разделение на OR в качестве упражнения для читателя. (И убедитесь, что у вас уже есть оптимальные индексы.)

Rick James 28.12.2018 18:02

Думаю, правильными обновлениями будут:

 UPDATE  TEMP_MESSAGE_SPLIT A
JOIN  ACTIVATION_MEMBER B  ON A.DH_MEMBER_ID = B.DH_MEMBER_ID
SET A.ACTIVATION_MEMBER_KEY = B.ACTIVATION_MEMBER_KEY,
    A.STATUS = 'U';

   UPDATE  TEMP_MESSAGE_SPLIT A
JOIN  ACTIVATION_MEMBER B  ON A.ALT_ID = B.ALT_ID AND A.DRSN = B.DRSN
SET A.ACTIVATION_MEMBER_KEY = B.ACTIVATION_MEMBER_KEY,
    A.STATUS = 'U';

Другие вопросы по теме