像整数运算符一样的mysql给了我比=运算符更好的结果

时间:2016-12-01 17:30:58

标签: mysql

这是tblNewsToCity上的索引:

enter image description here

我有这个问题:

SELECT * 
FROM   `tblnews` 
       INNER JOIN `tblnewstocity` 
               ON `tblnews`.`id` = `tblnewstocity`.`fkid` 
WHERE  `tblnewstocity`.`city` = '233' 
       AND `tblnews`.`id` != '1771' 
ORDER  BY `tblnews`.`id` DESC 
LIMIT  3 offset 0 

运行缓慢enter image description here

但如果我要将tblnewstocitycity = 233更改为:tblnewstocitycity like 233

我得到了这个好结果: enter image description here

很想明白为什么?我错过了什么?为什么第一个查询不能正常运行,当第二个在整数上使用like运算符时它应该更慢

2 个答案:

答案 0 :(得分:1)

不确定LIKE问题,但您应该在JOIN

中加入过滤器
SELECT * 
FROM   `tblnews` 
INNER JOIN `tblnewstocity` 
   ON `tblnews`.`id` = `tblnewstocity`.`fkid` 
  AND `tblnews`.`id` != '1771' 
  AND `tblnewstocity`.`city` = '233'      
ORDER  BY `tblnews`.`id` DESC 
LIMIT  3 offset 0 

答案 1 :(得分:1)

MySQL有几个选项来执行该查询:

  • 使用索引查找tblnewstocity.city = '233'的所有行,按ID进行连接和排序。它必须检查索引给出的所有行,因为前3个不必具有最大的tblnews.id

  • tblnews - 顺序(从结尾处)查看order by,进行连接,然后查找恰好具有正确city的第1行3行-值。它可以在找到3行后停止,因为不能有更大的tblnews.id

这取决于您的数据哪种方式更快。如果您有例如只有2行适合你的index - 条件(和连接),第一行会更快,因为它只需要检查少数行,而第二个查询则必须检查整个表以实现只有2个。例如所有行都有city = 233,第一个查询必须找到所有行(通过索引,但它仍然是全部),排序它们并取前3个,而第二个查询只需要测试前3个行,因为已经订购。

现实分布将介于这些可能性之间。 MySQL必须猜测。它猜测索引(对于=)只会给你一些行数,所以选择了1. like会让MySQL更少信任索引,所以它更喜欢第二个选项,幸运的是,这是更快的一个。但它也可能已经走了另一条道路,例如尝试like=的值没有城市(好吧,根据你的mysql服务器版本,优化器可能会检查它并且可能不会这样做,所以也许可以用一个只测试它的值来测试它给出一堆没有限制的行。

长话短说:有两个解决方案:

  • INNER JOIN tblnewstocity替换为straight_join tblnewstocity,这将迫使mysql采取第二种方式(但当然有可能在计数器示例中执行速度慢)
  • 或添加适当的索引:tblnewstocity (city, fkid)应该解决问题。您可能需要将ORDER BY tblnews.id DESC更改为ORDER BY tblnewstocity.fkid DESC,这相当于tblnewstocity.fkid = tblnews.id根据join条件,而mysql应该自行实现,但您永远不会知道...