Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/mysql/57.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
MySQL索引在一个;或;陈述_Mysql_Sql_Indexing - Fatal编程技术网

MySQL索引在一个;或;陈述

MySQL索引在一个;或;陈述,mysql,sql,indexing,Mysql,Sql,Indexing,我有3个表需要连接,这些表使用索引很好地连接在一起。但是,我们正在从使用一个遗留字段作为标识符过渡到另一个表中的另一个字段。 LEGACYID是遗留字段,而NEWID是新字段。两个字段都是varchars。 这两个字段都使用btree索引进行专门索引,两个表都是MyISAM SELECT Username FROM CUST C use index(primary,NEWID) JOIN TBLSHP S ON S.CUSID = C.CUSID JOIN TBLQ Q ON Q

我有3个表需要连接,这些表使用索引很好地连接在一起。但是,我们正在从使用一个遗留字段作为标识符过渡到另一个表中的另一个字段。 LEGACYID是遗留字段,而NEWID是新字段。两个字段都是varchars。 这两个字段都使用btree索引进行专门索引,两个表都是MyISAM

SELECT Username  
  FROM CUST C use index(primary,NEWID)
  JOIN TBLSHP S ON S.CUSID = C.CUSID
  JOIN TBLQ Q ON Q.SHPID = S.SHPID
 WHERE C.LEGACYID = '692041' 
    OR Q.NEWID = '692041'
这个查询需要5.147秒,比我预期的要长5秒

执行解释扩展查询时,NEWID的索引类型为ALL,即全表扫描,可能的键为(primary,NEWID)和键(null)。如果我从Or语句中删除LEGACYID,解释说现在将使用key(NEWID)。如果从或语句中删除NEWID,则会发生以下更改:

  • (S,C)的表联接类型从type ref更改为eq_ref
  • 按键长度从4变为5(两个)
  • 从空到“使用位置”的额外更改。 从语句中删除其中一条语句后,或查询以预期速度运行
表Q有183k条记录;C:115k;S:169k。 最后一点。如果移动查询位置:

   SELECT Username  
     FROM CUST C use index(primary,NEWID)
     JOIN TBLSHP  S ON S.CUSID = C.CUSID
LEFT JOIN TBLQ Q ON Q.SHPID = S.SHPID 
                AND Q.NEWID = '692041'
    WHERE C.LEGACYID = '692041' 
虽然它不是同一个查询,但对于数据的工作方式,它将提供我需要的结果,并且速度再次降低到0.1秒以下


我想澄清的是,我并不真的需要一个能够解决问题的查询。感谢下面的小马,它们已经提供了一个。我需要知道的是,是否有其他人遇到过这个问题,并且可以解释为什么会发生这种情况,以及我可以为这个简单的or语句做些什么来使用这两个索引。

如果您知道不会有重复项,请将
UNION
更改为
UNION ALL
UNION ALL
更快,因为它不会删除重复项)。否则,请使用:

SELECT Username  
  FROM CUST C use index(primary,NEWID)
  JOIN TBLSHP S ON S.CUSID = C.CUSID
  JOIN TBLQ Q ON Q.SHPID = S.SHPID
 WHERE C.LEGACYID = '692041' 
UNION
SELECT Username  
  FROM CUST C use index(primary,NEWID)
  JOIN TBLSHP S ON S.CUSID = C.CUSID
  JOIN TBLQ Q ON Q.SHPID = S.SHPID
 WHERE Q.NEWID = '692041'
是出了名的糟糕执行者,因为它会分裂执行路径。
UNION
减轻了这种分裂,并将两个结果集结合起来。也就是说,中的
s更可取,因为尽管逻辑上相同,但
中的
的执行通常更优化

UNION
并不总是答案 调查许多选项,在确定解决方案之前比较
解释计划
输出。我最近遇到了一些使用游标比使用深奥功能的单个查询性能更好的查询


另外,确保外键列(加入时在
ON
子句中使用的)已编制索引。MySQL已开始(v5.5+?)在执行外键约束时自动执行此操作,但这仅适用于InnoDB表。

这里没有提出任何问题。@Bueller:当OP显然在寻找性能更好的查询时,您可以快速投票关闭。你的阅读理解会因为正文中没有问号而受到如此大的影响吗@OMG小马:OP识别非工作查询,表明他们找到了一个查询,该查询提供了他们在预期和合理范围内查找的结果。问题是什么?@Bueller:我很高兴看到你没有必要的3K代表来投票,因为显然你需要更多的经验,我想你已经发现了MySQL的一个局限性:它实际上只支持在每个查询中查看每个表的一个索引。另外,从ref与eq_ref的比较中,我怀疑您的一个索引没有声明为唯一的。