【问题标题】:MySql complicated join performance issueMySql 复杂的连接性能问题
【发布时间】:2014-05-13 11:30:44
【问题描述】:

请考虑以下查询

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

【问题讨论】:

  • 您似乎缺少WHERE 子句和OM 表。这是我们需要查看 EXPLAIN 结果和包含表上的所有索引的情况之一。
  • 我认为这里不需要。在我测试时,如果没有它,AND 似乎可以正常工作。了解 EXPLAIN 结果。将不得不为此推出真正的查询。
  • 已编辑以显示带有执行计划的真实查询。
  • MM_CONTACT 中有多少行?
  • 全部都是大写字母。嘘!尽管如此,我觉得这很困难,而且没有 DDL 真的很难!

标签: mysql query-performance composite-index


【解决方案1】:

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

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 表开始,希望结果稳定且良好。

【讨论】:

  • 试过了,没用..我真的认为它会! :( 我猜这是因为 CONTACTS 有数百万条记录。将跟进更多细节。解释将需要使用“真实世界”查询。
  • @dre 。 . .你有CONTACTS(USER_ID) 的索引吗?
  • 是的,我有那个索引。
  • 参考您在编辑中添加的复合索引,索引中列的排序背后有什么策略吗?
  • @dre 。 . .是的。第一列服从where 中的相等条件;第二个不等式,其余的用于连接(因此不需要原始数据页)。
【解决方案2】:

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

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

 "Using temporary; Using filesort"

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2023-04-10
    • 1970-01-01
    • 2011-12-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多