mysql中的limit、between and、in

limit关键字
Limit子句可以被用于强制 SELECT 语句返回指定的记录数。Limit接受一个或两个数字参数。参数必须是一个整数常量。如果给定两个参数,第一个参数指定第一个返回记录行的偏移量,第二个参数指定返回记录行的最大数目。  

    //初始记录行的偏移量是 0(而不是 1):
  mysql> SELECT * FROM table LIMIT 5,10; //检索记录行6-15

  //为了检索从某一个偏移量到记录集的结束所有的记录行,可以指定第二个参数为 -1:
  mysql> SELECT * FROM table LIMIT 95,-1; // 检索记录行 96-last

  //如果只给定一个参数,它表示返回最大的记录行数目。换句话说,LIMIT n 等价于 LIMIT 0,n:
  mysql> SELECT * FROM table LIMIT 5;     //检索前 5 个记录行

Limit的效率高?

  常说的Limit的执行效率高,是对于一种特定条件下来说的:即数据库的数量很大,但是只需要查询一部分数据的情况。
  高效率的原理是:避免全表扫描,提高查询效率。
  

    比如:每个用户的email是唯一的,如果用户使用email作为用户名登陆的话,就需要查询出email对应的一条记录。
  SELECT * FROM t_user WHERE email=?;

  上面的语句实现了查询email对应的一条用户信息,但是由于email这一列没有加索引,会导致全表扫描,效率会很低。
  SELECT * FROM t_user WHERE email=? LIMIT 1;
  加上LIMIT 1,只要找到了对应的一条记录,就不会继续向下扫描了,效率会大大提高。

Limit的效率低?

  在一种情况下,使用limit效率低,那就是:只使用limit来查询语句,并且偏移量特别大的情况  

做以下实验:  

语句1:
     select * from table limit 150000,1000;
语句2:
     select * from table where id>=150000 limit 1000;
语句3:
     select * from table where id  between 1500000 and 1501000;


语句1为0.2077秒;语句2为0.0063秒;语句3:0.002s ,但是当表中ID出现断行情况的话,查询得到的结果集就会少于查询条数。

      比较以上的数据时,我们可以发现采用where...limit....性能基本稳定,受偏移量和行数的影响不大,而单纯采用limit的话,受偏移量的影响很大,当偏移量大到一定后性能开始大幅下降。不过在数据量不大的情况下,两者的区别不大。

  所以应当先使用where等查询语句,配合limit使用,效率才高

  ps:在sql语句中,limt关键字是最后才用到的。以下条件的出现顺序一般是:where->group by->having-order by->limit
附录:OFFSET

  为了与 PostgreSQL 兼容,MySQL 也支持句法: LIMIT # OFFSET #。
  经常用到在数据库中查询中间几条数据的需求
  比如下面的sql语句:  

① selete * from testtable limit 2,1;

② selete * from testtable limit 2 offset 1;


注意:
    1.数据库数据计算是从0开始的
    2.offset X是跳过X个数据,limit Y是选取Y个数据
    3.limit  X,Y  中X表示跳过X个数据,读取Y个数据
  这两个都是能完成需要,但是他们之间是有区别的:
    ①是从数据库中第三条开始查询,取一条数据,即第三条数据读取,一二条跳过
    ②是从数据库中的第二条数据开始查询两条数据,即第二条和第三条。

 MySQL BETWEEN 用法
BETWEEN 运算符用于 WHERE 表达式中,选取介于两个值之间的数据范围。BETWEEN 同 AND 一起搭配使用,语法如下:

WHERE column BETWEEN value1 AND value2
WHERE column NOT BETWEEN value1 AND value2
通常 value1 应该小于 value2。当 BETWEEN 前面加上 NOT 运算符时,表示与 BETWEEN 相反的意思,即选取这个范围之外的值。

BETWEEN 实例
选取 uid 在 2 到 5 之间的用户数据:

SELECT * FROM user WHERE uid BETWEEN 2 AND 5
返回查询结果如下:

除了数值类型外,BETWEEN 也支持字符串范围,如下选择出所有 username 介于 a 至 j 之间的用户(并包括单字母k/K):
SELECT * FROM user WHERE username BETWEEN 'a' AND 'k'
字符范围也支持汉字,但通常来说没什么意义。
MySQL BETWEEN 边界
虽然几乎所有的数据库都支持 BETWEEN ... AND 运算符,但不同的数据库对 BETWEEN ... AND 处理方式是有差异的。在 MySQL 中,BETWEEN 包含了 value1 和 value2 边界值,如上面选取 uid 在 2 到 5 之间的用户数据例子。
而有的数据库则不包含 value1 和 value2 边界值(类似于 > and <),也有数据库包含 value1 而不包含 value2(类似于 >= and <)。所以在使用 BETWEEN ... AND 的时候,请检查你的数据库是如何处理 BETWEEN 边界值的。
MySQL BETWEEN 时间日期
BETWEEN AND 常用于检索时间或日期段内的内容,下面是一些常见的 BETWEEN 时间日期例子:

// int 时间戳格式,查询 2008-08-08 20:00:00 到 2009-01-01 零点之前的数据
SELECT * FROM table WHERE column_time BETWEEN 1218196800 AND 1230739199
 
// DATE 格式,查询 2008-08-08 到 2009-01-01 零点之前的数据
SELECT * FROM table WHERE column_time BETWEEN '2008-08-08' AND '2009-01-01'
 
// DATETIME 格式,查询 2008-08-08 20:00:00 到 2009-01-01 零点之前的数据
SELECT * FROM table WHERE column_time BETWEEN '2008-08-08 20:00:00' AND '2008-12-31 23:59:59'

但对于查询到当前时间的数据,建议使用 >= 运算符:
// DATETIME 格式,查询 2008-08-08 20:00:00 到当前时刻的数据
SELECT * FROM table WHERE column_time >= '2008-08-08 20:00:00'


可见,同样的需求,不同的字段类型,写法可能就不一样。从效率上来讲,int 时间戳格式效率最优。
以上 BETWEEN 的各个例子,虽然都是 SELECT 查询,但 BETWEEN 也可以用于 UPDATE、DELETE 等适用 WHERE 表达式的 SQL 中。
MySQL BETWEEN 数据比较
BETWEEN 还具有数据比较功能,语法如下:

expr BETWEEN min AND max
当 expr 表达式的值大于或等于 min 且小于或等于 max 时, BETWEEN 的返回值为 1 ,否则返回 0 。利用这个功能,可以判断一个表达式或值否则在某个区间:

// 返回 0
SELECT 1 BETWEEN 2 AND 3
// 返回 1
SELECT 'b' BETWEEN 'a' AND 'c'
// 判断日期范围
SELECT 20080808 BETWEEN 20080101 AND 20090101

BETWEEN 与 <、<=、>=、> 等运算符在某些情况下有着类似的功能,但 BETWEEN 运算级别更高且效率上更甚一筹。当然由于 BETWEEN 存在边界值的问题而不够灵活,因此不同的情况,采用何种运算符,需要具体对待。

MySQL IN 用法
IN 运算符用于 WHERE 表达式中,以列表项的形式支持多个选择,语法如下:

WHERE column IN (value1,value2,...)
WHERE column NOT IN (value1,value2,...)
当 IN 前面加上 NOT 运算符时,表示与 IN 相反的意思,即不在这些列表项内选择。
IN 使用实例
选取 uid 为 2、3、5 的用户数据:

SELECT * FROM user WHERE uid IN (2,3,5)
返回查询结果如下:

IN 子查询
更多情况下,IN 列表项的值是不明确的,而可能是通过一个子查询得到的:
SELECT * FROM article WHERE uid IN(SELECT uid FROM user WHERE status=0)
在这个 SQL 例子里,我们实现了查出所有状态为 0 的用户(可能是被禁止)的所有文章。首先通过一个查询得到所有所有 status=0 的用户:

SELECT uid FROM user WHERE status=0
然后将查询结果作为 IN 的列表项以实现最终的查询结果,注意在子查询中返回的结果必须是一个字段列表项。

IN 运算符补充说明
IN 列表项不仅支持数字,也支持字符甚至时间日期类型等,并且可以将这些不同类型的数据项混合排列而无须跟 column 的类型保持一致:

SELECT * FROM user WHERE uid IN(1,2,'3','c')
一个 IN 只能对一个字段进行范围比对,如果要指定更多字段,可以使用 AND 或 OR 逻辑运算符:
SELECT * FROM user WHERE uid IN(1,2) OR username IN('admin','5idev')
使用 AND 或 OR 逻辑运算符后,IN 还可以和其他如 LIKE、>=、= 等运算符一起使用。
关于 IN 运算符的效率问题
如果 IN 的列表项是确定的,那么可以用多个 OR 来代替:

SELECT * FROM user WHERE uid IN (2,3,5)

// 等效为:
SELECT * FROM user WHERE (uid=2 OR uid =3 OR uid =5)

一般认为,如果是对索引字段进行操作,使用 OR 效率高于 IN,但对于列表项不确定的时候(如需要子查询得到结果),就必须使用 IN 运算符。另外,对于子查询表数据小于主查询的时候,也是适用 IN 运算符的。

BETWEEN 和in之间
在MySQL中经常会有朋友问关于大于小于,IN,OR,BETWEEN,哪个性能更好?

我想有很多朋友会用它们但确实不知道大于小于,IN,OR,BETWEEN性能哪个更好吧,下面总结一下关于大于小于,IN,OR,BETWEEN性能。

这里的查询条件有四种:>=和<=;between;or;in

这里id列是索引列,如果不是的话,三个查询都是全表扫描,性能差距应该不大。

in走全表是分情况的,上面的解答只是凭记忆大概说了一下,楼下小伙伴比较认真,这里就再解释一下,这个不是个数而应该是个比例,大概25%-35%左右,你要再问到底多少不好意思水平有限不读源码没办法确认。然后这个30左右的比例也并不是说一定走全表扫描,因为mysql还有一个索引扫描,就是说如果select的内容在你的索引里面就能找到的话当然不会去扫全表了,比如下面的例子中select id from ttt where id in (..);和select * from ttt where id in (...);前面这个肯定是走主键扫描(覆盖索引),即使你in了所有id值他也是走主键,而后面的情况就是这种百分比的情况了,具体看下面示例,欢迎指正^_^
额,然后还想说一下between的情况,为什么好是因为除了索引段上连续存取减少解析以外,还有一个情况就是在磁盘寻址检索数据的时候,会默认读取第一次取值附近的部分数据(有这么一个概率算法说的是当一个数据被检索到的时候,他附近的数据也很大概率会被用到)所以就有了这么一个一次性取出冗余数据避免多次寻址的情况,这时候使用between的连续取值就正适用了

https://segmentfault.com/q/1010000009092938

参考https://blog.csdn.net/u011781769/article/details/48471013https://www.jb51.net/article/76517.htm


原文:https://blog.csdn.net/weixin_39666581/article/details/82779436 
 

猜你喜欢

转载自blog.csdn.net/HXNLYW/article/details/85112706