2014-05-13 72 views
0

请考虑下面的查询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 

为了得到我需要,我需要的过滤数据集(注释)联系CLIENT_ID还有OUTBOUND_MESSAGES CLIENT_ID但是这是什么样的变化性能从毫秒到数十分钟。

执行计划没有 “和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 

执行计划与“ 和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字段是主键。 所有连接列上都有索引。

+0

你似乎缺少一个'WHERE'子句和'OM'表。这是我们需要查看EXPLAIN结果和包含表中所有索引的情况之一。 –

+0

我不认为这里需要什么。并且当我测试时似乎没有它工作正常。了解EXPLAIN结果。将不得不推出真正的查询。 – dre

+0

被编辑以显示具有执行计划的真实查询。 – dre

回答

0

我解决了谜题!无论如何,我的情况,所以我会分享。

这一切都归结为连接顺序的变化,一旦我添加了额外的子句,您可以在执行计划中清楚地看到它。当查询速度很快时,出站消息位于计划的顶部,但速度较慢时(添加子句后),联系人表位于顶部。 我认为这意味着出站消息索引不能再用于导致可怕的排序;

"Using temporary; Using filesort" 

通过后直接选择,我可以强制执行计划通过查询直接表示的顺序进行连接简单地增加STRAIGHT_JOIN关键字。 对于这个领域的更深入的知识的任何人都乐意与上面的任何事情发生冲突,但实际上发生了什么,但它绝对奏效。

0

您可以通过使用一个子查询来解决这个问题:

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表具有适当的过滤,有望使结果稳定,好。

+0

曾尝试过,没有工作..我真的认为它会! :(我猜这是因为CONTACTS有数百万条记录,将会跟进更多的细节,说明将需要使用“真实世界”查询。 – dre

+0

@dre ...。你有'CONTACTS(USER_ID)'索引吗? –

+0

是的,我有那个索引 – dre