千万级数据分页之二---一个简单的自定义分页控件
千万级数据分页之二---一个简单的自定义分页控件
千万级数据分页详细设计
1.1目的
为适应大数据量分页的需要,为以后千万级数据分页提供解决方法或者参考,节省开发时间,特制定本详细设计方案
1.2主要阅读对象
脚本设计人员
1.3参考资料
2.1分页存储过程
2.1.1简介
2.1.2分页存储过程代码
以下代码是网上找的分页存储过程,我是在原存储过程的基础上加了一个@IsCount bit = 0, 主要是用来返回纪录总数,当为非0值时返回。下面注释部分是原作者的测试部分。我在本机sql server 2005上的测试是在10000011纪录中查询第100000页,每页10条纪录按升序和降序时间均为0.38秒,测试语法如下:exec GetRecordFromPage tbl_Briefness,I_BriefnessID,10,100000,其中在tbl_Briefness表I_BriefnessID字段上建立了索引。
/*
经测试,在14483461 条记录中查询第100000 页,每页10 条记录按升序和降序第一次时间均为0.47 秒,第二次时间均为0.43 秒,测试语法如下:
exec GetRecordFromPage news,newsid,10,100000
news 为表名, newsid 为关键字段, 使用时请先对newsid 建立索引。
函数名称: GetRecordFromPage
函数功能: 获取指定页的数据
参数说明: @tblName 包含数据的表名
@fldName 关键字段名
@PageSize 每页记录数
@PageIndex 要获取的页码
@OrderType 排序类型, 0 - 升序, 1 - 降序
@strWhere 查询条件(注意: 不要加where)
创建时间: 2004-07-04
修改时间: 2008-02-13
*/
ALTER PROCEDURE [dbo].[GetRecordFromPage]
@tblName varchar(255), -- 表名
@fldName varchar(255), -- 字段名
@PageSize int = 10, -- 页尺寸
@PageIndex int = 1, -- 页码
@OrderType bit = 0, -- 设置排序类型, 非0 值则降序
@IsCount bit = 0, -- 返回记录总数, 非0 值则返回
@strWhere varchar(2000) = '' -- 查询条件(注意: 不要加where)
AS
declare @strSQL varchar(6000) -- 主语句
declare @strTmp varchar(1000) -- 临时变量
declare @strOrder varchar(500) -- 排序类型
if @OrderType != 0
begin
set @strTmp = '<(select min'
set @strOrder = ' order by [' + @fldName + '] desc'
end
else
begin
set @strTmp = '>(select max'
set @strOrder = ' order by [' + @fldName +'] asc'
end
set @strSQL = 'select top ' + str(@PageSize) + ' * from ['
+ @tblName + '] where [' + @fldName + ']' + @strTmp + '(['
+ @fldName + ']) from (select top ' + str((@PageIndex-1)*@PageSize) + ' ['
+ @fldName + '] from [' + @tblName + ']' + @strOrder + ') as tblTmp)'
+ @strOrder
if @strWhere != ''
set @strSQL = 'select top ' + str(@PageSize) + ' * from ['
+ @tblName + '] where [' + @fldName + ']' + @strTmp + '(['
+ @fldName + ']) from (select top ' + str((@PageIndex-1)*@PageSize) + ' ['
+ @fldName + '] from [' + @tblName + '] where ' + @strWhere + ' '
+ @strOrder + ') as tblTmp) and ' + @strWhere + ' ' + @strOrder
if @PageIndex = 1
begin
set @strTmp = ''
if @strWhere != ''
set @strTmp = ' where (' + @strWhere + ')'
set @strSQL = 'select top ' + str(@PageSize) + ' * from ['
+ @tblName + ']' + @strTmp + ' ' + @strOrder
end
if @IsCount != 0
set @strSQL = 'select count(' + @fldName + ') as Total from [' + @tblName + ']'
exec (@strSQL)
经测试,在14483461 条记录中查询第100000 页,每页10 条记录按升序和降序第一次时间均为0.47 秒,第二次时间均为0.43 秒,测试语法如下:
exec GetRecordFromPage news,newsid,10,100000
news 为表名, newsid 为关键字段, 使用时请先对newsid 建立索引。
函数名称: GetRecordFromPage
函数功能: 获取指定页的数据
参数说明: @tblName 包含数据的表名
@fldName 关键字段名
@PageSize 每页记录数
@PageIndex 要获取的页码
@OrderType 排序类型, 0 - 升序, 1 - 降序
@strWhere 查询条件(注意: 不要加where)
创建时间: 2004-07-04
修改时间: 2008-02-13
*/
ALTER PROCEDURE [dbo].[GetRecordFromPage]
@tblName varchar(255), -- 表名
@fldName varchar(255), -- 字段名
@PageSize int = 10, -- 页尺寸
@PageIndex int = 1, -- 页码
@OrderType bit = 0, -- 设置排序类型, 非0 值则降序
@IsCount bit = 0, -- 返回记录总数, 非0 值则返回
@strWhere varchar(2000) = '' -- 查询条件(注意: 不要加where)
AS
declare @strSQL varchar(6000) -- 主语句
declare @strTmp varchar(1000) -- 临时变量
declare @strOrder varchar(500) -- 排序类型
if @OrderType != 0
begin
set @strTmp = '<(select min'
set @strOrder = ' order by [' + @fldName + '] desc'
end
else
begin
set @strTmp = '>(select max'
set @strOrder = ' order by [' + @fldName +'] asc'
end
set @strSQL = 'select top ' + str(@PageSize) + ' * from ['
+ @tblName + '] where [' + @fldName + ']' + @strTmp + '(['
+ @fldName + ']) from (select top ' + str((@PageIndex-1)*@PageSize) + ' ['
+ @fldName + '] from [' + @tblName + ']' + @strOrder + ') as tblTmp)'
+ @strOrder
if @strWhere != ''
set @strSQL = 'select top ' + str(@PageSize) + ' * from ['
+ @tblName + '] where [' + @fldName + ']' + @strTmp + '(['
+ @fldName + ']) from (select top ' + str((@PageIndex-1)*@PageSize) + ' ['
+ @fldName + '] from [' + @tblName + '] where ' + @strWhere + ' '
+ @strOrder + ') as tblTmp) and ' + @strWhere + ' ' + @strOrder
if @PageIndex = 1
begin
set @strTmp = ''
if @strWhere != ''
set @strTmp = ' where (' + @strWhere + ')'
set @strSQL = 'select top ' + str(@PageSize) + ' * from ['
+ @tblName + ']' + @strTmp + ' ' + @strOrder
end
if @IsCount != 0
set @strSQL = 'select count(' + @fldName + ') as Total from [' + @tblName + ']'
exec (@strSQL)
2.2分页控件的实现
2.2.1分页控件的详细代码
using System;
using System.Collections.Generic;
using System.Text;
using System.ComponentModel;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
namespace CustomControls
{
[ToolboxData("<{0}:AspNetPager runat='server' PageSize='25' FirstPageText='首页' PrePageText='上一页' NextPageText='下一页' EndPageText='末页' ButtonText='GO'></{0}:AspNetPager>")]
public class AspNetPager : WebControl, INamingContainer
{
属性块
分页事件相关
样式属性
自定义视图状态
生成控件
按钮点击事件
重写TagKey
绘制控件
}
}
using System.Collections.Generic;
using System.Text;
using System.ComponentModel;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
namespace CustomControls
{
[ToolboxData("<{0}:AspNetPager runat='server' PageSize='25' FirstPageText='首页' PrePageText='上一页' NextPageText='下一页' EndPageText='末页' ButtonText='GO'></{0}:AspNetPager>")]
public class AspNetPager : WebControl, INamingContainer
{
属性块
分页事件相关
样式属性
自定义视图状态
生成控件
按钮点击事件
重写TagKey
绘制控件
}
}
2.3千万级数据分页实现
2.3.1 简介
这次分页我是用Gridview来实现的,测试时间没算,但基本上从10000011纪录中一次查询25条纪录,在10万页以内,时间花费 在1秒以内。使用其他控件比如DataGrid,DataList或者DataReapter应该花费的时间更短。
2.3.2 适用对象
服务器端控件Gridview,DataGrid,DataList,DataReapter等数据绑定控件
2.3.3 分页实现
分页效果图如下:
前台代码如下:
后台代码如下:
<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Demo.aspx.cs" Inherits="Demo" %>
<%@ Register Assembly="CustomControls" Namespace="CustomControls" TagPrefix="cc2" %>
<%@ Register Assembly="MyLabel" Namespace="MyLabel" TagPrefix="cc1" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
<title>无标题页</title>
<link type="text/css" rel="stylesheet" href="css/comm.css" />
</head>
<body>
<form id="form1" runat="server">
<div>
<asp:GridView ID="GridView1" runat="server" AllowPaging="false" AutoGenerateColumns="False" CellPadding="4" ForeColor="#333333" GridLines="None" PagerSettings-Visible="false"
Width="50%" height="35" OnRowCommand="GridView1_RowCommand" DataKeyNames="I_BriefnessID">
<FooterStyle BackColor="#507CD1" Font-Bold="True" ForeColor="White" />
<RowStyle BackColor="#EFF3FB" />
<EditRowStyle BackColor="#2461BF" />
<SelectedRowStyle BackColor="#D1DDF1" Font-Bold="True" ForeColor="#333333" />
<PagerStyle ForeColor="White" VerticalAlign="Top" BackColor="Transparent" />
<HeaderStyle BackColor="#507CD1" Font-Bold="True" ForeColor="White" />
<AlternatingRowStyle BackColor="White" />
<Columns>
<asp:TemplateField HeaderText="序号">
<ItemTemplate>
<%# Container.DataItemIndex+1 %>
</ItemTemplate>
</asp:TemplateField>
<asp:BoundField DataField="I_BriefnessID" HeaderText="ID" />
<asp:BoundField DataField="I_KMID" HeaderText="科目" />
<asp:BoundField DataField="C_Recno" HeaderText="试题号" />
<asp:BoundField DataField="M_Title" HeaderText="题面" />
<asp:BoundField DataField="C_Answer" HeaderText="答案" />
<asp:TemplateField HeaderText="删除">
<ItemTemplate>
<asp:LinkButton ID="LinkButton1" OnClientClick="return confirm('确定要删除?');" runat="server"
CausesValidation="False" CommandName="DeleteData" CommandArgument='<%#DataBinder.Eval(Container.DataItem,"I_BriefnessID").ToString()%>' Text="删除" ></asp:LinkButton>
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
</div>
<div>
<cc2:AspNetPager ID="AspNetPager1" runat="server" ButtonText="GO" EndPageText="末页"
FirstPageText="首页" NextPageText="下一页" PageSize="15" PrePageText="上一页" OnPageChanged="Page_Changed" Width="50%">
<ButtonStyle CssClass="btn1_mouseout" Width="30px" />
<TextBoxStyle Width="30px" CssClass="blue_rounded"/>
<LabelStyle ForeColor="red" Font-Bold="true" />
</cc2:AspNetPager>
</div>
</form>
</body>
</html>
<%@ Register Assembly="CustomControls" Namespace="CustomControls" TagPrefix="cc2" %>
<%@ Register Assembly="MyLabel" Namespace="MyLabel" TagPrefix="cc1" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
<title>无标题页</title>
<link type="text/css" rel="stylesheet" href="css/comm.css" />
</head>
<body>
<form id="form1" runat="server">
<div>
<asp:GridView ID="GridView1" runat="server" AllowPaging="false" AutoGenerateColumns="False" CellPadding="4" ForeColor="#333333" GridLines="None" PagerSettings-Visible="false"
Width="50%" height="35" OnRowCommand="GridView1_RowCommand" DataKeyNames="I_BriefnessID">
<FooterStyle BackColor="#507CD1" Font-Bold="True" ForeColor="White" />
<RowStyle BackColor="#EFF3FB" />
<EditRowStyle BackColor="#2461BF" />
<SelectedRowStyle BackColor="#D1DDF1" Font-Bold="True" ForeColor="#333333" />
<PagerStyle ForeColor="White" VerticalAlign="Top" BackColor="Transparent" />
<HeaderStyle BackColor="#507CD1" Font-Bold="True" ForeColor="White" />
<AlternatingRowStyle BackColor="White" />
<Columns>
<asp:TemplateField HeaderText="序号">
<ItemTemplate>
<%# Container.DataItemIndex+1 %>
</ItemTemplate>
</asp:TemplateField>
<asp:BoundField DataField="I_BriefnessID" HeaderText="ID" />
<asp:BoundField DataField="I_KMID" HeaderText="科目" />
<asp:BoundField DataField="C_Recno" HeaderText="试题号" />
<asp:BoundField DataField="M_Title" HeaderText="题面" />
<asp:BoundField DataField="C_Answer" HeaderText="答案" />
<asp:TemplateField HeaderText="删除">
<ItemTemplate>
<asp:LinkButton ID="LinkButton1" OnClientClick="return confirm('确定要删除?');" runat="server"
CausesValidation="False" CommandName="DeleteData" CommandArgument='<%#DataBinder.Eval(Container.DataItem,"I_BriefnessID").ToString()%>' Text="删除" ></asp:LinkButton>
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
</div>
<div>
<cc2:AspNetPager ID="AspNetPager1" runat="server" ButtonText="GO" EndPageText="末页"
FirstPageText="首页" NextPageText="下一页" PageSize="15" PrePageText="上一页" OnPageChanged="Page_Changed" Width="50%">
<ButtonStyle CssClass="btn1_mouseout" Width="30px" />
<TextBoxStyle Width="30px" CssClass="blue_rounded"/>
<LabelStyle ForeColor="red" Font-Bold="true" />
</cc2:AspNetPager>
</div>
</form>
</body>
</html>
using System;
using System.Data;
using System.Configuration;
using System.Collections;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
public partial class Demo : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
if (!Page.IsPostBack)
{
TestDataCount();
BindPaperDefineProgramme(1);
}
}
#region 绑定试卷定义方案列表
/// <summary>
/// 统计该表的所有纪录
/// </summary>
private void TestDataCount()
{
DataTable dt = null;
try
{
//public static DataTable GetTestData(string tableName, int pageSize, int pageIndex,string columnName,bool isCount)
//第一个参数为要查询的表,第二个参数为每页的纪录数,第三个为页码,这里初始化为第1页,第四个参数为表的字段
//,第五个参数为是否返回纪录总数,这里为true表示返回纪录总数
dt = ExecProc.GetTestData("tbl_Briefness", AspNetPager1.PageSize, 1, "I_BriefnessID", true);
}
catch (Exception ex)
{
Response.Write(ex.Message);
return;
}
if (dt.Rows.Count != 0)
{
AspNetPager1.RecordCount = int.Parse(dt.Rows[0]["Total"].ToString());
AspNetPager1.PageIndex = 1;//初始化当前页为第一页
}
}
#endregion
protected void Page_Changed(object sender, EventArgs e)
{
BindPaperDefineProgramme(AspNetPager1.PageIndex);
}
删除纪录
绑定试卷定义方案列表
}
using System.Data;
using System.Configuration;
using System.Collections;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
public partial class Demo : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
if (!Page.IsPostBack)
{
TestDataCount();
BindPaperDefineProgramme(1);
}
}
#region 绑定试卷定义方案列表
/// <summary>
/// 统计该表的所有纪录
/// </summary>
private void TestDataCount()
{
DataTable dt = null;
try
{
//public static DataTable GetTestData(string tableName, int pageSize, int pageIndex,string columnName,bool isCount)
//第一个参数为要查询的表,第二个参数为每页的纪录数,第三个为页码,这里初始化为第1页,第四个参数为表的字段
//,第五个参数为是否返回纪录总数,这里为true表示返回纪录总数
dt = ExecProc.GetTestData("tbl_Briefness", AspNetPager1.PageSize, 1, "I_BriefnessID", true);
}
catch (Exception ex)
{
Response.Write(ex.Message);
return;
}
if (dt.Rows.Count != 0)
{
AspNetPager1.RecordCount = int.Parse(dt.Rows[0]["Total"].ToString());
AspNetPager1.PageIndex = 1;//初始化当前页为第一页
}
}
#endregion
protected void Page_Changed(object sender, EventArgs e)
{
BindPaperDefineProgramme(AspNetPager1.PageIndex);
}
删除纪录
绑定试卷定义方案列表
}
Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=2244627