导读:EPON和GPON各有千秋,从性能指标上GPON要优于EPON,但是EPON拥有了时间和成本上的优势,GPON正在迎头赶上,展望未来的宽带接入市场也许并非谁替代谁, 应该是共存互补。对于带宽、多业务,QoS和安全性要求较高以及ATM技术 作为骨干网的客户,GPON会更加适合。 什么是PON?宽带接入技术风起云涌,注定成为一块硝烟永远不会散去的战场。目前国内占主流仍然是ADSL技术,不过越来越多的设备厂商及运营商已经把目光投向了光网络接入技术。 铜价不断攀升,光缆价格不断下降,不断增长的IPTV, 视频游戏业务对带宽的巨大需求推动着FTTH的发展。由光缆取代铜缆及有线同轴电缆,电话,有线电视,宽带数据三网合一的美好前景变的清晰起来。 图一:PON 拓扑结构 PON(Passive Optical Network)无源光网络是实现FTTH光纤到户的主要技术,提供点到多点的光纤接入,如图一所示,它由局侧的OLT(光线路终端)、用户侧的ONU(光网络单元)以及ODN(光分配网络)组成。一般其下行采用TDM广播方式、上行采用TDMA(时分多址接入)方式,组成点到多点树形拓扑结构。PON作为光接入技术最大的亮点是“无源”,ODN中不含有任何有源电子器件及电子电源,全部由光分路器(Splitter)等无源器件组成,管理维护运营成本较低。 PON发展史 PON技术研究起源于1995年,1998年10月,ITU通过了FSAN组织(全业务接入网)所倡导的基于ATM的PON技术标准——G。983。也被称为BPON(BroadbandPON)。速率为155Mbps,可选择支持622Mbps速率。 EFMA(Ethernetin the First Mile Alliance,第一英里以太网联盟)于2000年底提出了Ethernet-PON(EPON)的概念,传输速率达1Gbps,链路层基于简单的Ethernet 装。 GPON(Gigabit-CapablePON)由FSAN组织于2002年9月提出,2003年3月ITU通过了G。984。1和G。984。2协议。G。984。1对GPON接入系统的总体特性进行了规定;G。984。2对GPON的ODN(Optical Distribution Network)物理媒质相关子层进行了规定;2004年6月ITU又通过了G。984。3,它对传输汇聚(TC)层的相关要求进行了规定。 EPON和GPON产品比较 EPON和GPON作为光网络接入的两个主力成员,各有千秋,互有竞争,互有补充,互有借鉴,下面在各个方面对它们作个比较: 速率 EPON提供固定上下行1。25Gbps,采用8b/10b线路编码,实际速率为1Gbps。 GPON支持多种速率等级,可以支持上下行不对称速率,下行2.5Gbps或1.25Gbps,上行1.25Gbps或622Mbps,根据实际需求来决定上下行速率,选择相对应光模块,提高光器件速率价格比。 本项结论:GPON优于EPON。 分路比 分路比即一个OLT端口(局端)带多少个ONU(用户端)。 EPON标准定义分路比1:32。 GPON标准定义分路比下列几种1:32;1:64;1:128 其实,技术上EPON系统也可以做到更高的分路比,如1:64,1:128,EPON的控制协议可以支持更多的ONU。分路比主要是受光模块性能指标的限制,大的分路比会造成光模块成本大幅度上升;另外,PON插入损失15~18dB,大的分路比会降低传输距离;过多的用户分享带宽也是大分路比的代价。 本项结论:GPON提供多选择性,但是成本上考虑优势并不明显最大传送距离GPON系统可支持的最大物理距离,当光分路比为1:16时,应支持20km的最大物理距离;当光分路比为1:32时,应支持10km的最大物理距离。EPON与此相同,本项结论:相等。 QOS(Quality of Service) EPON在MAC层Ethernet包头增加了64字节的MPCP多点控制协议 (multipointcontrolprotocol),MPCP通过消息、状态机和定时器来控制访问P2MP点到多点的拓扑结构,实现DBA动态带宽分配。MPCP涉及的内容包括ONU发送时隙的分配、ONU的自动发现和加入、向高层报告拥塞情况以便动态分配带宽。MPCP提供了对P2MP拓扑架构的基本支持,但是协议中并没有对业务的优先级进行分类处理,所有的业务随机的竞争着带宽,GPON则拥有更加完善的DBA,具有优秀QoS服务能力。 GPON将业务带宽分配方式分成4种类型,优先级从高到低分别是固定带宽(Fixed)、保证带宽(Assured)、非保证带宽(Non-Assured)和尽力而为带宽(BestEffort)。DBA又定义了业务容器(trafficcontainer,T-CONT)作为上行流量调度单位,每个T-CONT由Alloc-ID标识。每个T-CONT可包含一个或多个GEMPort-ID。T-CONT分为5种业务类型,不同类型的T-CONT具有不同的带宽分配方式,可以满足不同业务流对时延、抖动、丢包率等不同的QoS要求。T-CONT类型1的特点是固定带宽固定时隙,对应固定带宽(Fixed)分配,适合对时延敏感的业务,如话音业务;类型2的特点是固定带宽但时隙不确定,对应保证带宽(Assured)分配,适合对抖动要求不高的固定带宽业务,如视频点播业务;类型3的特点是有最小带宽保证又能够动态共享富余带宽,并有最大带宽的约束,对应非保证带宽(Non-Assured)分配,适合于有服务保证要求而又突发流量较大的业务,如下载业务;类型4的特点是尽力而为(BestEffort),无带宽保证,适合于时延和抖动要求不高的业务,如WEB浏览业务;类型5是组合类型,在分配完保证和非保证带宽后,额外的带宽需求尽力而为进行分配。 本项结论:GPON优于EPON 运营、维护OAM EPON没有对OAM进行过多的考虑,只是简单的定义了对ONT远端故障指示、环回和链路监测,并且是可选支持。 GPON在物理层定义了PLOAM(PhysicalLayerOAM),高层定义了OMCI(ONTManagementandControlInterface),在多个层面进行OAM管理。PLOAM用于实现数据加密、状态检测、误码监视等功能。OMCI信道协议用来管理高层定义的业务,包括ONU的功能参数集、T-CONT业务种类与数量、QoS参数,请求配置信息和性能统计,自动通知系统的运行事件,实现OLT对ONT的配置、故障诊断、性能和安全的管理。 本项结论:GPON优于EPON 链路层 装和多业务支持 如图二所示,EPON沿用了简单的以太网数据格式,只是在以太网包头增加了64字节的MPCP点到多点控制协议来实现EPON系统中的带宽分配,带宽轮讯,自动发现,测距等工作。对于数据业务以外的业务(如TDM同步业务)的支持没有作过多研究,很多EPON厂家开发了一些非标准的产品来解决这个问题,但是都不理想,很难满足电信级的QoS要求。 GPON基于完全新的传输融合(TC)层,该子层能够完成对高层多样性业务的适配,如图二所示,定义了ATM 装和GFP 装(通用成帧协议),可以选择二者之一进行业务 装。鉴于目前ATM应用并不普及,于是一种只支持GFP 装的GPON。lite设备应运而生,它把ATM从协议栈中去除以降低成本。 GFP是一种通用的适用于多种业务的链路层规程,ITU定义为G。7041。GPON中对GFP作了少量的修改,在GFP帧的头部引入了PortID,用于支持多端口复用;还引入了Frag(Fragment)分段指示以提高系统的有效带宽。并且只支持面向变长数据的数据处理模式而不支持面向数据块的数据透明处理模式,GPON具有强大的多业务承载能力。GPON的TC层本质上是同步的,使用了标准的8kHz(125μm)定长帧,这使GPON可以支持端到端的定时和其他准同步业务,特别是可以直接支持TDM业务,就是所谓的NativeTDM,GPON对TDM业务具备“天然”的支持。 本项结论:对多业务的支持GPON的TC层要比EPON的MPCP强大。 图二:GPON与EPON协议栈比较 网络层次GPONEPON L3ATMTDMIPTDMIP L2ETHERNETETHERNET WITH MPCP GFP L1PON-PHYPON-PHY 结语 EPON和GPON各有千秋,从性能指标上GPON要优于EPON,但是EPON拥有了时间和成本上的优势,GPON正在迎头赶上,展望未来的宽带接入市场也许并非谁替代谁,应该是共存互补。对于带宽、多业务,QoS和安全性要求较高以及ATM技术作为骨干网的客户,GPON会更加适合。而对于成本敏感,QoS,安全性要求不高的客户群,EPON成为主导。 编 辑:初夏 from:http://www.cctime.com/html/2015-4-20/2015420936287107.htm
View Details以下所列是我在这些年来软件开发工作过程中受到的启发,还有总结而来的好经验。 开发 从小事做起,然后再扩展 无论是创建一个新的系统,还是在现有的系统中添加新的功能,我总是从一个简单到几乎没有任何所需功能的版本开始,然后再一步一步地解决问题,直到满意为止。我从来没有妄想过能够一步登天。相反,我一边开发一边学习,同时新掌握的信息还可以用于解决方案中。 我很喜欢 John Gall 的这句话: “复杂系统总是源于简单系统的演化。” 2. 一次只做一件事 当我们在开发时,碰到测试失败和功能无效的情况,如果你一次只研究一个问题,那将会更容易找到问题的关键。换言之,就是使用短迭代。必须确保这个问题解决之后,再转移到另一个问题上。这适用于向下提交。如果在你添加新功能之前需要先重构代码,那么先提交重构,然后再添加新的功能。 3. 尽早地添加日志和错误处理 在开发新系统时,我做的第一件事就是添加日志和错误处理,因为这两者从一开始就非常有用。对系统来说它比一大把代码更有用,你需要一些了解程序状态的方法。如果系统不能照常工作,那么你就需要知道程序中发生了什么——这是日志的作用。错误处理也是如此——错误和异常越早处理越好。 4. 每一行新代码必须至少执行一次 在你真正完成一个功能之前,你必须对它进行测试。不然,你怎么知道它是不是按照你的想法在执行呢?通常情况下,最好的方法是通过自动测试,但并非总是如此。不过,不管怎么说,每一行新代码必须至少执行一次。 一般,我们想触发某种条件很难。但幸运的是,我们可以作弊。例如,数据的错误处理可以通过临时拼写错一个列名来触发。或者,一个if语句可以暂时颠倒过来(从 if error 变成 if not error),这样来触发那些平时很难触发的条件,这样只是为了确定代码是否正常运行和它会出现什么结果。 有时,我发现有一些行代码永远都不会被运行。当我们做代码检查是它看起来没有什么问题,但就是不工作。你要避免这样的尴尬状况,如果你想你的每一行新代码都会被执行。 5. 在整体测试之前先进行模块测试 先进行部分模块测试可以节省时间。通常说来,我们在整合不同的模块时也会出现问题,例如模块之间的接口不匹配。但是如果我们能够信任各个组件的话,那么跟踪集成问题就会变得简单得多。 6. 所有事情所花费的时间总是比你预期的要长 特别是在编程中,即使一切进展顺利,我们也很难对功能所需的时间做出正确的预算。并且,开发软件时碰到各种意想不到的问题是非常常见的。一个简单的合并操作会导致一系列小bug,一次框架升级意味着一些函数必须改变或者一些API不按照你想象的那样工作。 Hofstadter Law( 霍夫施塔特定律)其实道出了真谛:做事所花费的时间总是比你预期的要长,即使你在预期中已经考虑了 Hofstadter Law( 霍夫施塔特定律)。 7. 先了解现有的代码 大多数的编码都需要以某种方式改变现有的代码。即使是新功能,也需要适应现有的程序。所以,在你加进去新的内容前,首先需要了解当前的解决方案。否则,你一不小心就很有可能会打破现有的功能。这意味着,阅读代码和编写代码都是必要的技能。这也是为什么看似微小的变化仍可能需要很长时间才能解决的原因之一,因为你首先必须了解上下文。 8. 阅读和运行代码 幸运的是,对于理解代码,我们有两种互补的方法。你可以阅读代码,也可以运行代码。运行代码的确是个非常棒的好方法。所以,请确保充分利用这两种方法。 故障排除 9. Bug 总是难免的 我不喜欢那些宣称软件开发可以“一蹴而就”的高谈阔论。不论你再怎么努力,bug总是难免的(BUG的定义基本上是:“我们没有想到”)。最好能够做成可以快速故障排除、修复bug和部署修复的系统。 10. 解决故障报告 每个开发人员都应该花时间去处理来自客户的故障报告,并修复bug。这能让你更好地理解客户的意图,明白如何使用系统,知道排除故障的难易程度,了解系统的设计情况。这也是为自己的开发成果负责的好方法。不要错过这些好处。 11. 重现问题 修复bug的第一步就是重现问题。然后你得确保修复之后,问题能够彻彻底底地消失。这样一个简单的规则,可以确保你不会误将非问题当作是问题,并确保解决方案真的能够奏效。 12. 修复已知错误,然后再看看有没有其他不对的地方 有时候,可能同时存在着几个不同的问题。它们之间的互相作用,可能会让你毫无头绪,束手无策。不要纠结于搞清楚发生了什么,先去解决所有已知的问题,然后再看看还有什么不对的地方。 13. 没有巧合 在测试和故障排除时,不要相信会出现什么巧合。就像你改变了定时器的值,那么就会改变系统重启的频率。所以一切都并非是巧合。添加新功能,另一个不相干的功能变慢了?这绝对不是巧合。相反,是你应该仔细调查的内容。 14. 关联时间戳 在故障排除时,事件的时间戳可以作为你的好帮手。寻找偶数增量。例如,如果系统重启了,并且刚刚发出过一个3000毫秒左右的请求,那么可能是触发了某个定时器,才导致出现重启的动作。 合作 15. 面对面的交流最有效 当我们需要讨论如何解决问题时,那么面对面的交流比视频、打电话和电子邮件都要好。我经常在与同事讨论完后发现一个令人兴奋的更好的方案。 16. 小黄鸭调试法 遇到你绞尽脑汁也解决不了的问题时,不妨找一个同事,然后将问题解释给他们听。很多时候,当你在叙述时,即使你的同事一言不发,你可能也会突然灵光乍现找到问题的关键。听起来像魔法,但是这经常起作用。详情看这篇文章:《小黄鸭调试法,每个程序员都要知道的》 17. 问问题 阅读和运行代码往往非常有助于指出代码的目的和它的工作原理。但是如果你有机会咨询那些更为了解的人(例如原来的程序员),那么千万不要错过。继续问他们具体的问题、后续的问题,这几分钟内给你的信息可能是你需要花费好几天才能获得的。 18. 共享荣誉 不要贪图荣誉,该是谁的就是谁的。例如:“Marcus 想出了这个主意……”(如果真是他想的话),而不要说“我们想出的……”。大胆的说出那些帮助过你或者贡献过力量的人的名字。 其他 19. 动手去做 如果你不知道某种编程语言功能的工作原理,那么不妨写一个小程序来理解它是如何工作的。这同样适用于测试你正在开发的系统。如果我将参数设置为-1,会发生什么?当我在重启系统时,如果服务当掉,会发生什么?以此来研究它的工作原理。经常做这些会帮你发现bug,在此同时也会加深你的系统工作的了解。 20. 带着问题睡觉 如果你正在解决一个很难的问题,那么不妨带着问题睡觉。有科学研究表明,这样做虽然你表明上并没有在主动思考,但你的潜意思却这么做了。其结果就是,第二天再去研究问题,解决方案已经呼之欲出了。 21. 改变/跳槽 不要害怕角色变化。和不同的人共事,开发不同的产品,感受不同的公司文化是非常有意思的。在我看来,太多的人只是被动地呆在同样的地方年复一年的工作,只有在被迫的情况下才去改变。 22. 活到老学到老 软件行业的一大魅力就是我们随时有机会可以学到新的东西。你可以尝试不同的编程语言和工具,阅读软件开发的书籍,接受MOOC课程。相信我,量变才能达到质的飞跃,这些小小的学习积累,终有一天会大大地提高你的知识和能力。 […]
View Details一、React的家世背景 React 起源于 Facebook 的内部项目,因为该公司对市场上所有 JavaScript MVC 框架,都不满意,就决定自己写一套,用来架设Instagram 的网站。做出来以后,发现这套东西很好用,就在2013年5月开源了。 Facebook的设计理念是独立、小巧、快速、创新,而React的特点也正说明了这一点。 二、React 更“轻”的MDV框架 先来说一下什么是MDV吧,MDV即Model Driven View,根据model动态生成view。MDV框架将程序员从传统手动渲染dom节点和事件绑定中解放了出来,大大提高了开发效率。 React更“轻”,这个"更"是有对比含义的,相对于AngularJs的双向数据流,ReactJs的单向数据流显然是更轻量级,而且React维护自己的VTree(虚拟Dom树),可以更快的渲染dom节点。据说,react渲染的界面,fps可以保持在60左右,这一点使得react特别适合于制作游戏。在react刚推出的时候,有测试指出react的性能要比angular高20%左右。 但是,AngularJs的数据交互可以双向进行,可以用于CURD,应用易于接受用户的自定义以及个人数据。当然, 毕竟 React是用于“render”的,view中最关键的是管理组件状态变化,而React在这一点上做的比AngularJs好很多。 在React中,对象的状态使用this.state表示,对象的初始状态设置使用getInitialState,设置状态使用setState,数据使用props管理,DOM操作和事件监听则类似于jquery。 三、使用React制作简易悬浮框 index.html
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
<span class="hljs-doctype"><!DOCTYPE html></span> <span class="hljs-tag"><<span class="hljs-title">html</span>></span> <span class="hljs-tag"><<span class="hljs-title">head</span>></span> <span class="hljs-tag"><<span class="hljs-title">meta</span> <span class="hljs-attribute">charset</span>=<span class="hljs-value">"utf-8"</span>></span> <span class="hljs-tag"><<span class="hljs-title">title</span>></span><span class="hljs-tag"></<span class="hljs-title">title</span>></span> <span class="hljs-tag"><<span class="hljs-title">link</span> <span class="hljs-attribute">rel</span>=<span class="hljs-value">"stylesheet"</span> <span class="hljs-attribute">type</span>=<span class="hljs-value">"text/css"</span> <span class="hljs-attribute">href</span>=<span class="hljs-value">"bootstrap/bootstrap.min.css"</span>></span> <span class="hljs-tag"><<span class="hljs-title">link</span> <span class="hljs-attribute">rel</span>=<span class="hljs-value">"stylesheet"</span> <span class="hljs-attribute">type</span>=<span class="hljs-value">"text/css"</span> <span class="hljs-attribute">href</span>=<span class="hljs-value">"css/style.css"</span>></span> <span class="hljs-tag"></<span class="hljs-title">head</span>></span> <span class="hljs-tag"><<span class="hljs-title">body</span>></span> <span class="hljs-tag"><<span class="hljs-title">div</span> <span class="hljs-attribute">id</span>=<span class="hljs-value">"container"</span>></span><span class="hljs-tag"></<span class="hljs-title">div</span>></span> <span class="hljs-tag"><<span class="hljs-title">div</span> <span class="hljs-attribute">id</span>=<span class="hljs-value">"layer"</span>></span><span class="hljs-tag"></<span class="hljs-title">div</span>></span> <span class="hljs-tag"></<span class="hljs-title">body</span>></span> <span class="hljs-tag"><<span class="hljs-title">script</span> <span class="hljs-attribute">type</span>=<span class="hljs-value">"text/javascript"</span> <span class="hljs-attribute">src</span>=<span class="hljs-value">"ReactJs/react.min.js"</span>></span><span class="hljs-tag"></<span class="hljs-title">script</span>></span> <span class="hljs-tag"><<span class="hljs-title">script</span> <span class="hljs-attribute">type</span>=<span class="hljs-value">"text/javascript"</span> <span class="hljs-attribute">src</span>=<span class="hljs-value">"ReactJs/react-dom.min.js"</span>></span><span class="hljs-tag"></<span class="hljs-title">script</span>></span> <span class="hljs-tag"><<span class="hljs-title">script</span> <span class="hljs-attribute">type</span>=<span class="hljs-value">"text/javascript"</span> <span class="hljs-attribute">src</span>=<span class="hljs-value">"ReactJs/browser.min.js"</span>></span><span class="hljs-tag"></<span class="hljs-title">script</span>></span> <span class="hljs-tag"><<span class="hljs-title">script</span> <span class="hljs-attribute">type</span>=<span class="hljs-value">"text/javascript"</span> <span class="hljs-attribute">src</span>=<span class="hljs-value">"jquery/jquery.min.js"</span>></span><span class="hljs-tag"></<span class="hljs-title">script</span>></span> <span class="hljs-tag"><<span class="hljs-title">script</span> <span class="hljs-attribute">type</span>=<span class="hljs-value">"text/babel"</span> <span class="hljs-attribute">src</span>=<span class="hljs-value">"js/common.js"</span>></span><span class="hljs-tag"></<span class="hljs-title">script</span>></span> <span class="hljs-tag"></<span class="hljs-title">html</span>></span> |
style.css
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
<span class="hljs-id">#modal</span><span class="hljs-rules">{ <span class="hljs-rule"><span class="hljs-attribute">width</span>:<span class="hljs-value"><span class="hljs-number">400px</span></span></span>; <span class="hljs-rule"><span class="hljs-attribute">height</span>:<span class="hljs-value"><span class="hljs-number">210px</span></span></span>; <span class="hljs-rule"><span class="hljs-attribute">margin-left</span>:<span class="hljs-value"> auto</span></span>; <span class="hljs-rule"><span class="hljs-attribute">margin-right</span>:<span class="hljs-value"> auto</span></span>; <span class="hljs-rule"><span class="hljs-attribute">padding-left</span>:<span class="hljs-value"><span class="hljs-number">10px</span></span></span>; <span class="hljs-rule"><span class="hljs-attribute">padding-right</span>:<span class="hljs-value"><span class="hljs-number">10px</span></span></span>; <span class="hljs-rule"><span class="hljs-attribute">border</span>:<span class="hljs-value"><span class="hljs-number">1px</span> solid <span class="hljs-hexcolor">#999</span></span></span>; <span class="hljs-rule"><span class="hljs-attribute">border-radius</span>:<span class="hljs-value"> <span class="hljs-number">10px</span></span></span>; <span class="hljs-rule"><span class="hljs-attribute">background-color</span>:<span class="hljs-value"> <span class="hljs-hexcolor">#fff</span></span></span>; <span class="hljs-rule"><span class="hljs-attribute">display</span>:<span class="hljs-value">none</span></span>; <span class="hljs-rule">}</span></span> <span class="hljs-id">#modal</span> <span class="hljs-class">.btn</span><span class="hljs-rules">{ <span class="hljs-rule"><span class="hljs-attribute">float</span>:<span class="hljs-value">right</span></span>; <span class="hljs-rule"><span class="hljs-attribute">margin-right</span>:<span class="hljs-value"><span class="hljs-number">10px</span></span></span>; <span class="hljs-rule">}</span></span> <span class="hljs-id">#layer</span><span class="hljs-rules">{ <span class="hljs-rule"><span class="hljs-attribute">width</span>:<span class="hljs-value"><span class="hljs-number">100%</span></span></span>; <span class="hljs-rule"><span class="hljs-attribute">height</span>:<span class="hljs-value"><span class="hljs-number">100%</span></span></span>; <span class="hljs-rule"><span class="hljs-attribute">position</span>:<span class="hljs-value">fixed</span></span>; <span class="hljs-rule"><span class="hljs-attribute">top</span>:<span class="hljs-value"><span class="hljs-number">0</span></span></span>; <span class="hljs-rule"><span class="hljs-attribute">left</span>:<span class="hljs-value"><span class="hljs-number">0</span></span></span>; <span class="hljs-rule"><span class="hljs-attribute">z-index</span>:<span class="hljs-value">-<span class="hljs-number">1</span></span></span>; <span class="hljs-rule">}</span></span> |
common.js (React创建组件)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 |
<span class="hljs-keyword">var</span> BootstrapButton=React.createClass({ render:<span class="hljs-function"><span class="hljs-keyword">function</span><span class="hljs-params">()</span></span>{ <span class="hljs-keyword">return</span> ( <span class="xml"><span class="hljs-tag"><<span class="hljs-title">a</span> {<span class="hljs-attribute">...this.props</span>} <span class="hljs-attribute">href</span>=<span class="hljs-value">"javascript:;"</span> <span class="hljs-attribute">role</span>=<span class="hljs-value">"button"</span> <span class="hljs-attribute">className</span>=<span class="hljs-value">{'btn</span> '+<span class="hljs-attribute">this.props.className</span>}/></span> )</span>; } }); <span class="hljs-keyword">var</span> BootstrapModal=React.createClass({ render:<span class="hljs-function"><span class="hljs-keyword">function</span><span class="hljs-params">()</span></span>{ <span class="hljs-keyword">return</span> ( <span class="xml"><span class="hljs-tag"><<span class="hljs-title">div</span> <span class="hljs-attribute">id</span>=<span class="hljs-value">"modal"</span> <span class="hljs-attribute">ref</span>=<span class="hljs-value">"root"</span>></span> <span class="hljs-tag"><<span class="hljs-title">h1</span>></span>Hello world<span class="hljs-tag"></<span class="hljs-title">h1</span>></span> <span class="hljs-tag"><<span class="hljs-title">hr</span>/></span> <span class="hljs-tag"><<span class="hljs-title">p</span>></span>This is a test!<span class="hljs-tag"></<span class="hljs-title">p</span>></span> <span class="hljs-tag"><<span class="hljs-title">hr</span>/></span> <span class="hljs-tag"><<span class="hljs-title">BootstrapButton</span> <span class="hljs-attribute">className</span>=<span class="hljs-value">"btn-primary"</span> <span class="hljs-attribute">onClick</span>=<span class="hljs-value">{this.handleConfirm}</span>></span> Confirm <span class="hljs-tag"></<span class="hljs-title">BootstrapButton</span>></span> <span class="hljs-tag"></<span class="hljs-title">div</span>></span> )</span>; }, handleConfirm:<span class="hljs-function"><span class="hljs-keyword">function</span><span class="hljs-params">()</span></span>{ <span class="hljs-keyword">this</span>.close(); }, open:<span class="hljs-function"><span class="hljs-keyword">function</span><span class="hljs-params">()</span></span>{ $(<span class="hljs-keyword">this</span>.refs.root).show(); $(<span class="hljs-string">"#layer"</span>).css(<span class="hljs-string">"background"</span>,<span class="hljs-string">"rgba(112,112,112,0.6)"</span>); }, close:<span class="hljs-function"><span class="hljs-keyword">function</span><span class="hljs-params">()</span></span>{ $(<span class="hljs-keyword">this</span>.refs.root).hide(); $(<span class="hljs-string">"#layer"</span>).css(<span class="hljs-string">"background"</span>,<span class="hljs-string">"rgba(0,0,0,0)"</span>); } }); <span class="hljs-keyword">var</span> ModalWidget=React.createClass({ render:<span class="hljs-function"><span class="hljs-keyword">function</span><span class="hljs-params">()</span></span>{ <span class="hljs-keyword">return</span>( <span class="xml"><span class="hljs-tag"><<span class="hljs-title">div</span>></span> <span class="hljs-tag"><<span class="hljs-title">BootstrapButton</span> <span class="hljs-attribute">className</span>=<span class="hljs-value">"btn-default"</span> <span class="hljs-attribute">onClick</span>=<span class="hljs-value">{this.showModal}</span>></span> show <span class="hljs-tag"></<span class="hljs-title">BootstrapButton</span>></span> <span class="hljs-tag"><<span class="hljs-title">BootstrapModal</span> <span class="hljs-attribute">ref</span>=<span class="hljs-value">"modal"</span>></span> <span class="hljs-tag"></<span class="hljs-title">BootstrapModal</span>></span> <span class="hljs-tag"></<span class="hljs-title">div</span>></span> )</span>; }, showModal:<span class="hljs-function"><span class="hljs-keyword">function</span><span class="hljs-params">()</span></span>{ {<span class="hljs-keyword">this</span>.refs.modal.open()}; } }); ReactDOM.render(<span class="xml"><span class="hljs-tag"><<span class="hljs-title">ModalWidget</span>/></span>,$("#container")[0]);</span> |
在线演示 from:http://my.oschina.net/lonelydawn/blog/699696
View DetailsChrome 浏览器具有强大的跨平台能力以及丰富的扩展插件,一直是许多开发者的首要选择。而利用许多 Chrome 插件,开发者们在开发流程中能够极大地提高开发效率。我们就整理了十款开发者常用的 Chr Chrome 浏览器具有强大的跨平台能力以及丰富的扩展插件,一直是许多开发者的首要选择。而利用许多 Chrome 插件,开发者们在开发流程中能够极大地提高开发效率。我们就整理了十款开发者常用的 Chrome 插件推荐给大家,相信能够在你的开发中助你一臂之力。 1. 掘金 Chrome 插件:帮你发现干货 不管你是开发者、设计师还是产品经理,想必每天都需要阅读大量的行业相关文章,这就需要我们浏览大量的互联网站点去寻找我们需要的内容。抛开繁复的筛选成本不说,「比特级」的内容都会压得你喘不过气来。 掘金为了解决这个问题,开发了掘金 Chrome 插件,掘金 Chrome 插件聚合了国内外优质的互联网站点内容,在节省你的筛选成本的同时,帮你发现好内容。 2. Postman:强大的 API & HTTP 请求调试工具 相 信 Postman 对于掘金上的各位开发者来说,一定不会陌生,这是一款强大的 API & HTTP 请求调试工具,Postman 不仅可以调试简单的 HTML、CSS 以及脚本等简单的网页基本信息,这款 Chrome 插件甚至还能发送几乎所有的 HTTP 请求,可谓是 Web 开发者的一大利器。 3. BuiltWith Technology Profiler:你的网站,用了什么技术栈? 作为开发者,对于友商网站所使用的技术栈想必也充满了许多好奇心,有没有工具能够帮你完成这项工作呢?答案就是 Chrome 插件 BuiltWith Technology Profiler,它能够帮你分类呈现当前访问网站的技术栈组成,实乃探索友商之利器。 当然,同类产品中,你也可以使用 Wappalyzer 这一款 Chrome 插件。 4. Octotree:你的 GitHub 文档库 GitHub 现有的目录层级形式,在查看来自不同层级文件夹的文件的时候,显得似乎不是很方便,Octotree 这款 Chrome 插件能够让你通过文档库的方式管理、查看你的 GitHub 仓库,简单直观的同时,也方便你进行文件之间的跳转操作。 5. GitHub Awesome Complete:属于 GitHub 的 「Alfred」 在 GitHub 搜索仓库或者项目的时候,你会怎么做?相信大部分人的步骤都是一样的: 在搜索框输入关键字后按回车键 在搜索结果中找到相应结果,点击进入相应页面 有没有更简单快捷的操作方法?答案是 GitHub Awesome Complete 这款 Chrome […]
View Details背景:移动端H5项目,需要实现调用手机拍照,并将图片压缩上传功能。 页面样式: 上传图片有原生的方法<input type="file" accept="image/*">,如果只想要拍照上传,不希望用户选择图片上传,可以通过添加capture属性,该属性值有camcorder/microphone/camera…,此处选择camera。PS:该属性存在浏览器兼容性问题,不是所有的浏览器都支持。
1 |
<input type="file" accept="image/*" capture="camera" > |
因为原生file样式不满足要求,需要进行相应的处理,此时使用定位,在input上面放置我们想要的页面效果。然后当点击上面的元素,就可以触发我们的input进行图片上传。此时的问题是:当点击input上面的元素,需要事件穿透,即相当于点击input。则借助于css3心术新pointer-events。
1 2 3 4 5 |
//使用cursor进行事件穿透,来阻止元素成为鼠标事件的目标 button{ cursor:pointer; pointer-events:none; } |
—-此时图片上传的样式已经处理好了—- 代码片段:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 |
<style > *{ padding: 0; margin: 0; } .wrapper{ width: 320px; height: 50px; margin: 20px auto; position: relative; border: 1px solid #f0f0f0; } input{ width: 100px; height: 30px; } button{ position: absolute; cursor: pointer; pointer-events: none; width: 100px; height: 30px; left: 0; top: 0; } a{ pointer-events: none; } .img{ border: 1px solid #ccc; padding: 10px; } </style > <div class = "wrapper"> <input type = "file" accept= "image/*" capture= "camera" id= "img" /> <button >上传照片 </button > </div > |
图片压缩处理: 因为要做的是手机拍照上传,现在的手机拍照片都很大,比如小米4S,大小在3M以上,如果原图上传,太消耗用户流量,于是要解决图片压缩的问题。 通过change事件,监听图片上传,通过readerAsDataURL获取上传的图片。
1 2 3 4 5 6 7 8 9 10 |
document.getElementById( 'img').addEventListener( 'change', function () { var reader = new FileReader(); reader.onload = function (e) { //调用图片压缩方法:compress(); }; reader.readAsDataURL(this.files[0]); console.log(this.files[0]); var fileSize = Math.round( this.files[0].size/1024/1024) ; //以M为单位 //this.files[0] 该信息包含:图片的大小,以byte计算 获取size的方法如下:this.files[0].size; }, false); |
对上传的图片进行压缩,需要借助于canvas API,调用其中的canvas.toDataURL(type, encoderOptions); 将图片按照一定的压缩比进行压缩,得到base64编码。重点来了:压缩策略:先设置图片的最大宽度 or 最大高度,一般设置其中一个就可以了,因为所有的手机宽高比差别不是很大。然后设置图片的最大size,allowMaxSize,根据图片的实际大小和最大允许大小,设置相应的压缩比率。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 |
//最终实现思路: 1、设置压缩后的最大宽度 or 高度; 2、设置压缩比例,根据图片的不同size大小,设置不同的压缩比。 function compress(res,fileSize) { //res代表上传的图片,fileSize大小图片的大小 var img = new Image(), maxW = 640; //设置最大宽度 img.onload = function () { var cvs = document.createElement( 'canvas'), ctx = cvs.getContext( '2d'); if(img.width > maxW) { img.height *= maxW / img.width; img.width = maxW; } cvs.width = img.width; cvs.height = img.height; ctx.clearRect(0, 0, cvs.width, cvs.height); ctx.drawImage(img, 0, 0, img.width, img.height); var compressRate = getCompressRate(1,fileSize); var dataUrl = cvs.toDataURL( 'image/jpeg', compressRate); document.body.appendChild(cvs); console.log(dataUrl); } img.src = res; } function getCompressRate(allowMaxSize,fileSize){ //计算压缩比率,size单位为MB var compressRate = 1; if(fileSize/allowMaxSize > 4){ compressRate = 0.5; } else if(fileSize/allowMaxSize >3){ compressRate = 0.6; } else if(fileSize/allowMaxSize >2){ compressRate = 0.7; } else if(fileSize > allowMaxSize){ compressRate = 0.8; } else{ compressRate = 0.9; } return compressRate; } |
图片上传给服务器: 图片已经压缩完成了,但是压缩后的图片不是File,而是一个base64编码,于是乎两个选择:1、以String的形式将base64编码上传给服务器,服务器转存base64为img图片;2、前端将base64转为File图片类型,上传给服务器。 方法一:压缩之后直接上传base64给后台,实现简单。 方法二:前端自己转存base64位File图片,这个对于前端 压力比较大。原因:html5 canvas属于客户端API,没有权限去保存图片到硬盘,只有canvas.toDataURL()这一接口可导出画布的base64编码,以提供给服务器进行处理保存。所以如果要将base64编码转成图片需要借助于nodeJs。因为nodeJS有相关文件处理的API。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
//使用nodeJS将base64转化成图片 var express = require('express'); var fs = require("fs"); var app = module.exports = express(); function dataToImage(dataUrl){ var base64Data = dataUrl.replace(/^data:image\/\w+;base64,/,''); var dataBuffer = new Buffer(base64Data,'base64'); fs.writeFile('out.jpg',dataBuffer,function(err){ if(err){ console.log(err); }else{ console.log('Success...'); } }); } dataToImage('data:image/jpeg;base64,/9...'); //图片完整base64过长,所以省略... if(!module.parent){ app.listen(8000); console.log('Express started on port 8000'); } |
Summary:如果使用nodeJS,需要单独部署nodeJS代码到服务器,整个逻辑会比较麻烦。综合比较两种方法,推荐使用第一种方法,直接传base64给服务器,后台处理相应的转化! 相关知识科普: 图像一般由两部分组成:一部分是数据本身,他记录了每个像素的颜色值,另一部分是文件头,这里记录着形如图像的宽度,高度等信息。 不同图片类型及适用场景: 不同图片类型: GIF:无损压缩,体积小,支持透明效果,缺点:色彩效果最低,用gif保存鲜艳的图片的话会让网站看上去非常可怕。 PNG:无损压缩,可渐变透明,缺点:不如JPG颜色丰富,同样的图片体积也比JPG略大。 JPG/JPEG:色彩还原性好,可以在照片不明显失真的情况下,大幅度压缩图片格式,所以体积不会很大。缺点:不支持透明 适用场景: 当图片色彩鲜艳,基本没有透明效果的时候,选择jpg/jpeg。 当图片色彩鲜艳,透明效果较多的情况下,选择png; 当图片色彩比较单一情况下,可以选择gif; toDataURL,查找原生压缩图片的方法。type支持image/webp格式
1 |
canvas.toDataURL(type, encoderOptions); |
Base64编码:将三个8Bit的字节转换为四个6Bit的字节。 参考资料: http://www.imys.net/20150916/webapp-input-use-camera.html http://www.oxxostudio.tw/articles/201409/pointer-events.html https://segmentfault.com/a/1190000005364299 from:http://my.oschina.net/zyxchuxin/blog/700381
View Details最近在忙着优化集团公司的一个报表。优化完成后,报表查询速度有从半小时以上(甚至查不出)到秒查的质变。从修改SQL查询语句逻辑到决定创建存储过程实现,花了我3天多的时间,在此总结一下,希望对朋友们有帮助。 数据背景 首先,项目是西门子中国在我司实施部署的MES项目,由于项目是在产线上运作(3 years+),数据累积很大。在项目的数据库中,大概上亿条数据的表有5个以上,千万级数据的表10个以上,百万级数据的表,很多… (历史问题,当初实施无人监管,无人监控数据库这块的性能问题。ps:我刚入职不久…) 不多说,直接贴西门子中国的开发人员在我司开发的SSRS报表中的SQL语句:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 |
select distinct b.MaterialID as matl_def_id, c.Descript, case when right(b.MESOrderID, 12) < '001000000000' then right(b.MESOrderID, 9) else right(b.MESOrderID, 12) end as pom_order_id, a.LotName, a.SourceLotName as ComLot, e.DefID as ComMaterials, e.Descript as ComMatDes, d.VendorID, d.DateCode,d.SNNote, b.OnPlantID,a.SNCUST from ( select m.lotname, m.sourcelotname, m.opetypeid, m.OperationDate,n.SNCUST from View1 m left join co_sn_link_customer as n on n.SNMes=m.LotName where ( m.LotName in (select val from fn_String_To_Table(@sn,',',1)) or (@sn) = '') and ( m.sourcelotname in (select val from fn_String_To_Table(@BatchID,',',1)) or (@BatchID) = '') and (n.SNCust like '%'+ @SN_ext + '%' or (@SN_ext)='') ) a left join ( select * from Table1 where SNType = 'IntSN' and SNRuleName = 'ProductSNRule' and OnPlantID=@OnPlant ) b on b.SN = a.LotName inner join MMdefinitions as c on c.DefID = b.MaterialID left join Table1 as d on d.SN = a.SourceLotName inner join MMDefinitions as e on e.DefID = d.MaterialID where not exists ( select distinct LotName, SourceLotName from ELCV_ASSEMBLE_OPS where LotName = a.SourceLotName and SourceLotName = a.LotName ) and (d.DateCode in (select val from fn_String_To_Table(@DCode,',',1)) or (@DCode) = '') and (d.SNNote like '%'+@SNNote+'%' or (@SNNote) = '') and ((case when right(b.MESOrderID, 12) < '001000000000' then right(b.MESOrderID, 9) else right(b.MESOrderID, 12) end) in (select val from fn_String_To_Table(@order_id,',',1)) or (@order_id) = '') and (e.DefID in (select val from fn_String_To_Table(@comdef,',',1)) or (@comdef) = '') --View1是一个嵌套两层的视图(出于保密性,实际名称可能不同),里面有一张上亿数据的表和几张千万级数据的表做左连接查询 --Table1是一个数据记录超过1500万的表 |
这个查询语句,实际上通过我的检测和调查,在B/S系统前端已无法查出结果,半小时,一小时 … 。因为我直接在SQL查询分析器查,半小时都没有结果。 (原因是里面对一张上亿级数据表和3张千万级数据表做全表扫描查询) 不由感慨,西门子中国的素质(或者说责任感)就这样? 下面说说我的分析和走的弯路(思维误区),希望对你也有警醒。 探索和误区 首先相关表的索引,没有建全的,把索引给建上。 索引这步完成后,发现情况还是一样,查询速度几乎没有改善。后来想起相关千万级数据以上的表,都还没有建立表分区。于是考虑建立表分区以及数据复制的方案。 这里有必要说明下:我司报表用的是一个专门的数据库服务器,数据从产线订阅而来。就是常说的“读写分离”。 如果直接在原表上建立表分区,你会发现执行表分区的事物会直接死锁。原因是:表分区操作本身会锁表,产线还在推数据过来,这样很容易“阻塞”,“死锁”。 我想好的方案是:建立一个新表(空表),在新表上建好表分区,然后复制数据过来。 正打算这么干。等等!我好像进入了一个严重的误区! 分析: 原SQL语句和业务需求,是对产线的数据做产品以及序列号的追溯,关键是查询条件里没有有规律的"条件"(如日期、编号),贸然做了表分区,在这里几乎没有意义!反而会降低查询性能! 好险!还是一步一步来,先做SQL语句分析。 一、对原SQL语句的分析 1、查询语句的where条件,有大量@var in … or (@var =") 的片段 2、where条件有like '%’+@var+’%' 3、where条件有 case … end 函数 4、多次连接同一表查询,另外使用本身已嵌套的视图表,是不是必须,是否可替代? 5、SQL语句有*号,视图中也有*号出现 二、优化设计 首先是用存储过程改写,好处是设计灵活。 核心思想是:用一个或多个查询条件(查询条件要求至少输入一个)得到临时表,每个查询条件如果查到集合,就更新这张临时表,最后汇总的时候,只需判断这个临时表是否有值。以此类推,可以建立多个临时表,将查询条件汇总。 这样做目前来看至少两点好处: 1、省去了对变量进行 =@var or (@var=")的判断; 2、抛弃sql拼接,提高代码可读性。 再有就是在书写存储过程,这个过程中要注意: 1、尽量想办法使用临时表扫描替代全表扫描; 2、抛弃in和not in语句,使用exists和not exists替代; 3、和客户确认,模糊查询是否有必要,如没有必要,去掉like语句; 4、注意建立适当的,符合场景的索引; 5、踩死 "*" 号; 6、避免在where条件中对字段进行函数操作; 7、对实时性要求不高的报表,允许脏读(with(nolock))。 三、存储过程 如果想参考优化设计片段的详细内容,请参阅SQL代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 |
/** * 某某跟踪报表 **/ --exec spName1 '','','','','','','公司代号' CREATE Procedure spName1 @MESOrderID nvarchar(320), --工单号,最多30个 @LotName nvarchar(700), --产品序列号,最多50个 @DateCode nvarchar(500), --供应商批次号,最多30个 @BatchID nvarchar(700), --组装件序列号/物料批号,最多50个 @comdef nvarchar(700), --组装件物料编码,最多30个 @SNCust nvarchar(1600), --外部序列号,最多50个 @OnPlant nvarchar(20) --平台 AS BEGIN SET NOCOUNT ON; /** * 1)定义全局的临时表,先根据六个查询条件的任意一个,得出临时表结果 **/ CREATE TABLE #FinalLotName ( LotName NVARCHAR(50), --序列号 SourceLotName NVARCHAR(50), --来源序列号 SNCust NVARCHAR(128) --外部序列号 ) --1.1 IF @LotName<>'' BEGIN SELECT Val INTO #WorkLot FROM fn_String_To_Table(@LotName,',',1) SELECT LotPK,LotName INTO #WorkLotPK FROM MMLots WITH(NOLOCK) WHERE EXISTS(SELECT 1 FROM #WorkLot b WHERE b.Val=MMLots.LotID) --求SourceLotPK只能在这里求 SELECT a.LotPK,a.SourceLotPK into #WorkSourcePK FROM MMLotOperations a WITH(NOLOCK) WHERE EXISTS(SELECT 1 FROM #WorkLotPK b WHERE b.LotPK=a.LotPK) AND a.SourceLotPK IS NOT NULL SELECT a.LotPK,a.SourceLotPK,b.LotName INTO #WorkSourcePK2 FROM #WorkSourcePK a JOIN #WorkLotPK b ON a.LotPK=b.LotPK INSERT INTO #FinalLotName SELECT a.LotName,b.LotName AS SourceLotName,NULL FROM #WorkSourcePK2 a JOIN (SELECT LotPK,LotName FROM MMLots WITH(NOLOCK) ) b on a.SourceLotPK=b.LotPK --b的里面加不加WHERE RowDeleted=0待确定 SELECT a.LotName,a.SourceLotName,b.SNCust INTO #FinalLotNameX1 FROM #FinalLotName a LEFT JOIN CO_SN_LINK_CUSTOMER b WITH(NOLOCK) ON a.LotName=b.SNMes DELETE FROM #FinalLotName INSERT INTO #FinalLotName SELECT LotName,SourceLotName,SNCust FROM #FinalLotNameX1 END --1.2 IF @BatchID<>'' BEGIN SELECT Val INTO #WorkSourceLot FROM fn_String_To_Table(@BatchID,',',1) IF EXISTS(SELECT 1 FROM #FinalLotName)--如果@LotName也不为空 BEGIN SELECT a.LotName,a.SourceLotName,a.SNCust INTO #FinalLotNameX2 FROM #FinalLotName a WHERE EXISTS(SELECT 1 FROM #WorkSourceLot b WHERE a.SourceLotName=b.Val) DELETE FROM #FinalLotName INSERT INTO #FinalLotName SELECT LotName,SourceLotName,SNCust FROM #FinalLotNameX2 END ELSE --@LotName条件为空 BEGIN SELECT LotPK AS SourceLotPK,LotName AS SourceLotName INTO #2 FROM MMLots WITH(NOLOCK) WHERE EXISTS(SELECT 1 FROM #WorkSourceLot b WHERE b.Val=MMLots.LotID) SELECT a.LotPK,a.SourceLotPK into #21 FROM MMLotOperations a WITH(NOLOCK) WHERE EXISTS(SELECT 1 FROM #2 b WHERE b.SourceLotPK=a.SourceLotPK) SELECT a.LotPK,a.SourceLotPK,b.SourceLotName INTO #22 FROM #21 a JOIN #2 b ON a.SourceLotPK=b.SourceLotPK INSERT INTO #FinalLotName SELECT b.LotName,a.SourceLotName,NULL FROM #22 a JOIN (SELECT LotPK,LotName FROM MMLots WITH(NOLOCK) ) b on a.LotPK=b.LotPK --b的里面加不加WHERE RowDeleted=0待确定 SELECT a.LotName,a.SourceLotName,b.SNCust INTO #FinalLotNameX21 FROM #FinalLotName a LEFT JOIN CO_SN_LINK_CUSTOMER b WITH(NOLOCK) ON a.LotName=b.SNMes DELETE FROM #FinalLotName INSERT INTO #FinalLotName SELECT LotName,SourceLotName,SNCust FROM #FinalLotNameX21 END END --1.3 IF @SNCust<>'' BEGIN SELECT Val INTO #WorkCustomSN FROM fn_String_To_Table(@SNCust,',',1) IF EXISTS(SELECT 1 FROM #FinalLotName)--前面两个条件至少有一个有值 BEGIN SELECT a.LotName,a.SourceLotName,a.SNCust INTO #FinalLotNameX3 FROM #FinalLotName a WHERE EXISTS(SELECT 1 FROM #WorkCustomSN b WHERE a.SNCust=b.Val) DELETE FROM #FinalLotName INSERT INTO #FinalLotName SELECT LotName,SourceLotName,SNCust FROM #FinalLotNameX3 END ELSE BEGIN SELECT a.SNMes INTO #WorkLotX FROM CO_SN_LINK_CUSTOMER a WITH(NOLOCK) WHERE EXISTS(SELECT 1 FROM #WorkCustomSN b WHERE a.SNCust=b.Val) -------------------以下逻辑和变量1(@LotName)类似[先根据外部序列号求解序列号,再照搬第一个判断变量的方式] SELECT LotPK,LotName INTO #WorkLotPKX FROM MMLots WITH(NOLOCK) WHERE EXISTS(SELECT 1 FROM #WorkLotX b WHERE b.SNMes=MMLots.LotID) --求SourceLotPK只能在这里求 SELECT a.LotPK,a.SourceLotPK into #WorkSourcePKX FROM MMLotOperations a WITH(NOLOCK) WHERE EXISTS(SELECT 1 FROM #WorkLotPKX b WHERE b.LotPK=a.LotPK) AND a.SourceLotPK IS NOT NULL SELECT a.LotPK,a.SourceLotPK,b.LotName INTO #WorkSourcePK2X FROM #WorkSourcePKX a JOIN #WorkLotPKX b ON a.LotPK=b.LotPK INSERT INTO #FinalLotName SELECT a.LotName,b.LotName AS SourceLotName,NULL FROM #WorkSourcePK2X a JOIN (SELECT LotPK,LotName FROM MMLots WITH(NOLOCK) ) b on a.SourceLotPK=b.LotPK --b的里面加不加WHERE RowDeleted=0待确定 SELECT a.LotName,a.SourceLotName,b.SNCust INTO #FinalLotNameX31 FROM #FinalLotName a LEFT JOIN CO_SN_LINK_CUSTOMER b WITH(NOLOCK) ON a.LotName=b.SNMes DELETE FROM #FinalLotName INSERT INTO #FinalLotName SELECT LotName,SourceLotName,SNCust FROM #FinalLotNameX31 ----------------------- END END /** * 2)定义全局的临时表,用于替换第一个全局临时表。 **/ CREATE TABLE #FinalCO_SN ( SN NVARCHAR(50), SourceSN NVARCHAR(50), SNCust NVARCHAR(128), matl_def_id NVARCHAR(50),--sn的物料ID ComMaterials NVARCHAR(50), --SourceSN的物料ID MESOrderID NVARCHAR(20), OnPlantID NVARCHAR(20), VendorID NVARCHAR(20), DateCode NVARCHAR(20) , SNNote NVARCHAR(512) ) --2.1 IF @MESOrderID<>'' BEGIN -------------------------------将MESOrderID做特殊处理----------------------------------- SELECT Val INTO #WorkMESOrderID FROM fn_String_To_Table(@MESOrderID,',',1) IF @OnPlant='Comba' BEGIN UPDATE #WorkMESOrderID SET Val='C000'+Val WHERE LEN(Val)=9 END ELSE BEGIN UPDATE #WorkMESOrderID SET Val='W000'+Val WHERE LEN(Val)=9 END SELECT SN,MaterialID,MESOrderID,OnPlantID INTO #WorkCO_SN1 FROM CO_SN_GENERATION a WITH(NOLOCK) WHERE SNType='IntSN' AND SNRuleName = 'ProductSNRule' AND OnPlantID=@OnPlant AND EXISTS(SELECT 1 FROM #WorkMESOrderID b WHERE a.MESOrderID=b.Val) ------------------------------------------------------------------------------------------ --条件判断(逻辑分析)开始 IF EXISTS(SELECT 1 FROM #FinalLotName)--如果前面判断的查询条件有值 BEGIN --查出SourceLotName对应的查询字段 SELECT a.SN AS SourceLotName,a.VendorID,a.DateCode,a.SNNote,a.MaterialID AS ComMaterials INTO #SourceLotNameTable FROM CO_SN_GENERATION a WITH(NOLOCK) WHERE EXISTS(SELECT 1 FROM #FinalLotName b WHERE a.SN=b.SourceLotName) INSERT INTO #FinalCO_SN SELECT a.LotName,a.SourceLotName,d.SNCust,b.MaterialID,c.ComMaterials,b.MESOrderID,b.OnPlantID,c.VendorID,c.DateCode,c.SNNote FROM #FinalLotName a LEFT JOIN #WorkCO_SN1 b ON a.LotName=b.SN LEFT JOIN #SourceLotNameTable c ON a.SourceLotName=c.SourceLotName LEFT JOIN CO_SN_LINK_CUSTOMER d WITH(NOLOCK) ON a.LotName=d.SNMes END ELSE BEGIN --已知SN集合求解对应的SourceSN和SNCust集合------------------------------------------ SELECT LotPK,LotName INTO #WorkLotPK410 FROM MMLots WITH(NOLOCK) WHERE EXISTS(SELECT 1 FROM #WorkCO_SN1 b WHERE b.SN=MMLots.LotID) SELECT a.LotPK,a.SourceLotPK into #WorkSourcePK420 FROM MMLotOperations a WITH(NOLOCK) WHERE EXISTS(SELECT 1 FROM #WorkLotPK410 b WHERE b.LotPK=a.LotPK) AND a.SourceLotPK IS NOT NULL SELECT a.LotPK,a.SourceLotPK,b.LotName INTO #WorkSourcePK430 FROM #WorkSourcePK420 a JOIN #WorkLotPK410 b ON a.LotPK=b.LotPK INSERT INTO #FinalLotName SELECT a.LotName,b.LotName AS SourceLotName,NULL FROM #WorkSourcePK430 a JOIN (SELECT LotPK,LotName FROM MMLots WITH(NOLOCK) ) b on a.SourceLotPK=b.LotPK --b的里面加不加WHERE RowDeleted=0待确定 SELECT a.LotName,a.SourceLotName,b.SNCust INTO #FinalLotNameX440 FROM #FinalLotName a LEFT JOIN CO_SN_LINK_CUSTOMER b WITH(NOLOCK) ON a.LotName=b.SNMes DELETE FROM #FinalLotName INSERT INTO #FinalLotName SELECT LotName,SourceLotName,SNCust FROM #FinalLotNameX440 ------------------------------------------------------------------------------------- SELECT a.SN AS SourceLotName,a.VendorID,a.DateCode,a.SNNote,a.MaterialID AS ComMaterials INTO #SourceLotNameTable2 FROM CO_SN_GENERATION a WITH(NOLOCK) WHERE EXISTS(SELECT 1 FROM #FinalLotName b WHERE a.SN=b.SourceLotName) INSERT INTO #FinalCO_SN SELECT a.LotName,a.SourceLotName,a.SNCust,b.MaterialID,c.ComMaterials,b.MESOrderID,b.OnPlantID,c.VendorID,c.DateCode,c.SNNote FROM #FinalLotName a LEFT JOIN #WorkCO_SN1 b ON a.LotName=b.SN LEFT JOIN #SourceLotNameTable2 c ON a.SourceLotName=c.SourceLotName END END --2.2 IF @DateCode<>'' BEGIN SELECT Val INTO #WorkDateCode FROM fn_String_To_Table(@DateCode,',',1) --此@DataCode条件求解出来的是SourceSN SELECT SN AS SourceSN,MaterialID AS ComMaterials,VendorID,DateCode,SNNote INTO #WorkSourceSNT1 FROM CO_SN_GENERATION a WITH(NOLOCK) WHERE EXISTS(SELECT 1 FROM #WorkDateCode b WHERE a.DateCode=b.Val) ---------------------------------------------------------------------------------------------------- --条件判断(逻辑分析)开始 IF EXISTS(SELECT 1 FROM #FinalCO_SN)--如果前面判断的查询条件有值 BEGIN SELECT a.LotName,a.SourceLotName,a.SNCust,a.MaterialID,a.ComMaterials,a.MESOrderID,a.OnPlantID,a.VendorID,a.DateCode,a.SNNote INTO #TMP51 FROM #FinalCO_SN a WHERE EXISTS (SELECT 1 FROM #WorkDateCode b WHERE a.DateCode=b.Val) DELETE FROM #FinalCO_SN INSERT INTO #FinalCO_SN SELECT LotName,SourceLotName,SNCust,MaterialID,ComMaterials,MESOrderID,OnPlantID,VendorID,DateCode,SNNote FROM #TMP51 END ELSE BEGIN IF EXISTS(SELECT 1 FROM #FinalLotName) BEGIN --查出SourceLotName对应的查询字段 SELECT a.SourceSN,a.VendorID,a.DateCode,a.SNNote,a.ComMaterials INTO #SourceLTX5 FROM #WorkSourceSNT1 a WHERE EXISTS(SELECT 1 FROM #FinalLotName b WHERE a.SourceSN=b.SourceLotName) --查出SN对应的查询字段 SELECT SN,MaterialID,MESOrderID,OnPlantID INTO #WorkSNT510 FROM CO_SN_GENERATION a WITH(NOLOCK) WHERE SNType='IntSN' AND SNRuleName = 'ProductSNRule' AND OnPlantID=@OnPlant AND EXISTS(SELECT 1 FROM #FinalLotName b WHERE a.SN=b.LotName) INSERT INTO #FinalCO_SN SELECT a.LotName,a.SourceLotName,d.SNCust,b.MaterialID,c.ComMaterials,b.MESOrderID,b.OnPlantID,c.VendorID,c.DateCode,c.SNNote FROM #FinalLotName a LEFT JOIN #WorkSNT510 b ON a.LotName=b.SN LEFT JOIN #WorkSourceSNT1 c ON a.SourceLotName=c.SourceSN LEFT JOIN CO_SN_LINK_CUSTOMER d WITH(NOLOCK) ON a.LotName=d.SNMes END ELSE BEGIN --已知SourceSN集合求解对应的SN和SNCust集合------------------------------------------ SELECT LotPK AS SourceLotPK,LotName AS SrouceLotName INTO #WorkLotX510 FROM MMLots WITH(NOLOCK) WHERE EXISTS(SELECT 1 FROM #WorkSourceSNT1 b WHERE b.SourceSN=MMLots.LotID) SELECT a.LotPK,a.SourceLotPK into #WorkLotX520 FROM MMLotOperations a WITH(NOLOCK) WHERE EXISTS(SELECT 1 FROM #WorkLotX510 b WHERE b.SourceLotPK=a.SourceLotPK) SELECT a.LotPK,a.SourceLotPK,b.SrouceLotName INTO #WorkLotX530 FROM #WorkLotX520 a JOIN #WorkLotX510 b ON a.SourceLotPK=b.SourceLotPK INSERT INTO #FinalLotName SELECT b.LotName,a.SrouceLotName,NULL FROM #WorkLotX530 a JOIN (SELECT LotPK,LotName FROM MMLots WITH(NOLOCK) ) b on a.LotPK=b.LotPK --b的里面加不加WHERE RowDeleted=0待确定 SELECT a.LotName,a.SourceLotName,b.SNCust INTO #WorkLotX540 FROM #FinalLotName a LEFT JOIN CO_SN_LINK_CUSTOMER b WITH(NOLOCK) ON a.LotName=b.SNMes DELETE FROM #FinalLotName INSERT INTO #FinalLotName SELECT LotName,SourceLotName,SNCust FROM #WorkLotX540 ------------------------------------------------------------------------------------- SELECT SN,MaterialID,MESOrderID,OnPlantID INTO #WorkLotX550 FROM CO_SN_GENERATION a WITH(NOLOCK) WHERE SNType='IntSN' AND SNRuleName = 'ProductSNRule' AND OnPlantID=@OnPlant AND EXISTS(SELECT 1 FROM #FinalLotName b WHERE a.SN=b.LotName) INSERT INTO #FinalCO_SN SELECT a.LotName,a.SourceLotName,a.SNCust,b.MaterialID,c.ComMaterials,b.MESOrderID,b.OnPlantID,c.VendorID,c.DateCode,c.SNNote FROM #FinalLotName a LEFT JOIN #WorkLotX550 b ON a.LotName=b.SN LEFT JOIN #WorkSourceSNT1 c ON a.SourceLotName=c.SourceSN END END END --2.3 IF @comdef<>'' BEGIN SELECT Val INTO #WorkComdef FROM fn_String_To_Table(@comdef,',',1) --此@comdef条件求解出来的是SourceSN SELECT SN AS SourceSN,MaterialID AS ComMaterials,VendorID,DateCode,SNNote INTO #WorkSourceSNT16 FROM CO_SN_GENERATION a WITH(NOLOCK) WHERE EXISTS(SELECT 1 FROM #WorkComdef b WHERE a.MaterialID=b.Val) ---------------------------------------------------------------------------------------------------- --条件判断(逻辑分析)开始 IF EXISTS(SELECT 1 FROM #FinalCO_SN)--如果前面判断的查询条件有值 BEGIN SELECT a.LotName,a.SourceLotName,a.SNCust,a.MaterialID,a.ComMaterials,a.MESOrderID,a.OnPlantID,a.VendorID,a.DateCode,a.SNNote INTO #TMP516 FROM #FinalCO_SN a WHERE EXISTS (SELECT 1 FROM #WorkComdef b WHERE a.matl_def_id=b.Val) DELETE FROM #FinalCO_SN INSERT INTO #FinalCO_SN SELECT LotName,SourceLotName,SNCust,MaterialID,ComMaterials,MESOrderID,OnPlantID,VendorID,DateCode,SNNote FROM #TMP516 END ELSE BEGIN IF EXISTS(SELECT 1 FROM #FinalLotName) BEGIN --查出SourceLotName对应的查询字段 SELECT a.SourceSN,a.VendorID,a.DateCode,a.SNNote,a.ComMaterials INTO #SourceLTX56 FROM #WorkSourceSNT16 a WHERE EXISTS(SELECT 1 FROM #FinalLotName b WHERE a.SourceSN=b.SourceLotName) --查出SN对应的查询字段 SELECT SN,MaterialID,MESOrderID,OnPlantID INTO #WorkSNT5106 FROM CO_SN_GENERATION a WITH(NOLOCK) WHERE SNType='IntSN' AND SNRuleName = 'ProductSNRule' AND OnPlantID=@OnPlant AND EXISTS(SELECT 1 FROM #FinalLotName b WHERE a.SN=b.LotName) INSERT INTO #FinalCO_SN SELECT a.LotName,a.SourceLotName,d.SNCust,b.MaterialID,c.ComMaterials,b.MESOrderID,b.OnPlantID,c.VendorID,c.DateCode,c.SNNote FROM #FinalLotName a LEFT JOIN #WorkSNT5106 b ON a.LotName=b.SN LEFT JOIN #WorkSourceSNT16 c ON a.SourceLotName=c.SourceSN LEFT JOIN CO_SN_LINK_CUSTOMER d WITH(NOLOCK) ON a.LotName=d.SNMes END ELSE BEGIN --已知SourceSN集合求解对应的SN和SNCust集合------------------------------------------ SELECT LotPK AS SourceLotPK,LotName AS SrouceLotName INTO #WorkLotX5106 FROM MMLots WITH(NOLOCK) WHERE EXISTS(SELECT 1 FROM #WorkSourceSNT16 b WHERE b.SourceSN=MMLots.LotID) SELECT a.LotPK,a.SourceLotPK into #WorkLotX5206 FROM MMLotOperations a WITH(NOLOCK) WHERE EXISTS(SELECT 1 FROM #WorkLotX5106 b WHERE b.SourceLotPK=a.SourceLotPK) SELECT a.LotPK,a.SourceLotPK,b.SrouceLotName INTO #WorkLotX5306 FROM #WorkLotX5206 a JOIN #WorkLotX5106 b ON a.SourceLotPK=b.SourceLotPK INSERT INTO #FinalLotName SELECT b.LotName,a.SrouceLotName,NULL FROM #WorkLotX5306 a JOIN (SELECT LotPK,LotName FROM MMLots WITH(NOLOCK) ) b on a.LotPK=b.LotPK --b的里面加不加WHERE RowDeleted=0待确定 SELECT a.LotName,a.SourceLotName,b.SNCust INTO #WorkLotX5406 FROM #FinalLotName a LEFT JOIN CO_SN_LINK_CUSTOMER b WITH(NOLOCK) ON a.LotName=b.SNMes DELETE FROM #FinalLotName INSERT INTO #FinalLotName SELECT LotName,SourceLotName,SNCust FROM #WorkLotX5406 ------------------------------------------------------------------------------------- SELECT SN,MaterialID,MESOrderID,OnPlantID INTO #WorkLotX5506 FROM CO_SN_GENERATION a WITH(NOLOCK) WHERE SNType='IntSN' AND SNRuleName = 'ProductSNRule' AND OnPlantID=@OnPlant AND EXISTS(SELECT 1 FROM #FinalLotName b WHERE a.SN=b.LotName) INSERT INTO #FinalCO_SN SELECT a.LotName,a.SourceLotName,a.SNCust,b.MaterialID,c.ComMaterials,b.MESOrderID,b.OnPlantID,c.VendorID,c.DateCode,c.SNNote FROM #FinalLotName a LEFT JOIN #WorkLotX5506 b ON a.LotName=b.SN LEFT JOIN #WorkSourceSNT16 c ON a.SourceLotName=c.SourceSN END END END /** * 3)条件判断结束 **/ IF EXISTS(SELECT 1 FROM #FinalLotName) BEGIN IF EXISTS(SELECT 1 FROM #FinalCO_SN) BEGIN--3.1 SELECT a.matl_def_id,b.Descript,a.MESOrderID AS pom_order_id,a.SN AS LotName,a.SourceSN AS ComLot, a.ComMaterials,c.Descript AS ComMatDes,a.VendorID,a.DateCode,a.SNNote, OnPlantID,SNCust FROM #FinalCO_SN a JOIN MMDefinitions b WITH(NOLOCK) ON a.matl_def_id=b.DefID JOIN MMDefinitions c WITH(NOLOCK) ON a.ComMaterials=c.DefID WHERE NOT EXISTS(select distinct SN, SourceSN from #FinalCO_SN x where x.SN = a.SourceSN and x.SourceSN = a.SN) END ELSE BEGIN--3.2 --3.2.1求解SN的必查字段 SELECT SN,MaterialID,MESOrderID,OnPlantID INTO #FinalSNX1 FROM CO_SN_GENERATION a WITH(NOLOCK) WHERE SNType='IntSN' AND SNRuleName = 'ProductSNRule' AND OnPlantID=@OnPlant AND EXISTS(SELECT 1 FROM #FinalLotName b WHERE a.SN=b.LotName) --3.2.2求解SourceSN的必查字段 SELECT a.SN AS SourceLotName,a.VendorID,a.DateCode,a.SNNote,a.MaterialID AS ComMaterials INTO #FinalSNX2 FROM CO_SN_GENERATION a WITH(NOLOCK) WHERE EXISTS(SELECT 1 FROM #FinalLotName b WHERE a.SN=b.SourceLotName) SELECT b.MaterialID AS matl_def_id,x.Descript,b.MESOrderID AS pom_order_id,b.SN AS LotName,c.SourceLotName AS ComLot,c.ComMaterials,y.Descript AS ComMatDes,c.VendorID,c.DateCode,c.SNNote,b.OnPlantID,a.SNCust FROM #FinalLotName a LEFT JOIN #FinalSNX1 b ON a.LotName=b.SN LEFT JOIN #FinalSNX2 c ON a.SourceLotName=c.SourceLotName JOIN MMDefinitions x WITH(NOLOCK) ON b.MaterialID=x.DefID JOIN MMDefinitions y WITH(NOLOCK) ON c.ComMaterials=y.DefID WHERE NOT EXISTS( SELECT DISTINCT * FROM #FinalLotName z WHERE z.LotName=a.SourceLotName and z.SourceLotName=a.LotName ) END END ELSE BEGIN IF EXISTS(SELECT 1 FROM #FinalCO_SN) BEGIN--3.3 SELECT a.matl_def_id,b.Descript,a.MESOrderID AS pom_order_id,a.SN AS LotName,a.SourceSN AS ComLot, a.ComMaterials,c.Descript AS ComMatDes,a.VendorID,a.DateCode,a.SNNote, OnPlantID,SNCust FROM #FinalCO_SN a JOIN MMDefinitions b WITH(NOLOCK) ON a.matl_def_id=b.DefID JOIN MMDefinitions c WITH(NOLOCK) ON a.ComMaterials=c.DefID WHERE NOT EXISTS(select distinct SN, SourceSN from #FinalCO_SN x where x.SN = a.SourceSN and x.SourceSN = a.SN) END ELSE BEGIN--3.4 PRINT 'There is no queryable condition,please enter at less a query conditon.' END END END GO |
虽然牺牲了代码的可读性,但创造了性能价值。本人水平有限,还请各位不吝赐教! 最后,将SSRS报表替换成此存储过程后,SQL查询分析器是秒查的。B/S前端用时1~2秒! 四、总结 平常的你是否偶尔会因急于完成任务而书写一堆性能极低的SQL语句呢?写出可靠性能的SQL语句不难,难的是习惯。 本文的优化思想很简单,关键点是避免全表扫描 & 注重SQL语句写法 & 索引,另外,如果你查询的表有可能会在查询时段更新,而实际业务需求允许脏读,可加with(nolock)预防查询被更新事物阻塞。 作者:hangwei 出处:http://www.cnblogs.com/hangwei/ 关于作者:专注于微软平台项目的架构设计与开发、数据库调优等工作。如有问题或建议,请多多赐教! from:http://www.oschina.net/news/74787/how-the-data-on-the-second-search
View Details