`
thblovezhj
  • 浏览: 5814 次
  • 性别: Icon_minigender_1
  • 来自: 武汉
最近访客 更多访客>>
社区版块
存档分类
最新评论

【转载】翻动100万级的数据 —— 只需几十毫秒 之揭秘篇

sql 
阅读更多
原文地址:

http://blog.csdn.net/jyk/archive/2006/03/04/615146.aspx

感谢大家的支持!!!
昨天发了一个邀请,邀请大家帮忙测试,效果还可以,下面小结一下:

通过内部的计数器得知:访问次数是1071(其中有好多是自己点的:)),人数不是太理想,本来是想看看上万人同时访问的情况:)

系统资源的占用情况

内存 —— 很理想。SQL占用的内存最大也没有超过65M,一般是在35M左右;asp.net占用的内存最大也没有超过40M,一般是在25M左右。

CPU:8%左右,由于访问次数不多,也不够集中,所以这个数值也说明不了什么。自己连续点了n次下一页,发现CPU的使用率飘高,达到了50%左右。
但是对于100万的记录,AMD XP2000+ 的CPU 几十毫秒的放映速度,因该是可以接受的,甚至是很理想的吧。
毕竟服务器的CPU要比我的快很多吧,而且记录也很难达到100万吧。

结果还是很满意的,但是美中不足的是,我想看一下海量访问的情况下的效果,
希望大家再支持一下,多点几下,谢谢了。呵呵

另外说明一下:前n页可以在60毫秒内完成,n应该是大于500的,小于多少嘛还没有测试。后n页就比较慢了,需要500毫秒左右。

下面讨论一下翻页的技巧吧。
我没有用游标、临时表、not in、in 这些方法,并不是说他们的效率不高,而是我还没有测试过。我只用了 top ,查了两次表。
大家也可提供一些其他的方法,我来测试一下,看看在100万条的情况下的效果。(请不要给在存储过程里面组串的,看着实在是太费劲了)


讨论的前提是在海量数据的情况下,至少是在10万以上的。如果是很少的数据呢,那怎么翻都可以了。也差不了多少。

1.设置合理的索引
首先要做的是设置合理的索引,这个好像经常被忽略,至少很少被谈起。

注意:主键是索引的一种,而且是最快的一种。如果你都是把主键当作排序字段的话,那么你已经利用了索引。

不设置合理的索引的话,会导致查询速度非常的慢,甚至会造成超时。

这方面你可以做一个实验:找一个表,填进去10万条记录,假设有ID 、addedDate等字段,在查询分析器里面执行一下

select top 10 * from table
应该立刻就能出现结果。

然后再执行 select top 10 * from table order by ID(这时ID字段是主键)
也是立刻就出现了结果。

然后再执行 select top 10 * from table order by addedDate (这时addedDate字段没有索引)
你会发现速度很慢。

现在给addedDate 加一个非聚集索引,然后在执行上面的查询语句,速度也变得很快了。

可见索引神奇的效果!

这是翻动百万级记录最基本的设置,具体到我的那个论坛的翻页,我是设置了BoardID、 replyDate两个字段作为联合索引的。
因为是要在同一个讨论组李翻页,而且是按replyDate排序的。


2.只返回需要的记录
对于海量数据,都读出来做缓存,那是不可想象的(记录少的话,也要看利用率,一般都是很浪费的)。
所以呢如果一页显示20条的话名那就只都读出来20条,这样就很省内存和时间。

注意:虽然ADO.NET里面有这个方法
SqlDataAdapter.Fill(DataSet1,startRecord,maxRecords,srcTable);
但是他还是要先从SQL里面把查询语句的查出来的所有记录都出来,然后在截取指定的记录数。这对于SQL来说是一样的,对于海量数据依然会很慢。

论坛里的首页用的是select top 20 * from table where boardID = 5 order by replyDate desc
这样呢就只返回了20条记录,再加上索引的功劳,速度是非常快的。


3.尽量减少字段的长度
一个表可以建很多的字段,但是字段的总长度不能超过8060B,也就是说如果你建了一个char(8060)的字段,就不能在建其他的字段了。

我在第一次的测试中(星期天的),把主题的所有信息都放在了一个表里面,包括了一个nvarchar(3600)的主题内容的字段,复制记录的时候发现非常的慢,
当达到9万的时候,就已经很慢的,勉强把记录数拷贝到了35万,加了索引,测试了一下,翻页速度还是可以的,前n也都是很快的,后n页就很慢了,
如果再加上查询那就非常之慢了。

查看了一下数据文件吓了一跳 —— 他居然占用了1.4G的硬盘空间,怪不得拷贝和查询都慢的要死呢。

于是修改了一下表结构,把那个nvarchar(3600)的主题内容的字段踢了出去,放在一个单独的表里面。
再重新拷贝记录就非常的快了,很快就把记录数从16表成了1048577。昨天的测试就是在这个条件下进行的。

4.技巧
终于到了翻页算法的地方了,呵呵没有等急吧。
思路呢就是先找到一个标志,然后呢把大于(或小于)这个标志的前n条记录取出来。
什么?没看懂。没关系,我举个例子吧。

假设是按ID倒序的,每一页显示10条记录,有100条记录,记录号正好是1到100(怎么这么巧??为了说明方便嘛)

那么第一页的记录就是100到91、第二页的记录就是90到81、第三页的记录就是80到71......

我现在要翻到第三页,那么要找到第21行的记录的ID的值(也就是80),然后把小于等于80的记录用top 10 取出来就行了。

查询语句

declare @pageSize int --返回一页的记录数
declare @CurPage int --页号(第几页)1:第一页;2:第二页;......;-1最后一页。

declare @Count int
declare @id int

set @pageSize=10
set @CurPage =1

if @CurPage = -1
begin
--最后一页
set rowcount @pageSize
select @id=ID from table order by ID
end

--定位
if @CurPage > 0
begin
set @Count = @pageSize * (@CurPage -1) + 1
set rowcount @Count
select @id=ID from table order by ID desc
end

--返回记录
set rowcount @pageSize
select * from table where ID <=@id order by ID desc

set rowcount 0


其中“定位”用了 select @id=ID from table order by ID desc
这种方法,感觉上是很省内存的,因为只记录了一个ID,

然后用 select * from table where ID <=@id order by ID desc
取得最终需要的记录

set rowcount @pageSize 相当于 top @pageSize 。


优点:无论翻到哪一页,内存的占用情况都不变,多人访问内存也不会不变,很多人呢,还没有测试出来:)
缺点:单表、单排序字段。



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 条件

那么单表查询和多表查询有什么区别呢?
至少有很多的多表(单字段排序)查询都是可用这种方式的。
注意:我并没有说所有的多表(单字段排序)查询都可以用,看具体情况了。



这是一个效率最高(需要合理的索引的帮忙),比较通用的翻页方法。不知道这次我有没有讲明白。
分享到:
评论

相关推荐

    翻动相册的flash

    很有用的翻转相册,很常见的flash翻转相册哟

    易语言源码易语言广告翻动源码.rar

    "易语言源码易语言广告翻动源码.rar" 是一个压缩包文件,其中包含了使用易语言编写的广告翻动效果的源代码。这个源码可能是一个小型的程序或模块,用于在软件中实现类似电子广告牌的效果,广告内容能够定时或动态地...

    IOS应用源码——超炫的滑屏翻页效果.zip

    本资源“IOS应用源码——超炫的滑屏翻页效果.zip”包含了一个实现这种效果的完整源代码,适合iOS开发者学习和借鉴。 滑屏翻页效果通常应用于电子书、相册应用或者任何需要展示多个页面的应用中。它模仿了纸质书页在...

    Android项目之——页面特效集合(附源码).zip

    这个名为"Android项目之——页面特效集合(附源码).zip"的压缩包文件包含了一个Android项目的源代码,特别关注于实现各种页面特效。这个项目由Java编写,旨在为开发者提供一系列的视觉效果示例,可以用于增强...

    图片翻动幻灯代码(超酷)

    标题中的“图片翻动幻灯代码(超酷)”指的是一个使用Flash技术实现的动态图片展示效果,这种效果通常在网站的轮播图或者产品展示区应用,能够吸引用户的注意力,提升用户体验。幻灯片翻动效果使得图片的切换不再...

    silverlight书页翻动特效

    在Silverlight中实现书页翻动特效,主要涉及到以下几个关键知识点: 1. **UI元素动画**:Silverlight提供了强大的动画系统,可以对UI元素的各个属性如位置、大小、透明度等进行平滑的动画处理。书页翻动特效通常会...

    JS超酷图片翻动展示效果

    图片翻动效果的实现涉及到几个关键的技术点: 1. **事件监听**:JavaScript的`addEventListener`方法用于监听鼠标事件,如`mouseover`(鼠标进入)和`mouseout`(鼠标离开)。通过对这些事件的响应,我们可以触发...

    随图片快速翻动幻灯代码

    "随图片快速翻动幻灯代码"可能包含以下几个核心知识点: 1. **DOM操作**:JavaScript通过Document Object Model (DOM) API与网页内容交互,包括获取、添加、修改和删除HTML元素。在幻灯代码中,可能涉及到对图片...

    整理随图片快速翻动幻灯代码

    flash整理随图片快速翻动 很棒的效果

    超星阅读器——安装文件

    安装超星阅读器的过程相对简单,只需双击压缩包中的"超星阅读器.exe"文件,按照向导指示操作即可。安装过程中需注意,根据个人需求选择安装路径和是否创建桌面快捷方式。安装完毕后,启动超星阅读器,即可开始享受...

    电子政务-插杆翻动式水电站进水口排沙装置.zip

    在这个特殊的案例中,我们关注的是一个与电子政务相关的技术应用——“插杆翻动式水电站进水口排沙装置”。 水电站是利用水流动力进行发电的重要设施,其进水口的清洁对于发电效率至关重要。进水口如果积累了大量...

    安卓Android源码——逼真翻页效果.zip

    在安卓开发中,实现逼真的翻页效果是提升用户体验的关键因素之一。这个“安卓Android源码——逼真翻页效果.zip”压缩包很可能是提供了一种实现这种效果的示例代码。翻页效果通常用于电子书应用、杂志阅读器或者任何...

    行业文档-设计装置-自升平台翻动模板.zip

    《自升平台翻动模板》是针对海洋工程领域中一种重要的设计装置——自升平台进行详细阐述的专业文档。自升平台是一种能够在海上自行提升至安全水深工作的特殊设施,广泛应用于石油钻探、海洋工程建设等领域。该文档的...

    翻动的书,flash动画,源文件

    翻动的书,一个翻书的flash动画,源文件

    JS鼠标悬停图片翻动展示效果

    在网页设计中,为了增强用户体验和视觉吸引力,经常会利用JavaScript实现一些动态效果,例如"JS鼠标悬停图片翻动展示效果"。这个效果是当用户将鼠标指针悬停在图片上时,图片会呈现出翻转的效果,为用户提供更丰富的...

    TextView实现广告翻动效果

    为了实现广告翻动,我们需要关注以下几个关键点: - **布局设计**:根据需求设计好广告页面的布局,包括TextView的位置、大小和样式。 - **数据管理**:存储广告内容,可以是本地资源,也可以是网络获取的数据。...

    Android源码——书籍翻页效果的demo.zip

    这个"Android源码——书籍翻页效果的demo.zip"包含了一个示例项目,展示了如何在Android平台上创建逼真的翻页动画。下面我们将深入探讨这个知识点。 首先,书籍翻页效果通常涉及到OpenGL ES或者自定义View。在这个...

    IOS应用源码——翻页(电子书).zip

    标题中的“IOS应用源码——翻页(电子书)”表明这是一个关于iOS平台上的电子书应用的源代码项目,特别关注的是实现翻页效果。在iOS开发中,创建具有翻页效果的电子书通常涉及到UI设计、动画效果以及对用户交互的...

    JS鼠标悬停图片翻动展示可控制图片翻动方式.zip

    在JavaScript(JS)编程中,实现鼠标悬停图片翻动展示功能是一种常见的交互设计,它能够为用户带来更丰富的视觉体验。在这个名为“JS鼠标悬停图片翻动展示可控制图片翻动方式.zip”的压缩包中,可能包含了实现这一...

Global site tag (gtag.js) - Google Analytics