mysql 分页查询方式_mysql-分页查询方案

一.直接使用limit最简单查询方法:

select * from content order by id desc limit 0, 10

在中小数据量的情况下,这样的SQL足够用了,唯一需要注意的问题就是确保使用了索引。

随着数据量的增加,页数会越来越多,查看后几页的SQL就可能类似:

select * from content order by id desc limit 10000, 10

言以蔽之,就是越往后分页,LIMIT语句的偏移量就会越大,速度也会明显变慢。

此时,通过2中方式:

二.子查询分页方式来提高效率

SELECT * FROM `content` WHERE id <=(SELECT id FROM `content` ORDER BY id desc LIMIT ".($page-1)*$pagesize.", 1) ORDER BY id desc LIMIT $pagesize

SELECT * FROM `log_data` WHERE id <=(SELECT id FROM `log_data` ORDER BY id desc LIMIT 5, 1) ORDER BY id desc LIMIT 5

为什么会这样呢?因为子查询是在索引上完成的,而普通的查询时在数据文件上完成的,通常来说,索引文件要比数据文件小得多,所以操作起来也会更有效率。

(via)通过explain SQL语句发现:子查询使用了索引

id select_type table type possible_keys keykey_len ref rows Extra1 PRIMARY content range PRIMARY PRIMARY 4 NULL 6264 Using where

2 SUBQUERY content index NULL PRIMARY 4 NULL 27085 Using index

三.JOIN分页方式

SELECT * FROM `content` ASt1JOIN (SELECT id FROM `content` ORDER BY id desc LIMIT ".($page-1)*$pagesize.", 1) ASt2WHERE t1.id <= t2.id ORDER BY t1.id desc LIMIT $pagesize;

SELECT * FROM `log_data` ASt1JOIN (SELECT id FROM `log_data` ORDER BY id desc LIMIT 5, 1) ASt2WHERE t1.id <= t2.id ORDER BY t1.id desc LIMIT 5;

经过测试,join分页和子查询分页的效率基本在一个等级上,消耗的时间也基本一致。explain SQL语句:

id select_type table type possible_keys keykey_len ref rows Extra1 PRIMARY system NULL NULL NULL NULL 1

1 PRIMARY t1 range PRIMARY PRIMARY 4 NULL 6264 Using where

2 DERIVED content index NULL PRIMARY 4 NULL 27085 Using index

四.使用mysql的found_rows()函数查询

Mysql FOUND_ROWS() 函数结合SQL_CALC_FOUND_ROWS在SELECT中可以得到两个结果:

1. 得到Limit的内容2. 得到去除Limit以后所有行数

SELECT语句中经常可能用LIMIT限制返回行数。有时候可能想要知道如果没有LIMIT会返回多少行,但又不想再执行一次相同语句。那么,在SELECT查询中包含SQL_CALC_FOUND_ROWS选项,然后执行FOUND_ROWS()就可以了:

select SQL_CALC_FOUND_ROWS * FROM tbl_name WHERE id > 100 LIMIT 10;SELECT FOUND_ROWS();

其中SQL_CALC_FOUND_ROWS 告诉Mysql将sql所处理的行数记录下来,FOUND_ROWS() 则取到了这个纪录。 虽然也是两个语句,但是只执行了一次主查询,所以效率比原来要高很多。

1. 如果在前一条语句中使用SQL_CALC_FOUND_ROWS选项,FOUND_ROWS()将返回第一条语句没有LIMIT时返回的行数。2. 如果在前一条语句中没有使用SQL_CALC_FOUND_ROWS选项,FOUND_ROWS()将返回前一条语句实际返回的行数。

如果使用 SELECT SQL_CALC_FOUND_ROWS,MySQL必须计算所有结果集的行数。尽管这样,总比再执行一次不使用LIMIT的查询要快多了吧,因为那样结果集要返回客户端滴。(另外:应该不单是没有将结果集返回的原因,还有原因可能是比如LIKE之类比较费劲的SQL不需要再去劳累一次。)

--注意下面语句中的条件 LIKE

SELECT SQL_CALC_FOUND_ROWS * FROM tbl_name WHERE Name LIKE '%string%' id > 100 LIMIT 10;SELECT FOUND_ROWS();

--上面语句等价于下面语句,但性能方面应该提升非常非常的明显:

SELECT COUNT(*) FROM tbl_name WHERE Name LIKE '%string%';SELECT * FROM tbl_name WHERE Name LIKE '%string%' id > 100 LIMIT 10;

五.使用存储过程

DELIMITER $$;DROP PROCEDURE IF EXISTS`sp_page`$$CREATE PROCEDURE`sp_page`(in _pagecurrent int,/*当前页*/

in _pagesize int,/*每页的记录数*/

in _ifelse varchar(1000),/*显示字段*/

in _where varchar(1000),/*条件*/

in _order varchar(1000)/*排序*/)

COMMENT'分页存储过程'

BEGIN

if _pagesize<=1 then

set _pagesize=20;end if;if _pagecurrent < 1 then

set _pagecurrent = 1;end if;set @strsql = concat('select',_ifelse,'from',_where,' ',_order,'limit',_pagecurrent*_pagesize-_pagesize,',',_pagesize);prepare stmtsql from @strsql;executestmtsql;deallocate preparestmtsql;set @strsqlcount=concat('select count(1) as count from',_where);/*count(1) 这个字段最好是主键*/

prepare stmtsqlcount from @strsqlcount;executestmtsqlcount;deallocate preparestmtsqlcount;END$$

DELIMITER ;$$

调用代码

调用例1 call sp_Page(1,3,'*','test','order by id desc');

调用例2 call sp_Page(1,3,'*','test where sort=1','order by id desc');

调用例3 call sp_Page(1,3,'id,title','test where sort=1','order by id desc');

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值