大伙评评,我这算是高效分页吗?

ldg9tpl 2008-07-14 08:12:20
select top " + 每页行数 + " 所取字段 from 文章表 where id not in(select top " + 每页行数乘以页索引值 + " id from 文章表)

我个人觉得这个SQL语句就是高效分页的核心,每次取一页数据而不是取整个表数据。
我在网上参考了一下别人做的例子总结出来的精华,就不知道我这精华臭不臭,呵呵。
看了一个高效分页存储过程例子,整个网页满满一大篇,头都看痛,我把整个例子拷贝到SQL查询分析器,一按右键执行,呵呵,好样啊,居然一点问题都没有,成功了!可是说老实话,我根本就没看懂那例子。我认为你再是天好的代码,你取数据的时候总得界定一个范围啊,还不是要进行内部计算。
我上面这个SQL语句,只要把每页行数和页索引值当作参数输入预先创建好的存储过程,不也是高效分页存储过程吗?我就是搞不懂那些例子干嘛要弄满满一大篇,是不是我这个语句执行时根本就不高效呢?
我的做法主要有两个步骤:
1、先[select count(id) from 文章表],得出总记录,从而计算页数(当然也考虑到余页问题);
2、在数据查询过程中,有个取数据时界定取值范围的内部计算,也就是后面那个SQL子句嘛。
我这样做,是不是在效率和性能上存在不足呢?
各位兄弟姐妹讨论讨论一下,谢谢!祝愿大家都进步哦。
...全文
145 24 打赏 收藏 转发到动态 举报
写回复
用AI写文章
24 条回复
切换为时间正序
请发表友善的回复…
发表回复
ldg9tpl 2008-07-15
  • 打赏
  • 举报
回复
哈哈,谢谢大家的参评啊,有朋友说不错,有朋友说不是最高效滴。
是不是高效无止境啊,呵呵,虽然不是最高效,但不知面对100万级数据是不是能胜任啊?
哥们再评评啊,3Q
Chris_thanks 2008-07-15
  • 打赏
  • 举报
回复
[Quote=引用 2 楼 igelf 的回复:]
这个不是最高效的。
[/Quote]
suyiming 2008-07-15
  • 打赏
  • 举报
回复
-- 获取指定页的数据

CREATE PROCEDURE pagination3

@tblName varchar(255), -- 表名

@strGetFields varchar(1000) = '*', -- 需要返回的列

@fldName varchar(255)='', -- 排序的字段名

@PageSize int = 10, -- 页尺寸

@PageIndex int = 1, -- 页码

@doCount bit = 0, -- 返回记录总数, 非 0 值则返回

@OrderType bit = 0, -- 设置排序类型, 非 0 值则降序

@strWhere varchar(1500) = '' -- 查询条件 (注意: 不要加 where)

AS

declare @strSQL varchar(5000) -- 主语句

declare @strTmp varchar(110) -- 临时变量

declare @strOrder varchar(400) -- 排序类型

if @doCount != 0

begin

if @strWhere !=''

set @strSQL = "select count(*) as Total from [" + @tblName + "] where "+@strWhere

else

set @strSQL = "select count(*) as Total from [" + @tblName + "]"

end

--以上代码的意思是如果@doCount传递过来的不是0,就执行总数统计。以下的所有代码都是@doCount为0的情况

else

begin

if @OrderType != 0

begin

set @strTmp = "<(select min"

set @strOrder = " order by [" + @fldName +"] desc"


--如果@OrderType不是0,就执行降序,这句很重要!

end

else

begin

set @strTmp = ">(select max"

set @strOrder = " order by [" + @fldName +"] asc"

end

if @PageIndex = 1

begin

if @strWhere != ''

set @strSQL = "select top " + str(@PageSize) +" "+@strGetFields+ " from [" + @tblName + "] where " + @strWhere + " " + @strOrder

else

set @strSQL = "select top " + str(@PageSize) +" "+@strGetFields+ " from ["+ @tblName + "] "+ @strOrder

--如果是第一页就执行以上代码,这样会加快执行速度

end

else

begin

--以下代码赋予了@strSQL以真正执行的SQL代码

set @strSQL = "select top " + str(@PageSize) +" "+@strGetFields+ " 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) +" "+@strGetFields+ " from ["

+ @tblName + "] where [" + @fldName + "]" + @strTmp + "(["

+ @fldName + "]) from (select top " + str((@PageIndex-1)*@PageSize) + " ["

+ @fldName + "] from [" + @tblName + "] where " + @strWhere + " "

+ @strOrder + ") as tblTmp) and " + @strWhere + " " + @strOrder

end

end

exec (@strSQL)

GO

上面的这个存储过程是一个通用的存储过程,其注释已写在其中了。
seesea125 2008-07-15
  • 打赏
  • 举报
回复
搞什么搞,超过100万条数据,分页还能这么玩吗?怎么玩速度也不快,大数据量,就需要单加一字段标明页数直接读取了,页数的标明需要每天晚上跑任务计算,只有头3页是动态取值的
minhua1983 2008-07-15
  • 打赏
  • 举报
回复
首先用not in效率不会高的,除非你按主键排序。
最近我也再测试分页用的就是21楼的通用分页存储过程
不过我修改了下,因为原始的程序不支持多表联合查询,也不能按时间或点击数来排序,因为这个通用的分页存储过程在按照其他字段排序时,只要那个字段有相同的值出现时,分页有问题的。
后来没办法~自己修改,又没比较好的解决方按,我也只能用not in来了。
我测试过100W的数据,当主键是累加一的ID时(默认聚族索引),按ID排序,分页在SQL SERVER 中执行还是很快的,我的测试数据1秒不到。但是如果按其他字段排序的话,很慢,在11秒~17秒。
以上还只是在SQL SERVER 2005中直接执行存储过程的结果。如果在正式环境中测试的话,估计更慢。
编程有钱人了 2008-07-15
  • 打赏
  • 举报
回复
我测试完了
100条万数据
速度还行
你的那句得该成
select top " + 每页行数 + " 所取字段 from 文章表 where id not in(select top " + 每页行数*(以页索引值 -1)+ " id from 文章表)
要不第一页不显示

速度平均

很好

贴我给你测试的代码

SqlConnection conn = new SqlConnection(ConfigurationManager.ConnectionStrings["constr"].ConnectionString);
int ToatalCountRecord;//总记录数
int PageItem = 10;//每页显示的条数
int CurrentPage = 1;//当前页数
protected void Page_Load(object sender, EventArgs e)
{
if (!this.Page.IsPostBack)
{
if (Request.QueryString["page"] != null)
{
if (!Int32.TryParse(Request.QueryString["page"].ToString(), out CurrentPage))
{
Response.Write("请输入分页参数!");
Response.End();
return;
}
}

this.BuidGrid();
}

}
private void BuidGrid()
{
string s2 = "select top "+this.PageItem+" * from fed where serial not in (select top "+PageItem*(CurrentPage-1)+" * from fed )";
SqlDataAdapter da = new SqlDataAdapter(s2, conn);
DataSet ds = new DataSet();
//int startRecord = (CurrentPage - 1) * PageItem;
da.Fill(ds,"a");
this.DataList1.DataSource = ds.Tables["a"].DefaultView;
this.DataList1.DataBind();
SqlCommand comm = new SqlCommand("select count(*) from fed", conn);
conn.Open();
ToatalCountRecord = Convert.ToInt32(comm.ExecuteScalar());
conn.Close();
BuildPages();
}
private void BuildPages()
{
int Step = 5;//偏移量
int LeftNum = 0;//做界限
int RightNum = 0;//右界限
string PageUrl = Request.FilePath;
int PageCount = (int)Math.Ceiling((double)(ToatalCountRecord) / PageItem);
if (CurrentPage - Step < 1)
{
LeftNum = 1;
}
else
{
LeftNum = CurrentPage - Step;
}
if (CurrentPage + Step > PageCount)
{
RightNum = PageCount;
}
else
{
RightNum = CurrentPage + Step;
}
string OutPut = "";
if (CurrentPage > 1)
{
OutPut += " <a href='" + PageUrl + "?page=" + (CurrentPage - 1) + "'>" + "上一页" + " </a>";
}
for (int i = LeftNum; i <= RightNum; i++)
{
if (i == CurrentPage)
{
OutPut += " <font color=red>" + " " + "[" + i.ToString() + "]" + "" + " </font>";
}
else
{
OutPut += " <a href='" + PageUrl + "?page=" + i.ToString() + "'>" + " " + "[" + i.ToString() + "]" + " " + " </a>";
}
}
if (CurrentPage < PageCount)
{
OutPut += " <a href='" + PageUrl + "?page=" + (CurrentPage + 1) + "'>" + "下一页" + " </a>";
}
this.PageInfo.InnerHtml = OutPut;
}
cftea 2008-07-15
  • 打赏
  • 举报
回复
[Quote=引用 18 楼 cftea 的回复:]
引用 14 楼 cftea 的回复:
楼主,我使用你的分页和另外一个分页进行了一下测试。
我的数据量是 109 万多点。
另一个分页算法(假设命名为 B):

SQL codeselect *
from (select top 当前页大小 *
from (select top 当前页*页大小 * from news order by id desc) a
order by a.id) b
order by b.id desc


从执行计划来看,你的分页要稍优一点点,但从实际执行来看,B…
[/Quote]
再继续往后翻,你的分页优势却很明显了,我想,是由于分页 B 中对大量数据进行排序占用了大量资源,而 not in 此时相比之下效率还要优得多。
cftea 2008-07-15
  • 打赏
  • 举报
回复
[Quote=引用 14 楼 cftea 的回复:]
楼主,我使用你的分页和另外一个分页进行了一下测试。
我的数据量是 109 万多点。
另一个分页算法(假设命名为 B):

SQL codeselect *
from (select top 当前页大小 *
from (select top 当前页*页大小 * from news order by id desc) a
order by a.id) b
order by b.id desc



从执行计划来看,你的分页要稍优一点点,但从实际执行来看,B 要优一点。
如果把你的也加…
[/Quote]
我又测试了下后页的页,越往后面翻页,你的分页的执行计划的优势虽然越来越明显,然后实际执行效率却越来越低,我想还是耗在 not in 上。
winner2050 2008-07-15
  • 打赏
  • 举报
回复
not in的分页方案能支持多字段排序.
cftea 2008-07-15
  • 打赏
  • 举报
回复
补充一下,我的数据库中,id 是聚集索引,升序,取结果用的是降序。
zyug 2008-07-15
  • 打赏
  • 举报
回复
.....真正的效率分页是不取总数的,因为取总数才是最慢的
cftea 2008-07-15
  • 打赏
  • 举报
回复
楼主,我使用你的分页和另外一个分页进行了一下测试。
我的数据量是 109 万多点。
另一个分页算法(假设命名为 B):
select *
from (select top 当前页大小 *
from (select top 当前页*页大小 * from news order by id desc) a
order by a.id) b
order by b.id desc


从执行计划来看,你的分页要稍优一点点,但从实际执行来看,B 要优一点。
如果把你的也加上 order by,那么不论是执行计划还是实际执行来说,B 都要优很多。

另外,如果楼主只是按 id 排序的话,根据实际情况,还会有更优的分页。
xhan2000 2008-07-15
  • 打赏
  • 举报
回复
只能算数据分页中最一般的解决方案

not in在大数据量时远不如in来得快

最好还是存储过程解决方案
编程有钱人了 2008-07-15
  • 打赏
  • 举报
回复
lz 我有100万条数据的数据库
给你测试以下哈
测试完了给你结果
walkghost 2008-07-15
  • 打赏
  • 举报
回复
not in 啊,效率那叫一个“高”啊。你要是有个几千万条记录。。。。你得not in个多长时间啊?不知道lz有没有对大数量数据计算过。把你的语句放到几千万条数据记录的库里面执行下就晓得效率高不高了。实践是检验真理的唯一标准嘛!
46539492 2008-07-15
  • 打赏
  • 举报
回复
[Quote=引用 7 楼 ldg9tpl 的回复:]
哈哈,谢谢大家的参评啊,有朋友说不错,有朋友说不是最高效滴。
是不是高效无止境啊,呵呵,虽然不是最高效,但不知面对100万级数据是不是能胜任啊?
哥们再评评啊,3Q
[/Quote]
能不能胜任,先插入百万级数据,打开SQL SERVER PROFILER,测试一下运行时间就知道
xuan.ye 2008-07-15
  • 打赏
  • 举报
回复
[Quote=引用 7 楼 ldg9tpl 的回复:]
哈哈,谢谢大家的参评啊,有朋友说不错,有朋友说不是最高效滴。
是不是高效无止境啊,呵呵,虽然不是最高效,但不知面对100万级数据是不是能胜任啊?
哥们再评评啊,3Q
[/Quote]
没问题的
igelf 2008-07-15
  • 打赏
  • 举报
回复
[Quote=引用 15 楼 zyug 的回复:]
.....真正的效率分页是不取总数的,因为取总数才是最慢的
[/Quote]
高手,指点一二
oec2003 2008-07-15
  • 打赏
  • 举报
回复
not in
最好換成另外的替代方式
lendylixt 2008-07-14
  • 打赏
  • 举报
回复
不错
加载更多回复(4)

62,165

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术交流专区
javascript云原生 企业社区
社区管理员
  • ASP.NET
  • .Net开发者社区
  • R小R
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

.NET 社区是一个围绕开源 .NET 的开放、热情、创新、包容的技术社区。社区致力于为广大 .NET 爱好者提供一个良好的知识共享、协同互助的 .NET 技术交流环境。我们尊重不同意见,支持健康理性的辩论和互动,反对歧视和攻击。

希望和大家一起共同营造一个活跃、友好的社区氛围。

试试用AI创作助手写篇文章吧