0

请考虑以下查询

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 字段是主键。所有连接列都有索引。

4

2 回答 2

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使用适当的过滤从表上开始,希望使结果稳定且良好。

于 2014-05-13T11:33:26.200 回答
0

我已经解开了这个谜!无论如何,对于我的情况,我会分享。

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

 "Using temporary; Using filesort"

通过在选择之后直接添加STRAIGHT_JOIN关键字,我可以强制执行计划按照查询直接表示的顺序加入。很高兴任何对该领域有更深入了解的人在实际发生的事情上与上述任何内容相矛盾,但它确实有效。

于 2014-05-14T16:28:36.117 回答