据说mysql查询的时候使用limit1可以提高效率

zzzrrr1989 2017-01-03 11:26:39
如题:从网上好多人做的实验来看
SELECT * FROM t_user WHERE email=? LIMIT 1; 比
SELECT * FROM t_user WHERE id=?; 确实快了不少,解释的理由是limit 1找到一条记录后就不会向下扫描了,所以效率高。

然后我的疑惑是——按照mysql的语句执行顺序,limit是在where跟select之后执行的,是不是说执行完select之后才执行limit,那么在执行完select的时候,不是已经产生了满足email条件的全量的虚拟表了么,然后才从这个虚拟表里面取了一条记录出来,感觉这样并不会快啊~~

求各位大大开导开导,没想明白
...全文
4857 13 打赏 收藏 转发到动态 举报
写回复
用AI写文章
13 条回复
切换为时间正序
请发表友善的回复…
发表回复
rucypli 2017-01-04
  • 打赏
  • 举报
回复
我感觉limit和select结合使用的
LongRui888 2017-01-04
  • 打赏
  • 举报
回复
引用 10 楼 VertigozZ 的回复:
[quote=引用 9 楼 yupeigu 的回复:] [quote=引用 7 楼 VertigozZ 的回复:] [quote=引用 6 楼 yupeigu 的回复:] 然后我的疑惑是——按照mysql的语句执行顺序,limit是在where跟select之后执行的,是不是说执行完select之后才执行limit,那么在执行完select的时候,不是已经产生了满足email条件的全量的虚拟表了么,然后才从这个虚拟表里面取了一条记录出来,感觉这样并不会快啊~~ 是这样的的,用where条件过滤出符合条件的数据的同时,进行计数,比如limit 1,那么在where过滤出第1条数据后,他就会直接把结果select出来返回给你,整个过程就结束了。 并不会说,where过滤出所有结果,比如10万条数据之后,然后再返回第1条,这样效率没有提高,因为where过滤之后,数据就已经都在内存中了,在select出来只是一个返回数据的过程,从内存返回数据速度非常快,然后数据经过网络,最后发送到你的客户端。 limit之所以快,是因为这个过程中只要返回了1条数据后,就直接返回数据,结束查询,如果语句中有order by email,而email中有没有索引,那么结果就又不一样了,因为这个时候,要过滤出所有数据,然后把所有数据进行排序,排完序之后,在取出第1条。 当然啦,如果mysql排序用的是冒泡排序,在遍历数据1遍之后,就会返回第1条数据,这个时候,limit 1 order by email速度还是非常快,可惜的是mysql没有那么智能化,能根据实际情况,做出判断,是用快速排序,还是冒泡排序。。。
是不是可以理解为 理论上,where和limit 是一前一后执行的,但是实际执行过程中 where 和 limit 是同时进行的吧?[/quote] 应该不是同时进行的,因为这里有问题就是mysql在执行时一般来说是单线程的,所以应该是一个线程中有个循环处理过程,在这个一次循环中,他要过滤数据,同时看看现在有几条数据了,是不是已经达到了limit 1的要求了,如果达到了,就break跳出循环,继续下面的操作,包括select的操作,也就是从内存中把数据通过网络发送到客户端。[/quote] 十分同意版主的说法,我也感觉是取数据的时候是循环逐条是进行的,比如之前用变量进行循环统计的时候,就已经有了这样的感觉!但是还有一个小小的疑惑 就是为什么查看 EXPLAIN 为什么是type 是 ALL ?[/quote] 这个应该是由于mysql的explain本身没有加入limit的操作符,功能有待提高。。。我感觉mysql现在总体功能已经是很强的了,但是在易用性方面还有很大改善的空间,比如这里的explain还很不太完善,哪些个性能视图作用也不是很大,看个死锁还得去看innodb的引擎日志 等等。 如果你用其他的比如 sql server 里的top,那么就可以看到里面会有一个 top操作符。
zzzrrr1989 2017-01-04
  • 打赏
  • 举报
回复
引用 6 楼 yupeigu 的回复:
然后我的疑惑是——按照mysql的语句执行顺序,limit是在where跟select之后执行的,是不是说执行完select之后才执行limit,那么在执行完select的时候,不是已经产生了满足email条件的全量的虚拟表了么,然后才从这个虚拟表里面取了一条记录出来,感觉这样并不会快啊~~ 是这样的的,用where条件过滤出符合条件的数据的同时,进行计数,比如limit 1,那么在where过滤出第1条数据后,他就会直接把结果select出来返回给你,整个过程就结束了。 并不会说,where过滤出所有结果,比如10万条数据之后,然后再返回第1条,这样效率没有提高,因为where过滤之后,数据就已经都在内存中了,在select出来只是一个返回数据的过程,从内存返回数据速度非常快,然后数据经过网络,最后发送到你的客户端。 limit之所以快,是因为这个过程中只要返回了1条数据后,就直接返回数据,结束查询,如果语句中有order by email,而email中有没有索引,那么结果就又不一样了,因为这个时候,要过滤出所有数据,然后把所有数据进行排序,排完序之后,在取出第1条。 当然啦,如果mysql排序用的是冒泡排序,在遍历数据1遍之后,就会返回第1条数据,这个时候,limit 1 order by email速度还是非常快,可惜的是mysql没有那么智能化,能根据实际情况,做出判断,是用快速排序,还是冒泡排序。。。
----------------------------------------------------------------------------------------- 多谢~~
VertigozZ 2017-01-03
  • 打赏
  • 举报
回复
引用 9 楼 yupeigu 的回复:
[quote=引用 7 楼 VertigozZ 的回复:] [quote=引用 6 楼 yupeigu 的回复:] 然后我的疑惑是——按照mysql的语句执行顺序,limit是在where跟select之后执行的,是不是说执行完select之后才执行limit,那么在执行完select的时候,不是已经产生了满足email条件的全量的虚拟表了么,然后才从这个虚拟表里面取了一条记录出来,感觉这样并不会快啊~~ 是这样的的,用where条件过滤出符合条件的数据的同时,进行计数,比如limit 1,那么在where过滤出第1条数据后,他就会直接把结果select出来返回给你,整个过程就结束了。 并不会说,where过滤出所有结果,比如10万条数据之后,然后再返回第1条,这样效率没有提高,因为where过滤之后,数据就已经都在内存中了,在select出来只是一个返回数据的过程,从内存返回数据速度非常快,然后数据经过网络,最后发送到你的客户端。 limit之所以快,是因为这个过程中只要返回了1条数据后,就直接返回数据,结束查询,如果语句中有order by email,而email中有没有索引,那么结果就又不一样了,因为这个时候,要过滤出所有数据,然后把所有数据进行排序,排完序之后,在取出第1条。 当然啦,如果mysql排序用的是冒泡排序,在遍历数据1遍之后,就会返回第1条数据,这个时候,limit 1 order by email速度还是非常快,可惜的是mysql没有那么智能化,能根据实际情况,做出判断,是用快速排序,还是冒泡排序。。。
是不是可以理解为 理论上,where和limit 是一前一后执行的,但是实际执行过程中 where 和 limit 是同时进行的吧?[/quote] 应该不是同时进行的,因为这里有问题就是mysql在执行时一般来说是单线程的,所以应该是一个线程中有个循环处理过程,在这个一次循环中,他要过滤数据,同时看看现在有几条数据了,是不是已经达到了limit 1的要求了,如果达到了,就break跳出循环,继续下面的操作,包括select的操作,也就是从内存中把数据通过网络发送到客户端。[/quote] 十分同意版主的说法,我也感觉是取数据的时候是循环逐条是进行的,比如之前用变量进行循环统计的时候,就已经有了这样的感觉!但是还有一个小小的疑惑 就是为什么查看 EXPLAIN 为什么是type 是 ALL ?
LongRui888 2017-01-03
  • 打赏
  • 举报
回复
引用 7 楼 VertigozZ 的回复:
[quote=引用 6 楼 yupeigu 的回复:] 然后我的疑惑是——按照mysql的语句执行顺序,limit是在where跟select之后执行的,是不是说执行完select之后才执行limit,那么在执行完select的时候,不是已经产生了满足email条件的全量的虚拟表了么,然后才从这个虚拟表里面取了一条记录出来,感觉这样并不会快啊~~ 是这样的的,用where条件过滤出符合条件的数据的同时,进行计数,比如limit 1,那么在where过滤出第1条数据后,他就会直接把结果select出来返回给你,整个过程就结束了。 并不会说,where过滤出所有结果,比如10万条数据之后,然后再返回第1条,这样效率没有提高,因为where过滤之后,数据就已经都在内存中了,在select出来只是一个返回数据的过程,从内存返回数据速度非常快,然后数据经过网络,最后发送到你的客户端。 limit之所以快,是因为这个过程中只要返回了1条数据后,就直接返回数据,结束查询,如果语句中有order by email,而email中有没有索引,那么结果就又不一样了,因为这个时候,要过滤出所有数据,然后把所有数据进行排序,排完序之后,在取出第1条。 当然啦,如果mysql排序用的是冒泡排序,在遍历数据1遍之后,就会返回第1条数据,这个时候,limit 1 order by email速度还是非常快,可惜的是mysql没有那么智能化,能根据实际情况,做出判断,是用快速排序,还是冒泡排序。。。
是不是可以理解为 理论上,where和limit 是一前一后执行的,但是实际执行过程中 where 和 limit 是同时进行的吧?[/quote] 应该不是同时进行的,因为这里有问题就是mysql在执行时一般来说是单线程的,所以应该是一个线程中有个循环处理过程,在这个一次循环中,他要过滤数据,同时看看现在有几条数据了,是不是已经达到了limit 1的要求了,如果达到了,就break跳出循环,继续下面的操作,包括select的操作,也就是从内存中把数据通过网络发送到客户端。
LongRui888 2017-01-03
  • 打赏
  • 举报
回复
我觉得楼主这里可能有个误区,觉得整个执行sql的过程,是一步一步的,其实这个想法没错,确实是一步一步来完成的,但考虑到内存资源有限,并不是会把所有数据过滤出来后,在做下一步操作。 而是按照总体次序,先where,然后limit,但是这个过程并不说 mysql要做完所有的where之后,才会应用limit,而是做一步,判断一下,次序总是先where,后limit判断,这个次序是不变的。 同样的,先where后select,是做一步where,然后再select,所以,如果数据量大,你会发现数据都是一部分一部分出来的,不会一下子出来。
VertigozZ 2017-01-03
  • 打赏
  • 举报
回复
引用 6 楼 yupeigu 的回复:
然后我的疑惑是——按照mysql的语句执行顺序,limit是在where跟select之后执行的,是不是说执行完select之后才执行limit,那么在执行完select的时候,不是已经产生了满足email条件的全量的虚拟表了么,然后才从这个虚拟表里面取了一条记录出来,感觉这样并不会快啊~~ 是这样的的,用where条件过滤出符合条件的数据的同时,进行计数,比如limit 1,那么在where过滤出第1条数据后,他就会直接把结果select出来返回给你,整个过程就结束了。 并不会说,where过滤出所有结果,比如10万条数据之后,然后再返回第1条,这样效率没有提高,因为where过滤之后,数据就已经都在内存中了,在select出来只是一个返回数据的过程,从内存返回数据速度非常快,然后数据经过网络,最后发送到你的客户端。 limit之所以快,是因为这个过程中只要返回了1条数据后,就直接返回数据,结束查询,如果语句中有order by email,而email中有没有索引,那么结果就又不一样了,因为这个时候,要过滤出所有数据,然后把所有数据进行排序,排完序之后,在取出第1条。 当然啦,如果mysql排序用的是冒泡排序,在遍历数据1遍之后,就会返回第1条数据,这个时候,limit 1 order by email速度还是非常快,可惜的是mysql没有那么智能化,能根据实际情况,做出判断,是用快速排序,还是冒泡排序。。。
是不是可以理解为 理论上,where和limit 是一前一后执行的,但是实际执行过程中 where 和 limit 是同时进行的吧?
LongRui888 2017-01-03
  • 打赏
  • 举报
回复
然后我的疑惑是——按照mysql的语句执行顺序,limit是在where跟select之后执行的,是不是说执行完select之后才执行limit,那么在执行完select的时候,不是已经产生了满足email条件的全量的虚拟表了么,然后才从这个虚拟表里面取了一条记录出来,感觉这样并不会快啊~~ 是这样的的,用where条件过滤出符合条件的数据的同时,进行计数,比如limit 1,那么在where过滤出第1条数据后,他就会直接把结果select出来返回给你,整个过程就结束了。 并不会说,where过滤出所有结果,比如10万条数据之后,然后再返回第1条,这样效率没有提高,因为where过滤之后,数据就已经都在内存中了,在select出来只是一个返回数据的过程,从内存返回数据速度非常快,然后数据经过网络,最后发送到你的客户端。 limit之所以快,是因为这个过程中只要返回了1条数据后,就直接返回数据,结束查询,如果语句中有order by email,而email中有没有索引,那么结果就又不一样了,因为这个时候,要过滤出所有数据,然后把所有数据进行排序,排完序之后,在取出第1条。 当然啦,如果mysql排序用的是冒泡排序,在遍历数据1遍之后,就会返回第1条数据,这个时候,limit 1 order by email速度还是非常快,可惜的是mysql没有那么智能化,能根据实际情况,做出判断,是用快速排序,还是冒泡排序。。。
zzzrrr1989 2017-01-03
  • 打赏
  • 举报
回复
引用 4 楼 ACMAIN_CHM 的回复:
email不是索引 则找到第一条就停止继续扫描了。
--------------------------------------------- 可是不是说sql的执行顺序是where之后才是limit么? 如果说找到一条就停止扫描了,那说明在执行where的时候,mysql程序就已经知道limit 1的话只要找一条了。
ACMAIN_CHM 2017-01-03
  • 打赏
  • 举报
回复
email不是索引 则找到第一条就停止继续扫描了。
zzzrrr1989 2017-01-03
  • 打赏
  • 举报
回复
引用 1 楼 ACMAIN_CHM 的回复:
具体情况具体分析。 贴出 explain select ...进行分析比较。
------------------------------------------------------------------------- 没有explain select ...,只是我在看文章的时候想到的,就拿 SELECT * FROM t_user WHERE email='12345@qq.com' LIMIT 1; 与 SELECT * FROM t_user WHERE email='12345@qq.com';来说,如果email不是索引,为什么第一条比第二条快? 或者说你认为第一条并不一定比第二条快?
zzzrrr1989 2017-01-03
  • 打赏
  • 举报
回复
引用 楼主 zzzrrr1989 的回复:
如题:从网上好多人做的实验来看 SELECT * FROM t_user WHERE email=? LIMIT 1; 比 SELECT * FROM t_user WHERE id=?; 确实快了不少,解释的理由是limit 1找到一条记录后就不会向下扫描了,所以效率高。 然后我的疑惑是——按照mysql的语句执行顺序,limit是在where跟select之后执行的,是不是说执行完select之后才执行limit,那么在执行完select的时候,不是已经产生了满足email条件的全量的虚拟表了么,然后才从这个虚拟表里面取了一条记录出来,感觉这样并不会快啊~~ 求各位大大开导开导,没想明白
---------------------------------------------- 写错了,应该是SELECT * FROM t_user WHERE email=? LIMIT 1;与SELECT * FROM t_user WHERE email=?;
ACMAIN_CHM 2017-01-03
  • 打赏
  • 举报
回复
具体情况具体分析。 贴出 explain select ...进行分析比较。

56,679

社区成员

发帖
与我相关
我的任务
社区描述
MySQL相关内容讨论专区
社区管理员
  • MySQL
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧