У меня есть запрос 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;
@sloanthrasher это 100000. Крор 10м.
Помимо операторов SHOW CREATE TABLE для всех соответствующих таблиц, вопросы о производительности запросов всегда требуют EXPLAIN для данного запроса.
25 крор - это 250 миллионов, а 19 лаков - это 1,9 миллиона, а также я отредактировал свой вопрос, чтобы добавить операторы создания таблиц и объяснение запроса.
Я не вижу результатов EXPLAIN для запроса ...






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 - Ой. Я оставлю переписывание одного UPDATE на два, а разделение на OR в качестве упражнения для читателя. (И убедитесь, что у вас уже есть оптимальные индексы.)
Думаю, правильными обновлениями будут:
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';
SO - это не сервис написания кода. Мы здесь, чтобы помочь другим программистам, когда они застряли. Если вам нужна помощь, вам нужно будет предоставить соответствующую информацию. Не уверен, что такое измерение * лак *, но если у вас есть запрос, который занимает 6 дней, чтобы заполнить только две таблицы с 25 строками и 19 строками, у вас есть серьезные проблемы с оборудованием / ОС.