成功长时期周期下目的的毫秒级查询 华泰证券开放一种长时期周期下目的毫秒级查询的方法 (成功的周期)
专利摘要显示,本发明地下了一种长时期周期下目的毫秒级查询的方法,采集目的并将采集的目的发送至信息两边件,采纳流式计算引擎取得目的聚算计算结果,以及加工目的流量中每条目的,并将目的聚算计算结果、加工后的明细目的结果分区存储至时序数据库 ElasticSearch 中,调用时序数据库 ElasticSearch 网关接纳外部恳求;解析接纳的外部恳求,取得外部恳求中的查询参数;并查询参数、性能的网关协议,确定时序数据库 ElasticSearch 网关查询索引的途径,用于加快照应目的查询服务。本发明的方法在时序数据库 ElasticSearch 中运行流式计算技术的流式计算才干,支持到毫秒级查询,从而成功对应毫秒级目的查询的才干,以及流式计算技术引擎采纳不同的时期窗口聚合,使得查询服务全体估量算量可控。
弱网下移动端网络衔接处置战略
一、背景 如何度量和模拟“弱网络”对移动APP的开发有着严重的意义,比如:浪费测试本钱、易于疑问重现、放慢产品上线等。
普通的方法是经常使用“丢包率”和“网络延时”来定义和权衡“弱网络”。
二、手机接入主机的流程 要讲这个疑问,首先要来了解下手机接入主机的流程。
首先,手机要经过无线网络协议,从基站取得无线链路分配,才干跟网络启动通讯。 无线网络基站、基站控制器这方面,会给手机启动信号的分配,已成功手机衔接和交互。 取得无线链路后,会启动网络附着、加密、鉴权,中心网络会审核你是不是可以衔接在这个网络上,能否开放套餐,是不是遨游等。 中心网络有SGSN和GGSN,在这一步成功无线网络协议和有线以太网的协议转换。 再下一步,中心网络会给你启动APN选择、IP分配、启动计费。 再往上方,才是传统网络的步骤:DNS查询、照应,树立TCP链接,HTTP GET,RTTP RESPONSE 200 OK,HTTP RESPONSE DATA,LAST HTTP RESPONSE DATA,末尾UI展现。 这是手机经过无线网络接入主机的全环节。 整个环节当中有几个困扰开发者的疑问:
无线网络是怎样给手机分配到无线链路的? 中心网络有接入点(APN),这里的CMNET和CMWAP有什么区别,仅仅是协议不同吗吗?数据转发又有什么区别?一个数据包在不同网络上传输有不同吗? 用户怎样最快的找到正确的主机?内容怎样加快有效的加载,在第一时期显示出来? 这几个疑问的重点在于其中的几个衔接点:
3.2 一秒钟规律 依据以下状况,就构成无线网络的一大特点:秒级形态控制,秒级形态转换。 这两个操作都在几百ms到几秒之间启动,关于维持衔接来说时期太短,关于从无衔接到有衔接的转换来说时期又太长。 相比之下,有线网络的形态控制如ip分配、tcp衔接释放,都是分钟级,而形态转换则是毫秒级。
这些通讯机制,同时加上无线网络的高延迟、高丢包。如何保证移动互联网的产品提供稳如泰山的、可预期的服务质量,成为十分大的应战:
2G网络上无线部分数据传输的延迟有几百ms,4G网络上无线部分传输延迟增加到几十ms,中心网形态转换、协议转换30~100ms,IP主干网上的延迟又跟物理距离以及运营商互联互通质量有关,跨运营商50-400ms,同运营商5-80ms,这个还要取决于网络拥塞的状况。 无线网络误码率比有线高两个数量级,在不同时期段的动摇也十分庞大。 怎样基于移动网络的特性去优化服务?
这就是我们总结的一秒钟规律:在一秒内要成功的规则举措。
1,2g网络:1秒内成功dns查询、和后台主机树立衔接 2,3g网络:1秒内成功首字显示(首字时期) 3,wifi网络:1秒内成功首屏显示(首屏时期) 4,这些目的要求在终端度量,必需跟用户体验相关:首字时期、首屏时期都必需是用户可以直观感遭到的。
四、优化思绪 4.1 服务保证准绳 从以上剖析可知,如何保证移动互联网的产品提供稳如泰山的、可预期的服务质量,具有十分大的应战。以下几点准绳或许会有协助:
1), 接口设计优化 ,接口的优化通常上不属于APP弱网络的优化,但是这个的API性能的疑问,确真实网络条件不好的状况下才原形毕露。 大家都在议论主机的好坏,设备的性能上下,其实,关于一个良好的Server来说,绝大部分拖延恳求速度的中央都是在IO上。 包括,磁盘读写的IO,SQL查询的IO等等。 常用的优化点:慢查询监控 、屡次查询优化、常用接口cache等。 2) 图片相关战略。 1)经常使用更快的图片格式,严厉说也不算弱网下的优化,但一个更快的图片格式真的很关键!这里建议采用WebP格式。 (WebP格式,谷歌(google)开发的一种旨在放慢图片加载速度的图片格式。 图片紧缩体积大约只要JPEG的2/3,并能节省少量的主机带宽资源和数据空间。 但WebP是一种有损紧缩。 相较编码JPEG文件,编码相同质量的WebP文件要求占用更多的计算资源。 ) 2)、不同网络的不同图片下发。 如(关于原图是600X480的图片):2/3G经常使用低明晰度图片——>下发300X240,精度为80的图片、4G普通明晰度图片——>下发600X480,精度为80的图片、WiFi拙劣晰度图片(最好依据网速来判别,wifi也有慢的)——>下发600X480,精度为100的图片。 3) 断线重连 。 这或许是最重的一个特性,由于在无线网络中有太多的要素造成数据衔接终止了。 这里可以经常使用CDN。 (CDN 是构建在数据网络上的一种散布式的内容分发网。 CDN 的作用是采用流媒体主机集群技术,克制单机系统输入带宽及并发才干缺乏的缺陷,可极大优化系统支持的并发流数目,增加或防止单点失效带来的不良影响。 ) 4)由于创立衔接是一个十分昂贵的操作,所以应尽量 减少数据衔接的创立次数 ,且在一次性恳求中应尽量以批量的方式执行义务。 假设屡次发送小数据包,应该尽量保证在2秒以内发送出去。 在短时期内访问不同主机时,尽或许地复用无线衔接。 5), 优化DNS查询 。 应尽量增加DNS查询、防止域名劫持、DNS污染,同时把用户调度到“最优接入点”。 6), 减小数据包大小和优化包量 。 经过紧缩、精简包头、信息兼并等方式,来减小数据包大小和包量。 7),控制数据包大小不超越1500, 防止分片 。 包括逻辑链路控制(Logic Link Control)分片、GGSN分片,以及IP分片。 其中,当数据包大小超出GGSN所支持的最大大小时,GGSN的处置方式有以下三种:分片、丢弃和拒绝。 8), 优化TCP socket参数 ,包括:能否封锁加快回收、初始RTO、初始拥塞窗口、socket缓存大小、Delay-ACK、Selective-ACK、TCP_CORK、拥塞算法(westwood/TLP/cubic)等。 做这件事情的意义在于:由于2G/3G/4G/WIFI/公司内网等接入网络的QoS差异很大,所以不同网络下为了取得较好的服务质量,上述参数的取值差异或许会很大。 9), 优化ACK包 。 在弱网络的状况下,TCP协议中的ACK包是十分昂贵的,延时甚至能够到达秒级别,而TCP协议的拥塞控制、加快重传、加快恢复等特性都十分依赖接纳端反应的ACK包。 可想而知,假设发送端接纳到的ACK包延时太长,会严重影响TCP协议的效率。 但是假设发送ACK太多又会占用珍贵过多的无线资源。 在移动网络下通讯,“在牢靠的衔接上,如何在增加ACK包的状况下,降低数据包的延时”是研讨的热点。 基本的思想:平衡冗余包和ACK包个数,到达降低延时,提高吞吐量的目的。 例如SGSN和GGSN之间的通讯成功:二者之间经过UDP协议通讯,发送者在无新的数据包的状况下,每隔一定的时期重试已发送的包,到达最大重试次数后,则丢弃该包。 10), TCP的拥塞控制算法 是以“丢包意味着网络出现拥塞”为假定设计的,很清楚这个假定在无线网络环境下是不适宜的。 但是在无线网络环境下,在设计牢靠UDP协议时能否能够完全丢弃拥塞控制呢?这里有其它的文章中提出了几种在无线网络环境下的TCP友好的拥塞控制算法,有兴味可以自行查阅。 11), 灵敏经常使用长衔接/短衔接 ,支持不同协议(TCP/UDP, http、二进制协议等),支持不同端口等。 12), 让用户觉得快 。 到这里曾经不能算是技术层面的方法了,属于一种心思层面的博弈,一种改善用户体验的方式。 比如: 1)、不从0末尾的进度条。 不论网页的加载进度如何,不论网络条件如何,加载进度一直是从50%起,并且逗留在大约98%进度左右的中央。 2)、先显示文字在加载图片。 相同是在Webview之中,图片或许多媒体的加载速度必需是远远慢过文字的加载速度的。 由于不同的webview显示和渲染效果不同,我们可以先让webview先显示文字,在显示图片。 给用户一种可以先预览整个网页概略的觉得。
4.2 接入调度优化 接入调度优化首先要思索的是增加DNS的影响。移动网络的DNS有如下特点:
1)主干网无法识别移动用户在哪个城市,东西南北各个中央的调度没有充沛调用。 目前有一部分全国范围的DNS承载了超越40%的全网用户 2),很多山寨机的终端local dns设置是错误的 3),另外还有一些有线网络也一样会遇到的疑问,如终端DNS解析滥用、域名劫持、DNS污染、老化、软弱等。 不过关于这些疑问,桌面的自愈性会比拟好,而在手机上则比拟难以处置。
关于DNS的疑问,有两条关键的处置思绪:
1),增加DNS的恳求、查询、更新,也就是做DNS缓存 2),在终端性能server list,直接访问IP,不用DNS
但仅仅这么做还不够,由于用户或许来自国际外不同的运营商,还要求进一步优化调度战略:
1),DNS缓存要求多树立接入点,用不同域名区分 2),IP列表要求更新以顺应不同网络状况,要做到主动调度。 好比最早我们只服务好移动用户就行,保证移动用户的接入质量优先,由于绝大少数用户集中在移动;如今国际有三个运营商,用户散布的比例在渐渐接近,要区分清楚;智能手时机用wifi,接入的是电信、联通还是哪个运营商,不知道,所以你无法能预先设置场景再if then,必需经事先台调度才干来处置。
再进一步优化,就发生一种融合的方式:
1),先做域名解析,客户端直接衔接解析的IP,可以用http协议,也可以用tcp socket 2),多端口、多协议组合:不同协议有不同的限制,有些只能http,有些只能tcp socket,各种环境都要顺应,客户端不能只支持一种协议 3),终端测速:接入点越来越多,接入哪个适宜,要选择,可以经过终端测速来选择最快的。 你当然可以每一次性新建衔接都做测速,但是这样树立衔接时期或许会很长;我们可以给用户先树立衔接后,在后台依据常年速度监控、以后测速的结果,来做灵活调度。 也就是说,第一次性衔接或许不是最优,衔接树立后灵活测速,再转移到最快接入点。 更进一步就是树立网络profile,终端学习的思绪。
关于测速采样的粒度,移动互联网取IP段是没用的,比拟好的粒度是到网元级别,比如广东有20多个wap网关,每一个网关的状况都不一样,这就是一个比拟适宜的粒度。
最后强调一个一切的接入调度准绳:不要把调度逻辑写死在客户端,一定要由后台成功。
4.3 协议优化 协议参数优化这块就简易列一下,是常年运营环节中总结的一些阅历,在启动移动互联网服务时作为运营的规范,可以少走很多弯路:
1,封锁TCP加快回收 2,Init RTO不低于3秒 3,初始拥塞控制窗口不小于10。 由于大部分页面在10kB以下,很多恳求在慢启动阶段曾经完毕,改为10可以降低小页面资源传输时延。 内容越大,这个选项的效果就比拟不清楚。 4,Socket buffer > 64k 5,TCP滑动窗口可变 6,控制发包大小在1400字节以下,防止分片
协议优化的准绳总结上去是这么几条:
1,衔接重用 2,并发衔接控制 3,超时控制 4,包头精简 5,内容紧缩 6,选择更高效率的协议。 无论是TCP、HTTP、UDP、长衔接、GZIP、SPDY、WUP还是WebP,每一种协议、方案都有其道理,没有最优,只要能否适宜你的产品和服务特点,要求大家在运营环节验证和取舍。
4.4 WAP接入点优化 关于WAP接入点优化,或许有些人会说,我们的App是高端大气上层次的运行,是不是就不用做WAP优化?实践上我们的统计显示,目前有5%-20%的用户选择的接入点是*WAP(CMWAP、3GWAP、CTWAP),这甚至包括一些iPhone终端。 实践上,WAP网关实质是个代理,不完全是落后的东西,随着技术的提高也在演进,以后在组网架构中或许有综合网关、内容计费网关来取代目前的WAP网关,所以建议也要一并思索。 以下是做WAP优化要求留意的一些疑问:
1,资费提示页面 2,302跳转处置 3,X-Online-Host经常使用与处置 4,包大小限制 5,劫持与缓存 6,正确失掉资源包大小
4.5 业务逻辑优化
1, 简化逻辑 :交互繁琐的内容尽量用标识更新。 举一个例子,我们在老版的手机QQ上做过一个测试:假设我有100个好友,用手机QQ成功登陆,成功好友列表更新一遍,要求3.5分钟。 这必需是不合理的。 建议用信令形态来通知能否要求更新,同时合理应用缓存。 在比如玩游戏,好友给你送了很多星星,是让用户一次性一次性点还是批量点?从优化的角度必需是批量点,从用户体验的角度这也愈加舒适。 另一方面,延伸域名图标的缓存时期也可以有效地优化访问次数。 我们把手机腾讯网图标的缓存时长从120分钟延伸到2天后,访问次数优化了差不多35%。 2, 柔性可用 :这个意思就是在网络质量好的时刻给高清大图,不好的时刻先给用户看小图,点一下再拉取原图。 举一个极端的例子,比如万一地震了,基站毁掉20%,用户要给家人报安康,这时刻产品上就必需优化,比如只发送文字,合理降3, 低网络消耗 。 另内在照应很慢的时刻,要求给用户一些合理的页面提示,比如提示用户再过5秒会发送,所以你不要不时刷屏,这也可以增加访问对后台服务、对网络的冲击。
上方说了那么多,这里就给出一个实例协助大家更直观的了解。
这里给出一个DNS系统设计来成功最优调度。其拓扑结构如下:
TGCP SDK的职责:
1,用HTTP的Get/Post方法从DNSvr获主机和DNSvr自身的最优接入点列表。 Get/Post方法的查询参数包括uin/openid、客户端版本号、IP列表的MD5(留意IP顺序)、域名列表、VIP、ServiceID等。 2,缓存访问主机和DNSvr的IP列表,以及其它元数据(比如IP列表等),且以APN为主键。 3,满足一定的条件下,要主动更新缓存的IP列表,例如缓存过时。
Tconnd的职责:
1,路由查询恳求给活动的DNSvr;
DNSvr的职责:
1,依据静态和灵活战略来选择客户端的“最优接入点”。 静态战略:依据uin/openid、客户端版本号或许强迫规则来选择IP列表;灵活战略:灯塔依据测速数据灵活选择用户的主机接入点。 2,支持以手动或智能的方式拉黑某些IP。 智能方式:由主机的接入tconnd向DNSvr上报其能否存活(要求向多个点上报,包括用公网IP上报),假设在一定时期内没有接纳到上报或许上报信息中明白一切的逻辑主机曾经挂掉,则智能拉黑相应的IP。 假设业务恢复,则智能激活相应的IP。 假设项目组接入TGW,关于某个IP和端口能否可用,则要求思索进程与VIP的映射相关。 3,在tcaplus中缓存灯塔的计算结果。 此时要求DNSvr能够依据客户端IP判别所属的国度、省份、运营商和网关(可以经过访问MIG的IP库成功)。 假设缓存了灯塔的计算结果,当缓存超时后,要重新从灯塔拉取相应数据。
灯塔的职责:
1,依据客户端IP和主机接入点IP,前往最优的接入点列表,包括IP的排序,以及客户端接入的国度、省份、运营商、APN和网关。
Tcaplus的职责:
1,保管接入的IP列表和端口、静态战略,或缓存灯塔的计算结果;
关键的流程:
客户端批量解析域名流程
1,TGCP以APN和域名列表为关键字查询缓存,假设存在且没有过时,则直接把IP前往给用户。 假设指定强迫解析域名列表,则跳过此步骤; 2,TGCP用预性能或缓存的IP向DNSvr发起查询恳求,假设成功前往结果,则执行步骤3,否则,重试IP列表中的其它IP,假设都失败,则用域名访问DNSvr。 留意:假设是结果格式不正确,则经常使用上次的IP重试,不要改换IP重试。 3,DNSvr比拟客户端IP列表和以后最新的IP列表的MD5,假设相等,则通知客户端不要求更新本地缓存。 否则,TGCP把接入主机和DNSvr的IP列表写入本地。 留意:在访问主机时,这些IP的优先级要高于静态性能在客户端的IP。
客户端经常使用域名访问主机流程
1,假设本地存在有效的IP(即存在对应APN的IP列表,且没有失效),则经常使用IP访问主机。 2,否则,发起“客户端批量解析域名流程”后,再访问主机。
主机接入tconnd主动上报形态流程:
1,Tconnd周期性向DNSvr上报心跳信息,其中包括本接入点能否可用的信息。 2,DNSvr在一定的时期内没有收到心跳信息或许相应的接入点无法用,则把相应的IP和端口拉黑,黑掉的IP不在下发给客户端。 留意:实践部署的时刻,接入的Tconnd要向多个DNSvr接入tconnd上报。
向客户端主动push接入点列表的流程
1,当TGCP衔接到主机接入的Tconnd时,Tconnd要向DNSvr发起恳求,以校验以后接入IP的质量和时效性。 假设IP列表出现变化,Tconnd要把最新的IP列表下发给客户端缓存起来。 2,当TGCP下次访问主机时,则经常使用最新的IP列表。
客户端访问DNSvr失败的流程
1,假设访问DNSvr失败(包括IP+域名),假设性能了本地IP,则直接用IP访问主机,否则用域名访问。
优化传输层协议设计
在原有tconnd支持的牢靠UDP的基础之上,参与以下逻辑:
1,数据紧缩; 2,数据加密; 3,兼并多个数据包; 4,支持流式数据传输,便于控制每个UDP包的大小,也便于数据加密和紧缩; 5,可选地支持改良的拥塞控制算法; 6,即使没有接纳到ACK包,也要求主动重试以发送的数据包;
5.2 Hybird开发下的一些优化 要处置在弱网络下的加载速度,那么我们要先确定一下我们的整个APP在哪个中央加载的速度如何,最长的加载途径在哪里,我们从而才有针对性的启动优化与修正。
5.2.1 WebView 假设是对是APP中内嵌的webview网页,针对网页体验优化曾经由来已久了。我们可以经常使用Chrome的开发者形式,调整到Network形式下,将网络条件设置为3G去恳求网页,那么我们就能够看出来一个网页加载的速度关键都消耗在哪个中央,如下图所示:
当然,html的减速方式有很多种
1,经常使用gulpgrunt启动打包紧缩:jscss资源紧缩,CSS Sprites兼并等。 2,经常使用font-awesome交流图片:字体可以很好的兼容,有限加大,常用的图片都有
plc扫描周期疑问
可编程控制器的任务环节包括两部分:自诊断及通讯照应的固定环节和用户程序执行环节,如图5-1所示。 PLC在每次执行用户程序之前,都先执行缺点自诊断程序、复位、监视、定时等外部固定程序,若自诊断正常,继续向下扫描,然后PLC审核能否有与编程器、计算机等的通讯恳求。 假设有与计算机等的通讯恳求,则启动相应处置。 当PLC处于中止(STOP)形态时,只循环启动前两个环节。 而在PLC处于运转(RUN)形态时,PLC从外部处置、通讯操作、输入扫描、执行用户程序、输入刷新五个任务阶段循环任务。 每成功一次性以上五个阶段所要求的时期称为一个扫描周期。 扫描周期是PLC的一个关键目的,小型PLC的扫描周期普通为十几毫秒到几十毫秒。 PLC的扫描周期长短取决于扫描速度和用户程序的长短。 毫秒级的扫描时期关于普通工业设备通常是支持的,PLC对输入的持久滞后也是支持的。 但对某些I/O加快照应的设备,则应采取相应的处置措施。 如选择高速CPU,提高扫描速度;选择加快照应模块、高速计数模块以及不同的终止处置等措施增加滞后时期。 关于用户来说,要提高编程才干,尽或许优化程序;而在编写大型设备的控制程序时,尽量增加程序长度,选择分支或跳步程序等,都可以增加用户程序执行时期。
我想失掉::站内搜索到信息的资料并将其分页..怎样试都不能将所失掉的信息分页,哪为高手指点,,,,
嘿嘿 我最近也正在做 查询的分页显示 给你我看的资料吧当然是从数据库来的 不然呢 1、前言 分页显示是一种十分经常出现的阅读和显示少量数据的方法,属于web编程中最常处置的事情之一。 关于web编程的新手来说,编写这种代码真实是和呼吸一样自然,但是关于初学者来说,经常对这个疑问摸不着眉目,因此特别撰写此文对这个疑问启动详细的解说,力图让看完这篇文章的好友在看完以后关于分页显示的原理和成功方法有所了解。 本文适宜初学者阅读,一切示例代码均经常使用php编写。 2、原理 所谓分页显示,也就是将数据库中的结果集人为的分红一段一段的来显示,这里要求两个初始的参数: 每页多少条记载($PageSize)? 以后是第几页($CurrentPageID)? 如今只需再给我一个结果集,我就可以显示某段特定的结果出来。 至于其他的参数,比如:上一页($PreviousPageID)、下一页($NextPageID)、总页数($numPages)等等,都可以依据前边这几个东西失掉。 以mysql数据库为例,假设要从表内截取某段内容,sql语句可以用:select * from table limit offset, rows。 看看上方一组sql语句,尝试一下发现其中的规率。 前10条记载:select * from table limit 0,10 第11至20条记载:select * from table limit 10,10 第21至30条记载:select * from table limit 20,10 …… 这一组sql语句其实就是当$PageSize=10的时刻取表内每一页数据的sql语句,我们可以总结出这样一个模板: select * from table limit ($CurrentPageID - 1) * $PageSize, $PageSize 拿这个模板代入对应的值和上边那一组sql语句对照一下看看是不是那么回事。 搞定了最关键的如何失掉数据的疑问以后,剩下的就仅仅是传递参数,结构适宜的sql语句然后经常使用php从数据库内失掉数据并显示了。 以下我将用详细代码加以说明。 3、简易代码 请详细阅读以下代码,自己调试运转一次性,最好把它修正一次性,加上自己的性能,比如搜索等等。 <?php // 树立数据库衔接 $link = mysql_connect(localhost, mysql_user, mysql_password) or die(Could not connect: . mysql_error()); // 失掉以后页数 if( isset($_GET[page]) ){ $page = intval( $_GET[page] ); } else{ $page = 1; } // 每页数量 $PageSize = 10; // 失掉总数据量 $sql = select count(*) as amount from table; $result = mysql_query($sql); $row = mysql_fetch_row($result); $amount = $row[amount]; // 记算总共有多少页 if( $amount ){ if( $amount < $page_size ){ $page_count = 1; } //假设总数据量小于$PageSize,那么只要一页 if( $amount % $page_size ){ //取总数据量除以每页数的余数 $page_count = (int)($amount / $page_size) + 1; //假设缺乏数,则页数等于总数据量除以每页数的结果取整再加一 }else{ $page_count = $amount / $page_size; //假设没缺乏数,则页数等于总数据量除以每页数的结果 } } else{ $page_count = 0; } // 翻页链接 $page_string = ; if( $page == 1 ){ $page_string .= 第一页|上一页|; } else{ $page_string .= <a href=/?page=1>;第一页</a>|<a href=/?page=.($page-1).>上一页</a>|; } if( ($page == $page_count) || ($page_count == 0) ){ $page_string .= 下一页|尾页; } else{ $page_string .= <a href=/?page=.($page+1).>下一页</a>|<a href=/?page=.$page_count.>尾页</a>; } // 失掉数据,以二维数组格式前往结果 if( $amount ){ $sql = select * from table order by id desc limit . ($page-1)*$page_size ., $page_size; $result = mysql_query($sql); while ( $row = mysql_fetch_row($result) ){ $rowset[] = $row; } }else{ $rowset = array(); } // 没有包括显示结果的代码,那不在讨论范围,只需用foreach就可以很简易的用失掉的二维数组来显示结果 ?> 4、OO品格代码 以下代码中的数据库衔接是经常使用的pear db类启动处置 <?php // FileName: // 分页类,这个类仅仅用于处置数据结构,不担任处置显示的任务 Class Pager { var $PageSize; //每页的数量 var $CurrentPageID; //以后的页数 var $NextPageID; //下一页 var $PreviousPageID; //上一页 var $numPages; //总页数 var $numItems; //总记载数 var $isFirstPage; //能否第一页 var $isLastPage; //能否最后一页 var $sql; //sql查询语句 function Pager($option) { global $db; $this->_setOptions($option); // 总条数 if ( !isset($this->numItems) ) { $res = $db->query($this->sql); $this->numItems = $res->numRows(); } // 总页数 if ( $this->numItems > 0 ) { if ( $this->numItems < $this->PageSize ){ $this->numPages = 1; } if ( $this->numItems % $this->PageSize ) { $this->numPages= (int)($this->numItems / $this->PageSize) + 1; } else { $this->numPages = $this->numItems / $this->PageSize; } } else { $this->numPages = 0; } switch ( $this->CurrentPageID ) { case $this->numPages == 1: $this->isFirstPage = true; $this->isLastPage = true; break; case 1: $this->isFirstPage = true; $this->isLastPage = false; break; case $this->numPages: $this->isFirstPage = false; $this->isLastPage = true; break; default: $this->isFirstPage = false; $this->isLastPage = false; } if ( $this->numPages > 1 ) { if ( !$this->isLastPage ) { $this->NextPageID = $this->CurrentPageID + 1; } if ( !$this->isFirstPage ) { $this->PreviousPageID = $this->CurrentPageID - 1; } } return true; } /*** * * 前往结果集的数据库衔接 * 在结果集比拟大的时刻可以直接经常使用这个方法取得数据库衔接,然后在类之外遍历,这样开支较小 * 假设结果集不是很大,可以直接经常使用getPageData的方式失掉二维数组格式的结果 * getPageData方法也是调用本方法来失掉结果的 * ***/ function getDataLink() { if ( $this->numItems ) { global $db; $PageID = $this->CurrentPageID; $from = ($PageID - 1)*$this->PageSize; $count = $this->PageSize; $link = $db->limitQuery($this->sql, $from, $count); //经常使用Pear DB::limitQuery方法保证数据库兼容性 return $link; } else { return false; } } /*** * * 以二维数组的格式前往结果集 * ***/ function getPageData() { if ( $this->numItems ) { if ( $res = $this->getDataLink() ) { if ( $res->numRows() ) { while ( $row = $res->fetchRow() ) { $result[] = $row; } } else { $result = array(); } return $result; } else { return false; } } else { return false; } } function _setOptions($option) { $allow_options = array( PageSize, CurrentPageID, sql, numItems ); foreach ( $option as $key => $value ) { if ( in_array($key, $allow_options) && ($value != null) ) { $this->$key = $value; } } return true; } } ?> <?php // FileName: test_ // 这是一段简易的示例代码,前边省略了经常使用pear db类树立数据库衔接的代码 require ; if ( isset($_GET[page]) ) { $page = (int)$_GET[page]; } else { $page = 1; } $sql = select * from table order by id; $pager_option = array( sql => $sql, PageSize => 10, CurrentPageID => $page ); if ( isset($_GET[numItems]) ) { $pager_option[numItems] = (int)$_GET[numItems]; } $pager = @new Pager($pager_option); $data = $pager->getPageData(); if ( $pager->isFirstPage ) { $turnover = 首页|上一页|; } else { $turnover = <a href=?page=1&numItems=.$pager->numItems.>首页</a>|<a href=/?page=.$pager->PreviousPageID.&numItems=.$pager->numItems.>上一页</a>|; } if ( $pager->isLastPage ) { $turnover .= 下一页|尾页; } else { $turnover .= <a href=/?page=.$pager->NextPageID.&numItems=.$pager->numItems.>下一页</a>|<a href=/?page=.$pager->numPages.&numItems=.$pager->numItems.>尾页</a>; } ?> 要求说明的中央有两个: 这个类仅仅处置数据,并不担任处置显示,由于我觉得将数据的处置和结果的显示都放到一个类里边真实是有些勉强。 显示的时刻状况和要求多变,不如自己依据类给出的结果处置,更好的方法是依据这个Pager类承袭一个自己的子类来显示不同的分页,比如显示用户分页列表可以: <?php Class MemberPager extends Pager { function showMemberList() { global $db; $data = $this->getPageData(); // 显示结果的代码 // ...... } } /// 调用 if ( isset($_GET[page]) ) { $page = (int)$_GET[page]; } else { $page = 1; } $sql = select * from members order by id; $pager_option = array( sql => $sql, PageSize => 10, CurrentPageID => $page ); if ( isset($_GET[numItems]) ) { $pager_option[numItems] = (int)$_GET[numItems]; } $pager = @new MemberPager($pager_option); $pager->showMemberList(); ?> 第二个要求说明的中央就是不同数据库的兼容性,在不同的数据库里截获一段结果的写法是不一样的。 mysql: select * from table limit offset, rows pgsql: select * from table limit m offset n ...... 所以要在类里边失掉结果的时刻要求经常使用pear db类的limitQuery方法。 ok,写完收功,希望花时期看完这些文字的你不觉得是糜费了时期。 回答者:ljpbxh027 - 护国法师 十四级 5-26 10:10<? if (!$page) { $page=1; } $sqldo=select count(*) as title from $tzdyyinfo; $result=mysql_query($sqldo); $message_count=mysql_result($result,0,title); $page_count=ceil($message_count/$page_size); $offset=($page-1)*$page_size; $strdo=select id,ybname,yblb,ybyy,ybip,ybzy,ybtime,ybinfo,ybtbadd from $tzdyyinfo order by ybtime desc limit $offset, $page_size; $result=mysql_query($strdo,$myconn); while($row=mysql_fetch_array($result)) { ?> <table border=0 cellpadding=0 cellspacing=0> <tr> <td>________________</td> </tr> </table> <? } ?> <? //以下是上一页下一页的代码 if($result) { $prev_page=$page-1; $next_page=$page+1; echo <p align=\center\>| ; if ($page<=1){ echo 第一页 | ; } else{ echo <a href=$PATH_INFO?page=1>第一页</a> | ; } if ($prev_page<1){ echo 上一页 | ; } else{ echo <a href=$PATH_INFO?page=$prev_page>上一页</a> | ; } if ($next_page>$page_count){ echo 下一页 | ; } else{ echo <a href=$PATH_INFO?page=$next_page>下一页</a> | ; } if ($page>=$page_count){ echo 最后一页 |</p>\n; } else{ echo <a href=$PATH_INFO?page=$page_count>最后一页</a> |</p>\n; } } ?> 这样就可以了
版权声明
本文来自网络,不代表本站立场,内容仅供娱乐参考,不能盲信。
未经许可,不得转载。