http://community.csdn.net/Expert/TopicView3.asp?id=4182510发了这个帖子,回复的人很多,感谢大家的支持。这里有个误会我不得不说明一下,免的误人子弟。在帖子里我并不是写了个算法就完事了,而是说了很多翻动海量数据要注意的地方,比如建立合理的索引,只返回需要的记录 ,尽量减少字段的长度 等注意到或没有注意到的地方。最后说的才是算法,可能是我的表达能力太差了吧,举的例子给大家带来了误会。翻页的语句 ( @pageSize * (@CurPage -1) + 1 )--定位
declare @id int
select top 41 @id=ID from table order by ID desc --显示数据
select top 20 * from table where ID <=@id order by ID desc 按照ID倒序排列(也就是按照int类型的字段排序)
一页显示20条记录,这是显示第三页的语句
@pageSize * (@CurPage -1) + 1 = 20*(3-1) + 1 = 41
正是因为ID是不连续的所以才需要用第一个语句来定位,如果是连续的那还用第一条语句做什么呢?举各少量数据的例子:
假设有10条记录,ID是:1000,500,320,205,115,110,95,68,4,1。这回不写连续的了免的误会
一页显示两条记录,现在要显示第三页,那么第三页的id就是 115,110先看第一条语句
select top 5 @id=ID from table order by ID desc
不知道大家有没有看懂这句,这时print @id 得到的结果是 115。再看第二条语句
select top 2 * from table where ID <=115 order by ID desc
这时的记录集就是 115,110,也就是我们所需要的记录了。
注意:不需要连续的ID,也不局限只能按ID排序,你可以换成ReplyDate(最后回复时间)字段,
当然了declare @id int 要改成 declare @id datetime这里的ID 是主键,唯一标识记录的字段,它本身就是一种索引,而且是效率最高的索引。A.唯一标识记录的字段的值怎么能随意改动呢,那不乱套了吗?B.主键是最快的索引,可能你还没有意识到(一开始我就不知道,学了SQL很久以后才知道的),如果你的算法用它作为排序字段,那么速度会很快,会比用其他字段(没有索引的字段)排序快很多。C.用ReplyDate(最后回复时间)来排序,那么就必须给他建立索引(在海量数据的情况下),否则会超时的。
D.建立索引后,再执行添加、修改、删除会对数据库带来灾难性的折磨??
一开始我也是这么认为的,但是为了能够翻页,不得不加索引。
但是接下来的事实确打消了我的顾虑先来看添加。
100万条记录是怎么弄出来的?大家可以看到帖子里有很多标题一样的主题,对了是复制出来的。
我先加了16条记录,然后加上了索引。注意在insert into 之前就已经建立好了索引!接下来就是insert into table (...) select ... from table 影响的行数:
16、32、64、128、256、512、1024、2048、4096、8192、16384、32768、65536、
131072、262144、524288 很快记录就达到了100完了。
最后一次也只不过一两分钟(具体的时间忘记了,反正是很快了)。
同时,论坛也提供了发贴的功能,只是在批量添加记录的时候,把一些记录的最后回复时间弄成了2006年,
所以,你发的帖子不会显示在第一页。但是你可以看到,执行时间是很快的。可见添加的时候是不成问题的,索引是倒序排列的,所以影响的行数绝对没有你想象的那么多。再来看修改。
看了sp1234的回复,加了修改的功能,只是为了测试,所以呢可以修改标题、最后发表时间、分组ID。
为什么可以修改这几个字段呢?标题是普通字段,最后发表时间和分组ID是索引字段。
修改这几个字段需要的时间都是很快的,在最后回复时间的右面有 [改] [删] 字样,大家可以试一试。
同样,修改的时候,影响的行数也不是很多。最后看删除
不多说了,论坛提供了这个功能,试一下就知道了。另外,删除的时候,不用重新建立一遍索引吧?
在来说一下是用范围吧。
首先呢这只是一种方法,而不是一个通用的存储过程,也就是说要根据情况作适当的修改。
最佳使用环境:
单表,单排序字段,可以利用索引。
注意事项:
排序字段不必连续,最好使用int、datetime类型的字段,字符串型的字段没有试过,效果可能会略差。
表可以没有主键,但是对于海量数据的情况下,必须建立合理的索引。有一个比较致命的限制,大家好像都没有发现,那就是排序字段的重复性,
最好是没有重复的,但不是说绝对不能有重复的记录,有不要紧,只要不跨页就行,跨页的话就会挤掉若干条记录,
用时间字段来排序,发生重复的记录的可能性就很小了。
扩展性:
bingbingcha(不思不归,不孟不E,原来是头大灰狼) 的回复很精彩
-----------------
这样的技巧在SQL区都讨论过了..速度是很快的..但是满足不了需求的..实用性太差了..现在的企业需要用到分页的大部分都是多表查询..单表分页满足不了需求的..这个存储过程可以扩展..用临时表+楼主的方法..是个不错的选择..
-----------------对于多表关联查询,有两种方法,第一种就是bingbingcha说的 —— “用临时表+楼主的方法”,这是在海量数据的时候唯一可行的方法。
但是在小数据量的时候,这么些就有一点繁琐,而且不容易归纳到通用的写法里。先来看一下查询语句据的写法:
联合的
SELECT a.ReplyID, a.TopicID
FROM dbo.BBS_Reply a INNER JOIN
dbo.BBS_body b ON a.BodyID = b.bodyID
where a.ReplyID >10单表的SELECT ReplyID, TopicID
FROM dbo.BBS_Reply
where ReplyID >10有没有看到相同的地方:
select 显示的字段
from 表
where 条件那么单表查询和多表查询有什么区别呢?
至少有很多的多表(单字段排序)查询都是可用这种方式的。
注意:我并没有说所有的多表(单字段排序)查询都可以用,看具体情况了。这是一个效率最高(需要合理的索引的帮忙),比较通用的翻页方法。不知道这次我有没有讲明白。
另外还有一个更通用的,但是效率略低了一点,需要表必须有一个主键(唯一字段)的方法。
我管他叫颠颠倒倒法。select * from bbs_topic where topicid in
(
select top 2 topicid from
(
select top 4 topicid,topOrder from bbs_topic
order by topOrder desc
) as aa order by topOrder
)
order by topOrder desc
公式
select 要显示的字段 from 表 where 主键 in
(
select top 一页的记录数 主键 from
( select top 一页的记录数 * 页号 主键,排序字段 from 表
order by 排序字段 desc ) as aa order by 排序字段
)
order by 排序字段 desc是不是有点晕,这个思路和not in 的方法有些类似,多用了一个select避开了not in。可以多字段排序,排序字段可以用重复的,可以多表查询(但不是很方便,也没有做过很多的测试)缺点:越往后翻越占内存,必须有主键。这个就不多解释了,能看懂就看了。另外论坛有查询的功能,但是比较占用内存,所以就不开放了。我键了一个群 6761675 ,感兴趣的一起研究。
declare @id int
select top 41 @id=ID from table order by ID desc --显示数据
select top 20 * from table where ID <=@id order by ID desc 按照ID倒序排列(也就是按照int类型的字段排序)
一页显示20条记录,这是显示第三页的语句
@pageSize * (@CurPage -1) + 1 = 20*(3-1) + 1 = 41
正是因为ID是不连续的所以才需要用第一个语句来定位,如果是连续的那还用第一条语句做什么呢?举各少量数据的例子:
假设有10条记录,ID是:1000,500,320,205,115,110,95,68,4,1。这回不写连续的了免的误会
一页显示两条记录,现在要显示第三页,那么第三页的id就是 115,110先看第一条语句
select top 5 @id=ID from table order by ID desc
不知道大家有没有看懂这句,这时print @id 得到的结果是 115。再看第二条语句
select top 2 * from table where ID <=115 order by ID desc
这时的记录集就是 115,110,也就是我们所需要的记录了。
注意:不需要连续的ID,也不局限只能按ID排序,你可以换成ReplyDate(最后回复时间)字段,
当然了declare @id int 要改成 declare @id datetime这里的ID 是主键,唯一标识记录的字段,它本身就是一种索引,而且是效率最高的索引。A.唯一标识记录的字段的值怎么能随意改动呢,那不乱套了吗?B.主键是最快的索引,可能你还没有意识到(一开始我就不知道,学了SQL很久以后才知道的),如果你的算法用它作为排序字段,那么速度会很快,会比用其他字段(没有索引的字段)排序快很多。C.用ReplyDate(最后回复时间)来排序,那么就必须给他建立索引(在海量数据的情况下),否则会超时的。
D.建立索引后,再执行添加、修改、删除会对数据库带来灾难性的折磨??
一开始我也是这么认为的,但是为了能够翻页,不得不加索引。
但是接下来的事实确打消了我的顾虑先来看添加。
100万条记录是怎么弄出来的?大家可以看到帖子里有很多标题一样的主题,对了是复制出来的。
我先加了16条记录,然后加上了索引。注意在insert into 之前就已经建立好了索引!接下来就是insert into table (...) select ... from table 影响的行数:
16、32、64、128、256、512、1024、2048、4096、8192、16384、32768、65536、
131072、262144、524288 很快记录就达到了100完了。
最后一次也只不过一两分钟(具体的时间忘记了,反正是很快了)。
同时,论坛也提供了发贴的功能,只是在批量添加记录的时候,把一些记录的最后回复时间弄成了2006年,
所以,你发的帖子不会显示在第一页。但是你可以看到,执行时间是很快的。可见添加的时候是不成问题的,索引是倒序排列的,所以影响的行数绝对没有你想象的那么多。再来看修改。
看了sp1234的回复,加了修改的功能,只是为了测试,所以呢可以修改标题、最后发表时间、分组ID。
为什么可以修改这几个字段呢?标题是普通字段,最后发表时间和分组ID是索引字段。
修改这几个字段需要的时间都是很快的,在最后回复时间的右面有 [改] [删] 字样,大家可以试一试。
同样,修改的时候,影响的行数也不是很多。最后看删除
不多说了,论坛提供了这个功能,试一下就知道了。另外,删除的时候,不用重新建立一遍索引吧?
在来说一下是用范围吧。
首先呢这只是一种方法,而不是一个通用的存储过程,也就是说要根据情况作适当的修改。
最佳使用环境:
单表,单排序字段,可以利用索引。
注意事项:
排序字段不必连续,最好使用int、datetime类型的字段,字符串型的字段没有试过,效果可能会略差。
表可以没有主键,但是对于海量数据的情况下,必须建立合理的索引。有一个比较致命的限制,大家好像都没有发现,那就是排序字段的重复性,
最好是没有重复的,但不是说绝对不能有重复的记录,有不要紧,只要不跨页就行,跨页的话就会挤掉若干条记录,
用时间字段来排序,发生重复的记录的可能性就很小了。
扩展性:
bingbingcha(不思不归,不孟不E,原来是头大灰狼) 的回复很精彩
-----------------
这样的技巧在SQL区都讨论过了..速度是很快的..但是满足不了需求的..实用性太差了..现在的企业需要用到分页的大部分都是多表查询..单表分页满足不了需求的..这个存储过程可以扩展..用临时表+楼主的方法..是个不错的选择..
-----------------对于多表关联查询,有两种方法,第一种就是bingbingcha说的 —— “用临时表+楼主的方法”,这是在海量数据的时候唯一可行的方法。
但是在小数据量的时候,这么些就有一点繁琐,而且不容易归纳到通用的写法里。先来看一下查询语句据的写法:
联合的
SELECT a.ReplyID, a.TopicID
FROM dbo.BBS_Reply a INNER JOIN
dbo.BBS_body b ON a.BodyID = b.bodyID
where a.ReplyID >10单表的SELECT ReplyID, TopicID
FROM dbo.BBS_Reply
where ReplyID >10有没有看到相同的地方:
select 显示的字段
from 表
where 条件那么单表查询和多表查询有什么区别呢?
至少有很多的多表(单字段排序)查询都是可用这种方式的。
注意:我并没有说所有的多表(单字段排序)查询都可以用,看具体情况了。这是一个效率最高(需要合理的索引的帮忙),比较通用的翻页方法。不知道这次我有没有讲明白。
另外还有一个更通用的,但是效率略低了一点,需要表必须有一个主键(唯一字段)的方法。
我管他叫颠颠倒倒法。select * from bbs_topic where topicid in
(
select top 2 topicid from
(
select top 4 topicid,topOrder from bbs_topic
order by topOrder desc
) as aa order by topOrder
)
order by topOrder desc
公式
select 要显示的字段 from 表 where 主键 in
(
select top 一页的记录数 主键 from
( select top 一页的记录数 * 页号 主键,排序字段 from 表
order by 排序字段 desc ) as aa order by 排序字段
)
order by 排序字段 desc是不是有点晕,这个思路和not in 的方法有些类似,多用了一个select避开了not in。可以多字段排序,排序字段可以用重复的,可以多表查询(但不是很方便,也没有做过很多的测试)缺点:越往后翻越占内存,必须有主键。这个就不多解释了,能看懂就看了。另外论坛有查询的功能,但是比较占用内存,所以就不开放了。我键了一个群 6761675 ,感兴趣的一起研究。
解决方案 »
- cs文件中如何添加 GridView列 超链接【跪求大虾!!!!】
- ASP.net打包安装时出现这个错误提示!!!!
- .net怎么调用java生成的RSA公钥进行加密?
- 点了树后在iframe里加载页面出了问题,变成弹出窗口了,请问问题出在哪儿呢?
- 请问以下日程安排模块是的周期模式是何意?
- 怎么把dataview类型转换为dataset类型
- 一个冒泡排序小疑问 大家帮忙
- asp.net怎样调用java的webservice
- 求救,再一个页面中怎样保存一个公共变量的值,不用Cookie,已此推致两个页面传参(不用页面传参方法)--再线等
- 这条sql语句怎么写
- 我想把Request.Params["id"]得到的值赋给一个变量(char类型)
- 一个DropDownList的操作?
update myTable set col1 = col1-1 col1 是int型的字段
这条语句,不明白sp1234要说明什么。实践证明:如果原来col1的值是 1,2,3,4,5,6
那么执行过后 col1的值是 0,1,2,3,4,5不知道sp1234说的是不是这个。
set @n=1
select myTable set id=@n,@n=@n+1 order by 分类,价格 desc,有限期
==============这是什么呢?
查询显示顺序??是排序字段吗?所有查询都是按照预先定义的ID排的
不是呀,可以按回复时间来排呀,也不是预先定义的呀。任何自定义的顺序都得重新计算ID
ID是主键,是标识记录的标志,就像身份证号,QQ号码,怎么能重新计算呢?这是绝对不可以的。建立索引是在海量数据的情况下,如果数据不多的话,就不用建了。可能是我写得太多了,懒得看了吧。:)另外我问一下sp1234,有没有遇到过要分页的情况呢?你用的是什么方法呢?
回复时间: 1 7 3 5 6 9 30 2 4每页4条记录。按照你的算法(咱们还是抓重点假设只在后边追加,因而可以按照由小到大排),要取得第2页,取得@id=11,然后再所有id<=2的记录中取后边4条作为第2页数据。这能成立吗?
回复时间: 1 7 3 5 6 9 30 20 4你的说法,按照回复时间取第8个,也就是@id=11,然后取id<=@id的记录中的后4条。我都是假设回复时间和id全都没有重复的情况。
declare @id int
select top 41 @id=ID from table order by ID desc--显示数据
select top 20 * from table where ID <=@id order by ID desc 这个我已经试验多次了,绝对没有问题的(在排序字段不重复时)。建议你在查询分析器里面试一下,就不要在这里争论了。
讲一个笑话吧。一个小朋友上幼儿园,阿姨叫他们加法。阿姨告诉他们,一个苹果加上两个苹果等于三个苹果。
回家了妈妈问他,在幼儿园里都学什么了,他说学加法了,
妈妈说,那好哇,我考考你把:一个桔子加上两个桔子,十几个桔子呀?在幼儿园里,阿姨用的是苹果呀!
22:13:48___5000
21:57:16___4002
21:48:09___3050
21:46:41___300221:43:01___2040
21:42:01___2025
21:40:36___2010
21:36:21___505121:36:21___5052
21:34:58___056
21:30:55___022
21:30:19___01121:23:24___1010
21:17:24___1000
21:12:43___999
20:57:28 120:56:28___-1其实ID是多少无所谓了,和他没有关系按回复时间倒序,一页显示4条记录,每一页显示的记录已经用空行分割出来了。下面先显示第三页的记录。--定位
select top 9 @time = time from table order by time desc这时@time 是 21:36:21(第9条记录的time值)。主意@time的值不是22:13:48(第一条的)
--显示记录
select top 4 * from table where time <='21:36:21' order by time desc先考虑没有重复的情况,比'21:36:21'小(包括相等的)有
21:36:21___5052
21:34:58___1056
21:30:55___1022
21:30:19___101121:23:24___1010
21:17:24___1000
21:12:43___999
20:57:28___120:56:28___-1而且是按time desc 排序的,再取前4条就是我们所需要的了。
现在来看看有重复的情况
21:36:21___5051
21:36:21___5052
21:34:58___1056
21:30:55___102221:30:19___1011___我在哪??21:23:24___1010
21:17:24___1000
21:12:43___999
20:57:28___120:56:28___-1由于多了一个21:36:21 ,于是 21:30:19___1011 就被挤出去了。
在显示第4页的时候 top 13 找到的是 21:23:24 ,
21:30:19 比他大,所以21:30:19也不会出现在第四页。但是DateTime精确到毫秒,出现重复的概率是很低的,应该是可以忽略的。
错了,毫秒也是可以重复的
select top 5 @id=ID from table order by ID desc
不知道大家有没有看懂这句,这时print @id 得到的结果是 115。那个5怎么确定啊???
不管如何,楼主的精神是值得俺学习的,学习ing