当前位置:首页 » 编程语言 » csql分页

csql分页

发布时间: 2025-01-17 01:35:11

Ⅰ C# 获取数据库内容分页,求大神指点,在线等

有两种方法:

1.使用数据库,也就是使用sql来实现。这部分,你网上一搜一大堆。所以,这里不回答了。

2.如果你使用的framework是大于.NET3.5以上的,那么,非常简单,使用linq即可。

效果图:

privateDataTabledt=newDataTable();
privateinti=0;
privatevoidForm1_Load(objectsender,EventArgse)
{
dt.Columns.Add("id");
dt.Columns.Add("name");
for(inti=0;i<10;i++)
{
dt.Rows.Add(i.ToString(),"A"+i.ToString());
}
btnNext.PerformClick();
}
privatevoidbtnNext_Click(objectsender,EventArgse)
{
varquery=fromqindt.AsEnumerable()
whereConvert.ToInt32(q["id"])>=2*i&&Convert.ToInt32(q["id"])<=2*i+1
selectq;
dataGridView1.DataSource=query.AsDataView();
i++;
}

Ⅱ 大数据量实时统计排序分页查询(并发数较小时)的几点建议

大数据量实时统计排序分页查询的瓶颈不是函数(count,sum等)执行,

不是having, 也不是order by,甚至不是表join, 导致慢的原因就在于“数据量太大本身”

就是将表划分为M份相互独立的部分,可以是分表,也可以是不分表但冗余一个取模结果字段

实际结果是不分表比分表更加灵活,只需稍加配置,就可以动态切分大表,随意更改M的大小。

将1条慢sql(大于30秒)拆分成为N条查询速度巨快的sql(单条sql执行时间控制在20毫秒以内)

然后再web应用中以适当的线程数去并发查询这些执行时间快的N条小sql再汇总结果

第一步查询中去并发执行这N条小sql, 只取排序字段和标识字段,其他字段一律丢弃

汇总结果后定位出当前页面要显示的pageNum条数据,再进行第二步查询,取出页面上需要展示的所有字段

PS:这一点是至关重要的,其他几点都可以不看,这点是最关键的。慢慢解释一下:

有三种方式统计所有的记录,

a) 第一种方式是把数据库中所有记录(只取排序字段和标识字段并且不做任何sum,count having order by等操作)

全部拉到web应用中,在web应用中完成所有的计算

b) 第二种方式是把数据库中所有记录做sum count having等操作之后的所有行数拉到web应用中,在web应用中完成剩余计算

c) 第三种方式是把数据库中所有记录做sum count having order by等操作之后把limit后的数据拉到web应用中,

在web应用中对limit后的数据再计算

显然,第一种方式 数据库什么活都不做只取数据 是不可行的。以lg_order_count_seller为例,1500万行,

如果只算id, seller_id和order_count 这三个bigint类型,至少需要拉8*3*1500 0000 = 360000000=340M,

拉到内存中之后存储需要8*4*15000000= 460M,这还不算List是的2的n次方这个特点和计算排序等的内存开销,

不仅数据库与web应用机器IO扛不住,就是应用自身恐怕也要OOM了。

第二种方式,所有记录做sum count having等操作之后,由于是group by seller_id的,总得数据量变为100万(就是卖家总数),

这样子一来,共需要拉8*3*100 0000 = 23M,拉到内存之后,需要8*4*100 0000 = 30M, 再算上List是的2的n次方这个特点和

计算排序等的内存开销也不会超过100M, IO的时间和内存开销勉强可以考虑接受。

第三种方式,所有记录做sum count having order by等操作之后把limit后的数据拉到web应用中,因为做了limit,所以,

数据量很小了,无论是IO还是内存开销都已经很小了。可以忽略。

综合以上三种,第三种方式适用于页面的前n页和后n页,因为这个limit的数据量随着页数的增大而增大,

当大到每个切分后的小表的数据量时就转为第二种方式了。

第二种方式适用于页面的第[n+1, totaoPageNum-n]页。

① 问题描述:

优化之前,还是是一条大慢sql查询时,由于数据库排序是稳定排序,

所以当两条记录排序字段值相同时他们在页面上的页码位置是固定的。

优化之后,当并行执行这N条小sql时,由于无法控制这些小sql的先后执行顺序,

导致在web应用中当两条记录的排序字段值相同时在页面上的页码位置是随机的。

② 解决办法:

除了拉标识字段(seller_id)和排序字段(order_count_sum)之外,再取一个unique(id)的字段,当两条记录的排序字段值相同时,

再用这个unique的字段(在卖家监控中这个字段是id)进行第二次排序.这样就解决了排序不稳定的问题。

③ 也许,看到这里会有疑问,为什么不用seller_id?seller_id也是唯一, 这样子不是少取id这个字段,减少IO了?

seller_id虽然也是唯一,可以辅助排序,但是不要忘记数据库的排序规则是:

如果两列的值相等,那么序号在前的排在前面,这里的序号就是主键(自动生成,autoincrement),

如果用seller_id的话还是不能保证排序的稳定性,只能用主键id.

把数据库的连接,扫表,计算等资源优先让给用户关注的主要元素,次要元素可等主要元素加载完成之后再加载。

反应在卖家监控页面中,查数据和查页页码的sql语句基本相同,是在竞争同一资源,

所以,需要做一个策略,优先把资源让给查数,数据查完之后再去查页码。

由于多线程取数据并没有从本质上提高数据库性能,所以必须针对大数据量实时统计排序分页查询做限流

我这里打个比方:食堂有6个窗口,物流团队吃饭要买6个菜,平均每买1个菜需要1分钟的时间,

如果派我一个人去一个窗口买的话需要6分钟的时间

假如派6个人分别去6个窗口买这6个菜,只需要1分钟的时间

但是,如果除了物流团队,再来其他5个团队呢,也就是说6个团队每个团队买6个菜共买36个菜,

这样子有的团队先买完,有的团队后买完,但平均时间还是6分钟。本质上没有变化。

所以,对于特定的查询条件,必须进行限流。让每分钟至多有6个团队买菜,这样子能使得情况变得不至于太糟糕。

这一点从目前来看只能是展望了,比如mysql数据库换更为强大的oracle数据库,

或更换InnoDb引擎为其他,或更换SATA硬盘为SSD 。。。。。。

相同的查询条件,原来一个页面查询时间由于超过60秒超时了,根据1-6点建议优化之后,查询时间变为2秒至3.5秒之间。

Ⅲ 不使用数据库怎么在页面上实现分页显示

一.逻辑分页

1.逻辑分页的第一种方式,利用ResultSet的滚动分页。步骤如下:
a.根据条件sql查询数据库。
b.得到ResultSet的结果集,由于ResultSet带有游标,因此可以使用其next()方法来指向下一条记录。
c.利用next()方法,得到分页所需的结果集。

这种分页方式依靠的是对结果集的算法来分页,因此通常被称为“逻辑分页”。

代码如下:

/**
* TestPageResultSetDAO.java
*
* Copyright 2008. All Rights Reserved.
*/
package com.cosmow.pageresultset.;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

import com.cosmow.pageresultset.entity.Bars;

/**
* TODO class TestPageResultSetDAO
*
* Revision History
*
* 2008-7-7,Cosmo,created it
*/
public class TestPageResultSetDAO {

private final String FIND_BARS_PAGE = "SELECT * FROM YYBARS ORDER BY id";

/**
* 提供JDBC连接方法,返回一个Connection的实例
*
* @return
* @throws SQLException
*/
private Connection getConnection() throws SQLException {
try {
final String url = "jdbc:oracle:thin:@localhost:1521:ORCL";
final String user = "store";
final String password = "store_password";
Class.forName("oracle.jdbc.driver.OracleDriver");
Connection con = DriverManager.getConnection(url, user, password);
return con;
} catch (ClassNotFoundException e) {
throw new SQLException(e.getMessage());
}
}

/**
* 逻辑分页方法一,该方法使用移位(rs.next)来进行
*
* @param currentPage
* 当前页
* @param showRows
* 一页显示的数据量
*/
public List<Bars> pageListOne(int currentPage, int showRows) {
Connection con = null;
PreparedStatement ps = null;
ResultSet rs = null;
ArrayList<Bars> resultList = new ArrayList<Bars>();
try {
con = getConnection();
ps = con.prepareStatement(FIND_BARS_PAGE);
rs = ps.executeQuery();
// 过滤结果集的变量
int skipBegin = (currentPage - 1) * showRows;
int skipEnd = currentPage * showRows;
// 翻页计数器
int currentNum = 0;
// 当返回结果集中有记录时
while (rs.next()) {
// 以下情况将保证在结果集中有记录时的应用
if (currentNum >= skipBegin && currentNum < skipEnd) {
Bars bar = new Bars();
bar.setId(rs.getLong("id"));
bar.setName(rs.getString("name"));
bar.setType(rs.getInt("type"));
bar.setCreatorId(rs.getLong("creator_id"));
resultList.add(bar);
if (currentNum == skipEnd - 1)
break;
}
currentNum++;
}
} catch (SQLException e) {
e.printStackTrace();
} finally {
try {
if (rs != null)
rs.close();
if (ps != null)
ps.close();
if (con != null)
con.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
return resultList;
}
}

2.逻辑分页的第二种方式
利用Scrollable ResultSets(可滚动结果集合)来快速定位到某个游标所指定的记录行,所使用的是ResultSet的absolute()方法。
改进代码如下:
/**
* TestPageResultSetDAO.java
*
* Copyright 2008. All Rights Reserved.
*/
package com.cosmow.pageresultset.;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

import com.cosmow.pageresultset.entity.Bars;

/**
* TODO class TestPageResultSetDAO
*
* Revision History
*
* 2008-7-7,Cosmo,created it
*/
public class TestPageResultSetDAO {

private final String FIND_BARS_PAGE = "SELECT * FROM YYBARS ORDER BY id";

/**
* 提供JDBC连接方法,返回一个Connection的实例
*
* @return
* @throws SQLException
*/
private Connection getConnection() throws SQLException {
try {
final String url = "jdbc:oracle:thin:@localhost:1521:ORCL";
final String user = "store";
final String password = "store_password";
Class.forName("oracle.jdbc.driver.OracleDriver");
Connection con = DriverManager.getConnection(url, user, password);
return con;
} catch (ClassNotFoundException e) {
throw new SQLException(e.getMessage());
}
}

/**
* 逻辑分页方法二,使用absolute()方法分页
*
* @param currentPage
* 当前页
* @param showRows
* 一页显示的数据量
*/
public List<Bars> pageListTwo(int currentPage, int showRows) {
Connection con = null;
PreparedStatement ps = null;
ResultSet rs = null;
ArrayList<Bars> resultList = new ArrayList<Bars>();
try {
con = getConnection();
ps = con.prepareStatement(FIND_BARS_PAGE);
rs = ps.executeQuery();

// 过滤结果集的变量
int skipBegin = (currentPage - 1) * showRows;
int skipEnd = currentPage * showRows;
// 利用rs.absolute进行定位
if (!rs.absolute(skipBegin))
return resultList;
// 当返回结果集中有记录时
while (rs.next()) {
// 以下情况将保证在结果集中有记录时的应用
if (skipBegin < skipEnd) {
Bars bar = new Bars();
bar.setId(rs.getLong("id"));
bar.setName(rs.getString("name"));
bar.setType(rs.getInt("type"));
bar.setCreatorId(rs.getLong("creator_id"));
resultList.add(bar);
if (skipBegin == skipEnd - 1)
break;
}
}
} catch (SQLException e) {
e.printStackTrace();
} finally {
try {
if (rs != null)
rs.close();
if (ps != null)
ps.close();
if (con != null)
con.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
return resultList;
}
}

虽然和第一种方式区别不大,单效率比ResultSet滚动要好,但是absolute()方法并不是所有jdbc驱动都支持。
可用如下代码测试当前jdbc驱动是否支持可滚动结果集:

int type = rs.getType();
if (type == ResultSet.TYPE_SCROLL_INSENSITIVE || type == ResultSet.TYPE_SCROLL_SENSITIVE)
System.out.println("Result set is scrollable");
else
System.out.println("Result set is not scrollable");

二.物理分页
利用数据库本身的一些特性来分页。即:利用了数据库对sql语法的优化,提高分页性能。
1.针对Oracle数据库
步骤如下:
a.根据所使用的数据库特性来组织sql进行分页。
b.每次跳转页面的sql查询都不相同。
通用的sql分页方式,“限制行数结果集的倒序”分页,步骤如下:
(1).取得符合条件的所有结果集中可以唯一标识的Key值(通常是主键),并正向排序。
(2).利用数据库提供的特殊方法进行“最大结果集”的限制(在Oracle中使用rownum, sql server中使用top, mysql中使用limit...),
该“最大结果集”指包含当前所处页的所有记录数,“最大结果集”应该只包含惟一的Key值。
(3).对步骤(2)中的“最大结果集”进行逆序,并取得“显示当前页显示数量的结果集”,该结果集中只包含惟一的Key值。
(4).通过步骤(3)中所取得的Key值取得显示数据,该显示数据就是当前页应该显示的数据。

2.针对MySQL数据库
在MySQL数据库中offset关键字的意思是"越过",而limit关键字的意思是“限制”,利用这两者结合可轻松分页。
(1)取得符合条件的结果集,包含全字段。
(2)利用offset关键字越过一段结果集(被越过的结果集就是"(当前页 - 1) * 一页显示数")。
(3)利用limit关键字限制取得一段结果集(被限制取得的结果集就是一页显示数)

代码如下:

/**
* TestPageResultSetDAO.java
*
* Copyright 2008. All Rights Reserved.
*/
package com.cosmow.pageresultset.;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

import com.cosmow.pageresultset.entity.Bars;

/**
* TODO class TestPageResultSetDAO
*
* Revision History
*
* 2008-7-7,Cosmo,created it
*/
public class TestPageResultSetDAO {

private final String FIND_BARS_MYSQL = "select * from yybars order by id limit ? offset ?";

/**
* 提供JDBC连接方法,返回一个Connection的实例
*
* @return
* @throws SQLException
*/
private Connection getConnection() throws SQLException {
try {
final String url = "jdbc:oracle:thin:@localhost:1521:ORCL";
final String user = "store";
final String password = "store_password";
Class.forName("oracle.jdbc.driver.OracleDriver");
Connection con = DriverManager.getConnection(url, user, password);
return con;
} catch (ClassNotFoundException e) {
throw new SQLException(e.getMessage());
}
}

/**
* 物理分页方法二针对mysql,使用sql语句的limit和offset来进行分页
*
* @param currentPage
* 当前页
* @param showRows
* 一页显示的数据量
*/
public List<Bars> pageListFour(int currentPage, int showRows) {
Connection con = null;
PreparedStatement ps = null;
ResultSet rs = null;
ArrayList<Bars> resultList = new ArrayList<Bars>();
try {
con = getConnection();
ps = con.prepareStatement(FIND_BARS_MYSQL);
//传入参数,第一个参数表示显示几条记录(limit关键字的含义)
ps.setInt(1, showRows);
//第二个参数表示丢弃几条记录(offset关键字的含义)
ps.setInt(2, showRows * (currentPage - 1));
rs = ps.executeQuery();
// 当返回结果集中有记录时
while (rs.next()) {
Bars bar = new Bars();
bar.setId(rs.getLong("id"));
bar.setName(rs.getString("name"));
bar.setType(rs.getInt("type"));
bar.setCreatorId(rs.getLong("creator_id"));
resultList.add(bar);
}
} catch (SQLException e) {
e.printStackTrace();
} finally {
try {
if (rs != null)
rs.close();
if (ps != null)
ps.close();
if (con != null)
con.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
return resultList;
}
}

分页结论:
1.物理分页速度上并不一定快于逻辑分页,逻辑分页速度上也并不一定快于物理分页。
2.物理分页总是优于逻辑分页:没有必要将属于数据库端的压力加诸到应用端来,就算速度上存在优势,
然而其它性能上的优点足以弥补这个缺点。
3.在分页工作前,有必要了解使用数据库本身的一些sql语句特点更好的分页。

分页方法有很多,主要看哪种符合你的要求。

希望我的回答对你有帮助,若帮助到您请及时的采纳
及时不采纳也请赞同下,让咱有继续回答的动力哈

热点内容
最优化遗传算法 发布:2025-01-17 03:35:24 浏览:546
四代飞度家用需要加装哪些配置 发布:2025-01-17 03:34:28 浏览:876
安卓手机猫和老鼠怎么换号 发布:2025-01-17 03:23:58 浏览:469
安卓系统怎么下蝙蝠 发布:2025-01-17 03:20:07 浏览:19
加密解密文件 发布:2025-01-17 03:16:32 浏览:83
抗震柱加密区 发布:2025-01-17 03:03:06 浏览:134
幼儿园源码php 发布:2025-01-17 02:41:45 浏览:401
win引导Linux 发布:2025-01-17 02:36:49 浏览:263
ftp是传输类协议吗 发布:2025-01-17 02:36:47 浏览:311
查看电视配置下载什么软件 发布:2025-01-17 02:36:41 浏览:159