mysql数据库页
很多应用往往只展示最新或最热门的几条记录,但为了旧记录仍然可访问,所以就需要个分页的导航栏。然而,如何通过MySQL更好的实现分页,始终是比较令人头疼的问题。虽然没有拿来就能用的解决办法,但了解数据库的底层或多或少有助于优化分页查询。
我们先从一个常用但性能很差的查询来看一看。
SELECT *
FROM city
ORDER BY id DESC
LIMIT 0, 15
这个查询耗时0.00sec。So,这个查询有什么问题呢?实际上,这个查询语句和参数都没有问题,因为它用到了下面表的主键,而且只读取15条记录。
CREATE TABLE city (
id int(10) unsigned NOT NULL AUTO_INCREMENT,
city varchar(128) NOT NULL,
PRIMARY KEY (id)
) ENGINE=InnoDB;
真正的问题在于offset(分页偏移量)很大的时候,像下面这样:
SELECT *
FROM city
ORDER BY id DESC
LIMIT 100000, 15;
上面的查询在有2M行记录时需要0.22sec,通过EXPLAIN查看SQL的执行计划可以发现该SQL检索了100015行,但最后只需要15行。大的分页偏移量会增加使用的数据,MySQL会将大量最终不会使用的数据加载到内存中。就算我们假设大部分网站的用户只访问前几页数据,但少量的大的分页偏移量的请求也会对整个系统造成危害。Facebook意识到了这一点,但Facebook并没有为了每秒可以处理更多的请求而去优化数据库,而是将重心放在将请求响应时间的方差变小。
对于分页请求,还有一个信息也很重要,就是总共的记录数。我们可以通过下面的查询很容易的获取总的记录数。
SELECT COUNT(*)
FROM city;
然而,上面的SQL在采用InnoDB为存储引擎时需要耗费9.28sec。一个不正确的优化是采用 SQL_CALC_FOUND_ROWS,SQL_CALC_FOUND_ROWS 可以在能够在分页查询时事先准备好符合条件的记录数,随后只要执行一句 select FOUND_ROWS(); 就能获得总记录数。但是在大多数情况下,查询语句简短并不意味着性能的提高。不幸的是,这种分页查询方式在许多主流框架中都有用到,下面看看这个语句的查询性能。
SELECT SQL_CALC_FOUND_ROWS *
FROM city
ORDER BY id DESC
LIMIT 100000, 15;
这个语句耗时20.02sec,是上一个的两倍。事实证明使用 SQL_CALC_FOUND_ROWS 做分页是很糟糕的想法。
下面来看看到底如何优化。文章分为两部分,第一部分是如何获取记录的总数目,第二部分是获取真正的记录。
高效的计算行数
如果采用的引擎是MyISAM,可以直接执行COUNT(*)去获取行数即可。相似的,在堆表中也会将行数存储到表的元信息中。但如果引擎是InnoDB情况就会复杂一些,因为InnoDB不保存表的具体行数。
我们可以将行数缓存起来,然后可以通过一个守护进程定期更新或者用户的某些操作导致缓存失效时,执行下面的语句:
SELECT COUNT(*)
FROM city
USE INDEX(PRIMARY);
获取记录
下面进入这篇文章最重要的部分,获取分页要展示的记录。上面已经说过了,大的偏移量会影响性能,所以我们要重写查询语句。为了演示,我们创建一个新的表“news”,按照时事性排序(最新发布的在最前面),实现一个高性能的分页。为了简单,我们就假设最新发布的新闻的Id也是最大的。
CREATE TABLE news(
id INT UNSIGNED PRIMARY KEY AUTO_INCREMENT,
title VARCHAR(128) NOT NULL
) ENGINE=InnoDB;
一个比较高效的方式是基于用户展示的最后一个新闻Id。查询下一页的语句如下,需要传入当前页面展示的最后一个Id。
SELECT *
FROM news WHERE id < $last_id
ORDER BY id DESC
LIMIT $perpage
查询上一页的语句类似,只不过需要传入当前页的第一个Id,并且要逆序。
SELECT *
FROM news WHERE id > $last_id
ORDER BY id ASC
LIMIT $perpage
上面的查询方式适合实现简易的分页,即不显示具体的页数导航,只显示“上一页”和“下一页”,例如博客中页脚显示“上一页”,“下一页”的按钮。但如果要实现真正的页面导航还是很难的,下面看看另一种方式。
SELECT id
FROM (
SELECT id, ((@cnt:= @cnt + 1) + $perpage - 1) % $perpage cnt
FROM news
JOIN (SELECT @cnt:= 0)T
WHERE id < $last_id
ORDER BY id DESC
LIMIT $perpage * $buttons
)C
WHERE cnt = 0;
通过上面的语句可以为每一个分页的按钮计算出一个offset对应的id。这种方法还有一个好处。假设,网站上正在发布一片新的文章,那么所有文章的位置都会往后移一位,所以如果用户在发布文章时换页,那么他会看见一篇文章两次。如果固定了每个按钮的offset Id,这个问题就迎刃而解了。Mark Callaghan发表过一篇类似的博客,利用了组合索引和两个位置变量,但是基本思想是一致的。
如果表中的记录很少被删除、修改,还可以将记录对应的页码存储到表中,并在该列上创建合适的索引。采用这种方式,当新增一个记录的时候,需要执行下面的查询重新生成对应的页号。
SET p:= 0;
UPDATE news SET page=CEIL((p:= p + 1) / $perpage) ORDER BY id DESC;
当然,也可以新增一个专用于分页的表,可以用个后台程序来维护。
UPDATE pagination T
JOIN (
SELECT id, CEIL((p:= p + 1) / $perpage) page
FROM news
ORDER BY id
)C
ON C.id = T.id
SET T.page = C.page;
现在想获取任意一页的元素就很简单了:
SELECT *
FROM news A
JOIN pagination B ON A.id=B.ID
WHERE page=$offset;
还有另外一种与上种方法比较相似的方法来做分页,这种方式比较试用于数据集相对小,并且没有可用的索引的情况下—比如处理搜索结果时。在一个普通的服务器上执行下面的查询,当有2M条记录时,要耗费2sec左右。这种方式比较简单,创建一个用来存储所有Id的临时表即可(这也是最耗费性能的地方)。
CREATE TEMPORARY TABLE _tmp (KEY SORT(random))
SELECT id, FLOOR(RAND() * 0x8000000) random
FROM city;
ALTER TABLE _tmp ADD OFFSET INT UNSIGNED PRIMARY KEY AUTO_INCREMENT, DROP INDEX SORT,ORDER BY random;
接下来就可以向下面一样执行分页查询了。
SELECT *
FROM _tmp
WHERE OFFSET >= $offset
ORDER BY OFFSET
LIMIT $perpage;
简单来说,对于分页的优化就是。。。避免数据量大时扫描过多的记录。
❷ Mysql 数据库怎么实现分页,要说的通俗一点儿
每次取的数据集是有总条数的
数据集 有当前页,总页数的属性
然后就可以分页啦
rs.pagecount
rs.absolutepage
❸ Mysql 数据库怎么实现分页,要说的通俗一点儿
一个不带limit 一个带limit。以php+mysql为例首先,连接数据库,写一条sql语句把你要查询的信息总量查找出来sql = select count(*) from tb,$all_page ;设定每页显示条数, $display 。然后,当前页为$page ;在写一句sql = select * from tb limit $dispaly*($page - 1),$display;最后,在页面显示分页信息把当前页传回给分页处理页,一定要把相关的条件一起传回去,get 方式传值,否则查询条件改变查询信息就不正确。 网上有好多封装好的分页类。我也有一个很好用的分页类,如果请我吃肉就发给你一份哈。。\(^o^)/~ 追问: 这个$all_page用在哪儿,怎么将当前页传回给分页处理页。显示的时候那些“首页”“上一页”“下一页”“末页”是链接吗、链到什么地方,还是别的什么 回答: $all_page是查询总数,总是页数等于查询总数除以每页显示的信息。$num_page = ceil($all_page/$display); 用get方式把当前页传给分页处理页,就是标签 别的我也想不起来,让我自己写分页,我只会最简单的那种,一般我都是调用一个现成的分页类。只需传个参数就Ok,连样式都不用写的。。。
❹ 怎么用命令打开mysql数据库操作页面
使用命令行连接mysql数据库:
windows操作系统下,开始——运行,打开"运行"对话框,输入cmd,点击“确定”即可进入dos窗口。
dos窗口输入登录mysql数据库命令
mysql
-h
127.0.0.1
-u
root
-p
命令参数说明:
mysql是登录数据库的命令,-h
后面跟服务器的ip,由于本示例mysql服务器安装在本地,因此ip地址为127.0.0.1;-u
后面跟用户名,本示例采用
root用户登录;-p
后面跟登录密码。
输入上述命令后回车,再输入登录密码,在回车即可完成登录mysql数据库服务了。跟着可以运行use
databasename语句操作某个数据库了
❺ 如何打开Mysql数据库
1、安装phpstudy服务器,可以到官网下载这个服务器,会有详细的安装步骤,安装成功后,界面会下图的图标,如下图
❻ mysql数据库页面输入正常,到数据库乱码
考虑是软件不兼容或者是系统问题导致的
如果是这样那么就首先卸载软件
如果不行就需要系统重装
如果还不行就考虑是硬件问题或者其他的设置问题
考虑是你的系统文件问题导致的
可能是由于系统文件错误导致的
个人建议如果能够进入系统就用杀毒软件进行修复
如果不能进入系统就进入安全模式
如果以上方法都不行就只能进行系统统重装了
你所描述的问题解决方法差不多就是以上方法 最后所有方法都没用记得只能请专业人员维修
❼ 急急急!!!请问怎么在Java中每次读取mysql数据库的一页数据
你好:
分页需要用到3个变量,数据总条数、当前页数、一页条数;这3个变量一般从前台传过来,根据这3个变量计算出数据库改取第几条数据到第几条数据,就是limit m,n(m是第几条数据开始,n是一页条数) ;例如第二页,一页显示20条,总条数是50;那就m=(2-1)*20,n=20;就是sql中limit 20,20; 表示取21条到40条数据
❽ php使用mysql数据库分页显示100页,怎么只输出前后5页的超链接,中间的用省略号显示
这个得用程序去判断,根据每页显示的记录条数和记录总数做处理,给你个思路吧。
functiongetTotalPagesStr($total,$maxPageItems){
$totalPages=0;
if($total%$maxPageItems==0){
$totalPages=$total/$maxPageItems;
if($totalPages==0)
$totalPages=1;
}
else{
$totalPages=(int)($total/$maxPageItems)+1;
}
return'<span>共'.$total.'条记录,'.$totalPages.'页</span>';
}
functiongetTotalPages($total,$maxPageItems){
$totalPages=0;
if($total%$maxPageItems==0){
$totalPages=$total/$maxPageItems;
if($totalPages==0)
$totalPages=1;
}
else{
$totalPages=(int)($total/$maxPageItems)+1;
}
return$totalPages;
}
functiongetPageUrl($page){
$url=$_SERVER['PHP_SELF'];
$i=0;
$queryStr='';
foreach($_GETas$key=>$value)
{
if($key!='page'){
if($i==0){
if(is_array($value)){
$j=0;
foreach($valueas$simpleValue){
if($j==0){
$queryStr=$queryStr.'?'.$key.'[]='.$simpleValue;
}
else{
$queryStr=$queryStr.'&'.$key.'[]='.$simpleValue;
}
$j++;
}
}
else{
$queryStr=$queryStr.'?'.$key.'='.$value;
}
}
else{
if(is_array($value)){
foreach($valueas$simpleValue){
$queryStr=$queryStr.'&'.$key.'[]='.$simpleValue;
}
}
else{
$queryStr=$queryStr.'&'.$key.'='.$value;
}
}
$i++;
}
}
foreach($_POSTas$key=>$value)
{
if($key!='page'&&$key!='submit'){
if($i==0){
if(is_array($value)){
$j=0;
foreach($valueas$simpleValue){
if($j==0){
$queryStr=$queryStr.'?'.$key.'[]='.$simpleValue;
}
else{
$queryStr=$queryStr.'&'.$key.'[]='.$simpleValue;
}
$j++;
}
}
else{
$queryStr=$queryStr.'?'.$key.'='.$value;
}
}
else{
if(is_array($value)){
foreach($valueas$simpleValue){
$queryStr=$queryStr.'&'.$key.'[]='.$simpleValue;
}
}
else{
$queryStr=$queryStr.'&'.$key.'='.$value;
}
}
$i++;
}
}
if($i!=0){
return$url.$queryStr.'&page='.$page;
}
return$url.'?page='.$page;
}
functiongetPageDisplay($total,$maxPageItems,$currentPage,$maxShowPages,
$pageSeparator){
$totalPages=getTotalPages($total,$maxPageItems);
$pageDispayStr='';
$ppage=0;
$startPage=0;
$endPage=0;
if($currentPage%$maxShowPages==0)
$ppage=(int)($currentPage/$maxShowPages)-1;
else
$ppage=(int)($currentPage/$maxShowPages);
$startPage=$ppage*$maxShowPages+1;
if($totalPages<=($ppage+1)*$maxShowPages){
$endPage=$totalPages;
}
else{
$endPage=($ppage+1)*$maxShowPages;
}
if($totalPages>$maxShowPages){
if($currentPage==1){
$pageDispayStr=$pageDispayStr.'<span>[第一页/上一页]</span>';
}
else{
$pageDispayStr=$pageDispayStr.'[<ahref=''.getPageUrl(1).''>第一页</a>/';
$pageDispayStr=$pageDispayStr.'<ahref=''.getPageUrl($currentPage-1).''>上一页</a>]';
}
}
if($startPage==1){
$pageDispayStr=$pageDispayStr.'<span><</span>';
}
else{
$pageDispayStr=$pageDispayStr.'<ahref=''.getPageUrl($startPage-1).''><<</a>';
}
for($i=$startPage;$i<=$endPage;$i++){
if($i!=$currentPage){
$pageDispayStr=$pageDispayStr.'<ahref=''.getPageUrl($i).''>'.$i.'</a>';
if($i!=$endPage){
$pageDispayStr=$pageDispayStr.$pageSeparator;
}
$pageDispayStr=$pageDispayStr.'';
}
else{
$pageDispayStr=$pageDispayStr.'<spanclass="current">'.$i.'</span>';
if($i!=$endPage){
$pageDispayStr=$pageDispayStr.$pageSeparator;
}
$pageDispayStr=$pageDispayStr.'';
}
}
if($endPage==$totalPages){
$pageDispayStr=$pageDispayStr.'<span>>></span>';
}
else{
$pageDispayStr=$pageDispayStr.'<ahref=''.getPageUrl($endPage+1).''>>></a>';
}
if($totalPages>$maxShowPages){
if($currentPage==$totalPages){
$pageDispayStr=$pageDispayStr.'<span>[下一页/最后一页]</span>';
}
else{
$pageDispayStr=$pageDispayStr.'[<ahref=''.getPageUrl($currentPage+1).''>下一页</a>';
$pageDispayStr=$pageDispayStr.'/<ahref=''.getPageUrl($totalPages).''>最后一页</a>]';
}
}
returngetTotalPagesStr($total,$maxPageItems).$pageDispayStr;
}
❾ mysql数据库页面渲染正常,可数据库里中文部分显示是乱码是怎么回事
看起来是编码不对,数据库定义的字段编码、网页的编码、以及查询之前mysql_query("set names xxx")的编码,三个一致就不会乱码。
❿ mysql数据库动态分页的sql语句
sql语句是通用的
select * from mytable1 where 1 order by id desc limit 0,10
作用是倒序,取最前10条记录,也就是第一页
取第二页可以是这样的limit 10,10
自已修改着用吧