php超大树形分页,PHP+MySql千万级数据limit分页优化方案
PHP+MySql千万级数据limit分页优化方案
1年前
阅读 2750
评论 0
喜欢 0
### 原因
徒弟突然有个需求,就是他发现limit分页,页数越大之后,mysql的消耗越大,查询时间越长,当突破百万级数据之后,一个简单的翻页都需要5-6秒,极其不方便。
### 测试数据库结构
```
CREATE TABLE IF NOT EXISTS `video_info` (
`id` int(10) unsigned NOT NULL COMMENT '自增ID',
`channel_id` varchar(30) DEFAULT NULL COMMENT '频道ID',
) ENGINE=InnoDB AUTO_INCREMENT=4565068 DEFAULT CHARSET=utf8mb4;
ALTER TABLE `video_info`
ADD PRIMARY KEY (`id`),
ADD KEY `channel_id` (`channel_id`);
ALTER TABLE `video_info`
MODIFY `id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增ID',AUTO_INCREMENT=1;
```
上面数据库随机生成700W数据,进行效率测试。
### ThinkPHP5.1的分页代码:
```php
namespace app\index\controller;
use think\Controller;
class Index extends Controller
{
public function index() {
$page = !empty($_GET['page']) ? $_GET['page'] : 1;
$limit = !empty($_GET['limit']) ? $_GET['limit'] : 10;
$where = [];
$param = '?';
if (!empty($_GET['keys'])) {
$where[] = ['channel_id', 'like', '%'.$_GET['keys'].'%'];
$param .= 'keys='.$_GET['keys'];
}
$total = \think\Db::name('video_info')->where($where)->count();
// 取最后一条记录做翻页条件
$sql = \think\Db::name('video_info')->where($where)->limit((($page-1)*$limit), 1)->field('id')->buildSql();
$list = \think\Db::name('video_info')->where($where)->where('id >= '.$sql.'')->limit($limit)->field('id, channel_id')->select();
$this->assign('page', $page);
$this->assign('limit', $limit);
$this->assign('param', $param);
$this->assign('total', $total);
$this->assign('list', $list);
// 渲染模板输出
return $this->fetch();
}
}
```
### 原生PHP的分页代码:
```php
//程序运行时间
$starttime = explode(' ',microtime());
# 设置html页面为UTF-8编码
header("Content-type:text/html;charset=utf-8");
# 使用MySqli连接数据库
$DB = mysqli_connect('127.0.0.1', 'localhost_db', 'localhost_db', 'localhost_db', 3306);
# 设置数据库为UTF-8编码
mysqli_query($DB, 'set names utf8');
$page = !empty($_GET['page']) ? $_GET['page'] : 1;
$limit = !empty($_GET['limit']) ? $_GET['limit'] : 10;
$where = ' 1=1';
$param = '?';
if (!empty($_GET['keys'])) {
$where .= ' AND channel_id like "%'.$_GET['keys'].'%"';
$param .= 'keys='.$_GET['keys'];
}
$sql = 'SELECT COUNT(*) AS count FROM video_info where'.$where;
# 使用mysqli_query()执行SQL语句
$res = mysqli_query($DB, $sql);
# 判断是否执行成功
if ($res == false) {
echo '查询失败'; exit;
}
$array= mysqli_fetch_array($res);
$total = $array['count'];
$sql = ' SELECT `id`,`channel_id` FROM `video_info` WHERE '.$where.' AND ( id >= ( SELECT `id` FROM `video_info` WHERE '.$where.' LIMIT '.(($page-1)*$limit).', 1 ) ) LIMIT '.$limit;
$res = mysqli_query($DB, $sql);
# 判断是否执行成功
if ($res == false) {
echo '查询失败'; exit;
}
$list= mysqli_fetch_all($res, MYSQLI_ASSOC);
//程序运行时间
$endtime = explode(' ',microtime());
$thistime = $endtime[0]+$endtime[1]-($starttime[0]+$starttime[1]);
$thistime = round($thistime,7);
$title = "本网页执行耗时:".$thistime." 秒";
?>
test page
搜索
ID | 渠道ID |
<?php echo $v['id'];?> | <?php echo $v['channel_id'];?> |
function getParameter(name) {
var reg = new RegExp("(^|&)"+ name +"=([^&]*)(&|$)");
var r = window.location.search.substr(1).match(reg);
if (r!=null) return unescape(r[2]); return null;
}
//init
$(function(){
var totalPage = <?php echo $total/$limit;?>;
var totalRecords = <?php echo $total;?>;
var pageNo = getParameter('page');
if(!pageNo){
pageNo = 1;
}
//生成分页
//有些参数是可选的,比如lang,若不传有默认值
kkpager.generPageHtml({
pno : pageNo,
//总页码
total : totalPage,
//总数据条数
totalRecords : totalRecords,
//链接前部
hrefFormer : '/2/index.php',
//链接尾部
hrefLatter : '',
getLink : function(n){
return this.hrefFormer + this.hrefLatter +'<?php echo $param;?>'+"&page="+n;
}
/*
,lang: {
firstPageText: '首页',
firstPageTipText: '首页',
lastPageText: '尾页',
lastPageTipText: '尾页',
prePageText: '上一页',
prePageTipText: '上一页',
nextPageText: '下一页',
nextPageTipText: '下一页',
totalPageBeforeText: '共',
totalPageAfterText: '页',
currPageBeforeText: '当前第',
currPageAfterText: '页',
totalInfoSplitStr: '/',
totalRecordsBeforeText: '共',
totalRecordsAfterText: '条数据',
gopageBeforeText: ' 转到',
gopageButtonOkText: '确定',
gopageAfterText: '页',
buttonTipBeforeText: '第',
buttonTipAfterText: '页'
}*/
//,
//mode : 'click',//默认值是link,可选link或者click
//click : function(n){
//this.selectPage(n);
// return false;
//}
});
});
```
### 最终效果
在没优化之前,正常的limit翻页到4.5W页,最后一页时,需要耗时22秒左右,优化之后则只需要花费1.5秒,提高了17倍左右的查询速度。
### 原理和缺点:
原理很简单,就是使用子查询获得max(id),然后进行当前分页。
缺点也很明显,那就是分页的关键参数,id值只能为自增主键,否则这个方案用不了。
© 著作权归作者所有
php超大树形分页,PHP+MySql千万级数据limit分页优化方案相关推荐
- MYSQL百万级数据,如何优化
MYSQL百万级数据,如何优化 首先,数据量大的时候,应尽量避免全表扫描,应考虑在 where 及 order by 涉及的列上建立索引,建索引可以大大加快数据的检索速度.但是,有些情况索引是不会起效 ...
- 单表千万级数据 count() 统计优化
1. 创建一张测试表: DROP TABLE IF EXISTS `user`; CREATE TABLE `user` ( `id` bigint(20) PRIMARY key not null ...
- 一次 MySQL 千万级大表的优化过程
作者:赵客缦胡缨v吴钩霜雪明 https://www.jianshu.com/p/336f682e4b91 概述 使用阿里云rds for MySQL数据库(就是MySQL5.6版本),有个用户上网记 ...
- MySQL千万级数据JDBC插入
案例语句: String sql = "LOAD DATA LOCAL INFILE '" + dataFilepath + "' into table " + ...
- mysql千万级大数据SQL查询优化
1.对查询进行优化,应尽量避免全表扫描,首先应考虑在 where 及 order by 涉及的列上建立索引.2.应尽量避免在 where 子句中对字段进行 null 值判断,否则将导致引擎放弃使用索引 ...
- 如何优化MySQL千万级大表
很好的一篇博客,转载 如何优化MySQL千万级大表 原文链接::https://blog.csdn.net/yangjianrong1985/article/details/102675334 千万级 ...
- 来个硬货——长文解读:基于业务场景的MySQL千万级大表优化
千万级大表如何优化,这是一个很有技术含量的问题,通常我们的直觉思维都会跳转到拆分或者数据分区,在此我想做一些补充和梳理,想和大家做一些这方面的经验总结,也欢迎大家提出建议. 从一开始脑海里开始也是火光 ...
- MySQL千万级大表优化解决方案
MySQL千万级大表优化解决方案 参考文章: (1)MySQL千万级大表优化解决方案 (2)https://www.cnblogs.com/yliucnblogs/p/10096530.html 备忘 ...
- 30个mysql千万级大数据SQL查询优化技巧详解
点击上方关注 "终端研发部" 设为"星标",和你一起掌握更多数据库知识 文章来自:脚本之家 http://www.jb51.net/article/136701 ...
最新文章
- hadoop自定义类型注意问题
- Redis系列四:redis支持的数据类型
- 数据库:分享四个实用的SQLServer脚本函数,欢迎收藏
- 智能自动PPR更改事件策略
- Django系列:(1)PyCharm下创建并运行我们的第一个Django工程
- 常用的Linux命令行文本处理工具总结
- CSS3学习笔记之loading动画
- 华为交换机路由器最新默认密码大全
- 百度迁徙数据爬取 生成excel数据
- 计算机无法安装新字体,如何解决XP系统中无法安装新字体
- 重量级ORM框架--持久化框架Hibernate【关系映射详解】
- 疫情影响下普惠金融风险与对策
- 苹果新专利:紧急情况下可用指纹或特定输入操作悄悄呼救
- 4 Bootstrap4组件——徽章(Badges)
- 基于Java web的电动车销售平台 毕业设计-附源码201524
- Python 列表元组拆分为多个列表
- 3.2 项目(多肉)
- 解决Ardupilot+gazebo+mavros在仿真状态下无人机能解锁,但是不能起飞的问题
- 怎么看在手机上看hbo_HBO Max上播放的最佳中医电影(2020年6月)
- 【Java8 Stream】:探秘Stream实现的核心:Collector,模拟Stream的实现
热门文章
- KNN算法检测手势动作
- axios跨域携带cookie_vue 本地调试跨域---带cookies(axios)
- Win10中如何找到并打开SqlServer2008 R2配置管理器
- mysql 视图 数据相加_MySQL
- mysql t 保存_检查 (调试) - 离线消息保存到 MySQL - 《EMQ X Enterprise v4.1 中文文档》 - 书栈网 · BookStack...
- md5会重复吗_如何优雅地处理重复请求(并发请求)
- go get如何删除_Go 每日一库之 xorm
- linux cmake变量,linux – CMake错误:此项目中使用了以下变量,但它们设置为NOTFOUND...
- UC浏览器怎样收藏视频
- Win7旗舰版禁止修改文件属性的设置方法