Нужно настроить MySQL запрос - PullRequest
       10

Нужно настроить MySQL запрос

0 голосов
/ 27 декабря 2018

У меня есть запрос MySQL, выполнение которого занимает более 6 дней: около 250 миллионов записей в таблице активации и члене и около 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 для всех членов, которые уже присутствуют в таблице Activation_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;

Ответы [ 2 ]

0 голосов
/ 31 декабря 2018

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

 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';
0 голосов
/ 27 декабря 2018
  • Использовать многотабличный номер UPDATE JOIN без подзапроса (если возможно).
  • Пожалуйста, используйте синтаксис JOIN ... ON вместо старого синтаксиса "commajoin".
  • Вместо использования 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 строк за раз. В этом обсуждается, как это сделать эффективно.

...