MySql сложная проблема производительности соединения
Пожалуйста, рассмотрите следующий запрос
SELECT * FROM PC_SMS_OUTBOUND_MESSAGE AS OM
JOIN MM_TEXTOUT_SERVICE AS TOS ON TOS.TEXTOUT_SERVICE_ID = OM.SERVICE_ID
JOIN PC_SERVICE_NUMBER AS SN ON OM.TO_SERVICE_NUMBER_ID = SN.SERVICE_NUMBER_ID
JOIN PC_SUBSCRIBER AS SUB ON SUB.SERVICE_NUMBER_ID = SN.SERVICE_NUMBER_ID
JOIN MM_CONTACT CON ON CON.SUBSCRIBER_ID = SUB.SUBSCRIBER_ID
--AND CON.MM_CLIENT_ID = 1
AND OM.CLIENT_ID= 1
AND OM.CREATED>='2013-05-08 11:47:53' AND OM.CREATED<='2014-05-08 11:47:53'
ORDER BY OM.SMS_OUTBOUND_MESSAGE_ID DESC LIMIT 50
Чтобы получить набор данных, который мне требуется, мне нужно отфильтровать (закомментированные) CONTACTS client_id, а также OUTBOUND_MESSAGES client_id, но это то, что меняет производительность с миллисекунд до десятков минут.
План выполнения без "AND CON.MM_CLIENT_ID = 1":
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE OM index FK4E518EAA19F2EA2B,SERVICEID_IDX,CREATED_IDX,CLIENTID_IDX,CL_CR_ST_IDX,CL_CR_STYPE_ST_IDX,SID_TOSN_CL_CREATED_IDX PRIMARY 8 NULL 6741 3732.00 Using where
1 SIMPLE SUB ref PRIMARY,FKA1845E3459A7AEF FKA1845E3459A7AEF 9 mmlive.OM.TO_SERVICE_NUMBER_ID 1 100.00 Using where
1 SIMPLE SN eq_ref PRIMARY PRIMARY 8 mmlive.OM.TO_SERVICE_NUMBER_ID 1 100.00 Using where
1 SIMPLE CON ref FK2BEC061CA525D30,SUB_CL_IDX FK2BEC061CA525D30 8 mmlive.SUB.SUBSCRIBER_ID 1 100.00
1 SIMPLE TOS eq_ref PRIMARY,FKDB3DF298AB3EF4E2 PRIMARY 8 mmlive.OM.SERVICE_ID 1 100.00
План выполнения с "AND CON.MM_CLIENT_ID = 1":
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE CON ref FK2BEC061CA525D30,FK2BEC06134399E2A,SUB_CL_IDX FK2BEC06134399E2A 8 const 18306 100.00 Using temporary; Using filesort
1 SIMPLE SUB eq_ref PRIMARY,FKA1845E3459A7AEF PRIMARY 8 mmlive.CON.SUBSCRIBER_ID 1 100.00
1 SIMPLE OM ref FK4E518EAA19F2EA2B,SERVICEID_IDX,CREATED_IDX,CLIENTID_IDX,CL_CR_ST_IDX,CL_CR_STYPE_ST_IDX,SID_TOSN_CL_CREATED_IDX FK4E518EAA19F2EA2B 9 mmlive.SUB.SERVICE_NUMBER_ID 3 100.00 Using where
1 SIMPLE SN eq_ref PRIMARY PRIMARY 8 mmlive.SUB.SERVICE_NUMBER_ID 1 100.00 Using where
1 SIMPLE TOS eq_ref PRIMARY,FKDB3DF298AB3EF4E2 PRIMARY 8 mmlive.OM.SERVICE_ID 1 100.00
Любые предложения о том, как отформатировать вышеупомянутое, чтобы сделать его немного проще для глаз, были бы хорошими.
Поля ID являются первичными ключами. Есть индексы на всех соединяющихся столбцах.
2 ответа
Я разгадал загадку! В любом случае, так что я поделюсь.
Все это сводилось к изменению порядка соединения, как только я добавил это дополнительное предложение, которое вы четко видите в плане выполнения. При быстром запросе исходящие сообщения находятся вверху плана, но при медленном (после добавления предложения) таблица "Контакты" находится вверху. Я думаю, это означает, что индекс исходящих сообщений больше не может быть использован для сортировки, которая вызывает ужас;
"Using temporary; Using filesort"
Просто добавив ключевое слово STRAIGHT_JOIN непосредственно после выбора, я мог принудительно объединить план выполнения в порядке, указанном непосредственно в запросе. Рад, что кто-то, обладающий более глубокими знаниями в этой области, может противоречить любому из вышеперечисленного с точки зрения того, что на самом деле происходит, но это определенно работает.
Вы можете решить эту проблему, используя подзапрос:
JOIN (SELECT C.* FROM CONTACTS C WHERE C.USER_ID = 1) ON C.SUBSCRIBER_ID = SUB.ID
Это материализует совпадающие строки, что может оказать влияние на план запроса.
Если это не работает, отредактируйте ваш запрос и добавьте:
explain
планы на оба запроса.- Индексы доступны по таблице.
РЕДАКТИРОВАТЬ:
Можете ли вы попробовать создать составной индекс:
PC_SMS_OUTBOUND_MESSAGE(CLIENT_ID, CREATED, SERVICE_ID, TO_ SERVICE_ID, SMS_OUTBOUND_MESSAGE_ID);
Это может изменить оба плана запроса для запуска на OM
таблица с соответствующей фильтрацией, надеюсь, сделав результаты стабильными и хорошими.