Quantcast
Channel: IT社区推荐资讯 - ITIndex.net
Viewing all 15843 articles
Browse latest View live

openSession()与getCurrentSession()区别:

$
0
0
来自 http://blog.csdn.net/dy511/article/details/6166134
1.getCurrentSession创建的session会和绑定到当前线程,而openSession不会。
2. getCurrentSession创建的线程会在事务回滚或事物提交后自动关闭,而openSession必须手动关闭。
这里getCurrentSession本地事务(本地事务:jdbc)时要在配置文件里进行如下设置
    * 如果使用的是本地事务(jdbc事务)
<property name="hibernate.current_session_context_class">thread</property>
* 如果使用的是全局事务(jta事务)
<property name="hibernate.current_session_context_class">jta</property>
3.getCurrentSession () 使用当前的session,openSession() 重新建立一个新的session
4.在一个应用程序中,如果DAO 层使用Spring 的hibernate 模板,通过Spring 来控制session 的生命周期,则首选getCurrentSession ()。
5.在 SessionFactory 启动的时候, Hibernate 会根据配置创建相应的 CurrentSessionContext ,在 getCurrentSession() 被调用的时候,实际被执行的方法是 CurrentSessionContext.currentSession() 。在 currentSession() 执行时,如果当前 Session 为空, currentSession 会调用 SessionFactory 的 openSession 。所以 getCurrentSession() 对于 Java EE 来说是更好的获取 Session 的方法。


已有 1人发表留言,猛击->> 这里<<-参与讨论


ITeye推荐




高性能建站系统

$
0
0

首先是从三方面来提高的,应用层面,服务器端层面,数据库层面。
一、应用层面
1、采用freemaker或者velocity来做页面静态化,提高网站的访问速度。

二、服务器端
1、对于一些不经常增删改的数据做缓存,比如memcached,redis,mongodb
2、对于图片的话,采用fastDFS来做图片的分布式服务器,加快图片的存储与读取。
3、对于安全方面,采用数据库事务来保证数据的安全性能。
4、能尽量少的使用锁来处理,因为锁有时候会带来一系列的连锁反应。
5、做负载均衡,通过nginx+tomcat组合给服务器端分流。
6、通过队列来做一些数据的信息暂存,来减缓线程对服务器的压力。
7、采用并发的集合类,例如ConcurrentHashMap,CopyOnWriteArrayList等。
8、考虑程序的可扩展性和可移植性。
9、数据的一致性问题,需要考虑java concurrent包
10、适当的使用一些高效算法。
11、内存一致性:内存操作(如共享变量的读写)的 happen-before 关系。只有写入操作 happen-before 读取操作时,才保证一个线程写入的结果对另一个线程的读取是可视的。synchronized 和 volatile 构造 happen-before 关系,Thread.start() 和Thread.join() 方法形成 happen-before 关系。
12、JVM的内存模型以及JVM的垃圾回收机制,一直垃圾回收器的合理使用,新生代和老年代的合理分区。

三、数据库层面
1、给数据库字段做索引,能够加快查询速度,不是所有的索引都能够加快查询速度的,前提是对于查询多于增删改的数据。
2、给数据库表做表分区,能够加速查询的速度。
3、分库分表,通过分区分表能够加快查询速度。
4、根据explain命令对于sql语句进行解释执行计划分析。
5、对表进行分区,分区查询会加快速度的
6、oracle的话。需要选择合适的选择器,根据实际需要,选择基于成本的选择器,或者基于基于规则的优化器
7、in和exists,还有not in和not exists的用法区别,以及适用场合
8、做master-slave,进行读写分离,给数据库通过分流来减小压力。
9、对于sql语句进行优化.



已有 0人发表留言,猛击->> 这里<<-参与讨论


ITeye推荐



怎样了解一个行业?

$
0
0

原文来自: 怎样了解一个行业?从哪些角度去了解?怎样去了解行业特性?

1.什么是行业?什么是产业?两者有什么区别?

答:按照定义来说, 产业应该是按照规模经济和范围经济要求集成起来的行业群体。通俗的说法就是,行业是社会分工后细化的一类工作,能以此为生,但可能行业规模和运作方式不能大批量的延伸。产业则是一个行业发展到一定程度可以大规模的开拓市场拓展商业机会。

之所以讨论一下产业和行业的区别,是因为在当前市场经济的大潮下,行业的逻辑已经逐步在用产业的方式推进。所以,有了这个大前提,就能把很多商业的问题讨论清楚。所以,后面对行业的讨论,都是在产业的模式下讨论。对于那种米上雕子、火车站带路的买卖,只能是个小众的行业。研究起来价值有限。

2.一个产业应该有什么样的参数?从哪些角度去了解?

答:我们在学习化学的时候,常常会研究他的一些通用性能。比如金属,我们会研究他的导热性、燃点、导电性、颜色……所以,涉及到一个产业,也会有类似的一些参数,依照我个人的理解。可以从下面的几个角度去了解,这几个角度中也对应了一个产业应有的参数。

按照麦肯锡的战略研究来看,一个行业比较常见的分析方法是PEST 分析、波特的五力模型、SWOT分析法、竞争者分析等等。在解决这个问题的时候,我个人不是很推崇。我觉得从 菲利普·科特勒在其畅销书《营销管理:分析、规划与控制》提出的4Ps为核心的营销组合方法把我们对一个产业的理解尽收眼底,也把前面的几个战略分析能够尽收眼底。即:产品(Product)、价格 (Price)、渠道 (Place)、促销(Promotion)。下面我来细细拆分。

首先说产品。说到产品,要倒退一步说说研发,当前中国的研发还是集中在高校和部分有实力的企业中,相比美国的企业主导研发而言,中国的研发还是处于一种和市场脱节的状态下,应用性不够好,多数为了那国家课题而制作很多不必要的创新。而好的应用性研发很稀缺,以我听说中科院的一个分所最近出售的石墨烯生产技术为例,最终成交额以亿为单位,这样招人待见、高金额的例子几乎是凤毛麟角。可见,招市场青睐的技术不是那么容易被高校制造出来。说完研发,就是产品在理论研究后如何被工业化生产出来,一个生产过程就会涉及到工业技术路线的问题。比如环保行业的除尘,为了达到这个目标可以有电除尘、也可以由布袋除尘。选哪个,为什么选,就成了一个企业的产品特色。选定了工业技术路线就会有工程实现方式,把前面的原理和技术路线变成工程可操作的现实。而最要命的是,有的产品永远是非标准化的,耐克鞋没法像可口可乐一次就一个模子;而一些道路桥梁的建设则是全国各地都没个重样的,这些都会影响到产品的特性。

因此,一个产品的研究就涉及到了 产品的基础生产原理、工业技术路线、工程实现方式、标准化程度以及上游供应商,以上种种形成了一个产品的特性,也决定了后面的定价、营销。顺便说下,很多时候服务也是无形的产品,懒得打字就不细说了。

其次说价格。一个产品的特性其实就融合了很多价格的基础。一般来说,咱们做一个产业不能亏本吧。以我熟悉的水务领域,是典型的国家规定“保本微利”行业。也就是说你不能多挣钱 。而北京的公交以四毛钱的绝对低廉,成就了一个公益性行业的美誉。除了产业特性和政策的影响外,供求关系也是绝对的影响,最近火热的艺术品投资市场,张大千等名家的画以足够的不可再生稀缺性获得了定价话语权。而在竞争性领域,华为这样的企业会把某个优势产品的价格拉到低利润,借此打垮竞争对手。总之,价格凝结了商业的很多内涵,也反映了很多产业的特性。

因此,一个产品价格的定制 涉及到了供求关系、产业特性、成本基础、政策影响、企业策略。

第三说渠道。渠道是客户买单和了解产品的基础。商业上有句话说,用渠道挣钱是一毛一毛的挣钱;用劳动力挣钱是一分一分的挣钱;用资本挣钱是一块一块的挣钱。写到这里,发现我们还在用一分一分挣钱,实在是让人倍感凄凉。不过还是要振作精神把字码完,别浪费了前面的一群汉子(汉字)。

建设渠道有很多方式,像沃尔玛这样的渠道,像苹果体验店这样的渠道,也有进批发市场的渠道,还有的产品,像第一财经日报,天然就是渠道。我听过一个故事,说某服装品牌全国建立了500家店,但是不怎么赢利,就把这个渠道网络卖掉了,就弄来了N个亿。可见没有渠道就没有产业的规模。

因此渠道的参数应该 包括渠道质量、渠道体量、渠道管控、渠道维护成本等等。

最后说说促销。到目前为止看到的促销内容,大家都多是理解为逛超市的时候搞个免费品尝、免费试用、半价促销、买二赠一……但是促销的精髓不在这种让利刺激上,而在刺激消费冲动上。注意,少了让利两个字内涵就大多了。如此说来,品牌影响力、回扣、迎合政绩等都是良好的促销方式。具体的,如果您有兴趣,我们可以细细用案例再交流。

因此,促销的参数应该包含 品牌形象、公关手法、价格联动、卖点买点等等。

好吧,以我的理解,各行各业都是从上面的四个角度去切入和理解。成为我们了解一个产业的思考模型和参数库。

3.那么,我们该如何切入一个行业去了解他呢?

答:第一位的是人。一个社会是人构成的,产业只是以经济和服务特性类似为纽带的一类人。以擒贼先擒王的思路看,就涉及到了政策制定者、技术专家、营销大师、生产能手、大客户等。不同的行业这些人散落的点不同。以GIS行业为例,政策制定者多在国土资源部、测绘地理信息局、交通部等;技术专家多在ESRI大外企、设计院、高等院校等地;营销大师和生产能手多在设计院和优质企业;大客户多是要找那些对产品购买有决策权的人。至于去哪里找到并熟悉这些人,我想展会、沙龙、产品发布会、他们上班的单位、资讯产品、论文、行研都是很好的渠道。

说完了人,其次才是事儿。也就是前面说的4Ps里面的各个环节,拆开了,揉碎了,挖深了的了解。对比不同的技术、渠道、客户等每个环节。用不了多久就能变成一个行业专家。

最后,我用一个小故事结尾吧。当年福特造汽车,还不是流水线生产,这个灵感来自于老福特参观了屠宰牛的工厂,发现一步一个工作,让效率最大化了,于是汽车工业就带来了流水线的生产。可见,对一个行业的研究和了解是一个开发的过程,跨行业的创新常常能给一个行业一次洗牌的机会。

就像马云和他的淘宝,让多少小城市的服装城欲哭无泪。



— 完 —
本文作者: 知乎用户(登录查看详情)

【知乎日报】 你都看到这啦,快来点我嘛 Σ(▼□▼メ)

WebView之js调用Android类的方法传递数据 - 依凡王子

$
0
0

1,具体的思路如下:

  在android中写一个Activity,里面写一个webview,这个webview加载本地的一个html文件,显示这个网页,这个网页包括一个用户名和密码的输入框和两个按钮(只有登陆按钮有用),输入用户名密码之后调用android中的类,并把输入的数据传过去,再在android中输出出来(具体你那数据做什么操作就看你的需求了),这样就做大额js与android数据交互的效果了:

  在android端,一些webviwe的设置和自定义类的写法如下源码:

  package com.example.webview;

  import android.app.Activity;
  import android.os.Bundle;
  import android.webkit.JavascriptInterface;
  import android.webkit.WebChromeClient;
  import android.webkit.WebSettings;
  import android.webkit.WebView;

  public class MainActivity extends Activity {
    private WebView webview;
    private String URL = "http://192.168.31.122/word2/login.html";//这是你要访问你html文件的存放地址,我这个是放在appache中的word文件夹下的login.html文件
    @Override
    protected void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);
      setContentView(R.layout.activity_main);
      webview = (WebView) findViewById(R.id.webView1);
      WebSettings webset = webview.getSettings();
      webset.setJavaScriptEnabled(true);// 表示webview可以执行服务器端的js代码
      webview.setWebChromeClient(new WebChromeClient(){});
      webview.addJavascriptInterface(new JsObject(),"jsObject");
      webview.loadUrl(URL);
    }

    public class JsObject {
      @JavascriptInterface
      public void getMessage(String name, String pwd) {
        // TODO Auto-generated method stub
        System.out.println("==="+"name:" + name + "---pwd:" + pwd);
      }
    }

  }

  而xml比较简单,只是一个比较简单的webview而已,代码如下:

  <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"

    android:layout_width="fill_parent"

    android:layout_height="fill_parent"
    android:orientation="vertical" >

    <WebView
      android:id="@+id/webView1"
      android:layout_width="match_parent"
      android:layout_height="match_parent" />

  </LinearLayout>

  对于要加载的html文件只要放在你要访问的地方就可以,比如appache下,具体代码如下:

   <!DOCTYPE html>

  <html>
    <head>
      <script>
        function login(){
          var th = document.form;
          var user = th.user.value;
          if(user==""){
            alert("请输入用户名!");
          }else{
            var name = th.user.value;
            var pwd = th.pwd.value;
            var name2 = jsObject.getMessage(name,pwd);
          }
        }
      </script>
    </head>
    <body>
      <form name='form' method='post' class='form' action=''>
        <table id='login_table'>
          <tr>
            <td>
              <span>账号:</sapn>
            </td>
            <td>
              <input type='text' class='usr' name='user' value=''/>
            </td>
            <td></td>
          </tr>
          <tr>
            <td>
              <span>密码:</sapn>
            </td>
            <td>
              <input type='password' class='psw' name='pwd' value=''/>
            </td>
            <td></td>
          </tr>
          <tr>
            <td></td>
            <td>
              <input type="file" value="上传图片" />
              <button class='denglu' onclick="login()">登陆</button>
              <button class='clear'>清空</button>
            </td>
            <td></td>
          </tr>
        </table>
      </form>
    </body>
  </html>
  


本文链接: WebView之js调用Android类的方法传递数据,转载请注明。

关于安卓中的cookie管理 - Sharp陈响

$
0
0

 

     Cookie管理是大家在做安卓app中难以避免的问题。我在此发表一些拙见。

     先先看看cookie可能存放的位置

  1.Httpclient会存储当次请求的cookie内容,存储位置在 httpClient.getCookieStore 但是apache建议自定义cookie存储方式,因为cookiestore把cookie放在arraylist里很容易被系统回收[1]。

  2.WebView会存储cookie在CookieManager,具体使用方式,后续的文章会讲这里不是重点。

  正常HttpClient中得Cookie是不能与WebView中得Cookie共享的所以这里需要一个中间变量(这里叫做CookieMap)来管理Cookie。每次请求的时候都要刷新CookieMap,我推荐的Cookie管理方式是只增加、修改不删除。每次请求完成都要进行一次Cookie同步,有的app要求保持登陆状态,所以也有必要把cookie放入Preference。

List<Cookie> cookieList = httpClient.getCookieStore().getCookies();
if (context == null || cookieList == null || cookieList.size() == 0) {
return;
}

SharedPreferences preferences = context.getSharedPreferences(Constant.HTTPHEAD, Context.MODE_PRIVATE);
Editor edit = preferences.edit();

for (Cookie cookie : cookieList) {
edit.putString(cookie.getName(), cookie.getValue());
httpCookiesMap.put(cookie.getName(), cookie);
}

edit.commit();

 

 

  在请求之前,如果要自己在header中setcookie的话那么就不要保留httpclient中的cookie否则容易造成给服务器提交的request的header中包含两个cookie的情况,有的会造成服务器混乱。

// 由于自行处理cookie所以要清理client管理的cookie否则容易出现两个cookie头的情况
httpClient.getCookieStore().clear();
String strHeader =getCookiesForHttpHeader(context);
request.setHeader(Constant.COOKIE, strHeader);
HttpResponse response = httpClient.execute(request);

  偶尔会碰到api和webview所做的请求在不同域的情况那么就要求重新设置cookie的域和path,这里鼓励把path范围设置的大一些否则有些请求可能得不到cookie。

cookieManager.setCookie(url, key + "=" + cookie.getValue() + ";domain=" + "xxxx.com"+";path=/");

  下面是当Logout的时候需要做得cookie清理工作,如果使用cookie来判断是否登录的话,则只清理本地cookiemap和Preference中得cookie是不够的。还需要清理掉webview中的对应的cookie。否则下次登陆依然是登陆状态。

// 清理内存cookie
httpCookiesMap.clear();
// 清理httpclientcookie
httpClient.getCookieStore().clear();
// 清理掉WebViewCookie
CookieManager.getInstance().removeAllCookie();
CookieSyncManager.getInstance().sync();

// 清理preferencecookie相关的项目
SharedPreferences preferences = context.getSharedPreferences(Constant.HTTPHEAD, Context.MODE_PRIVATE);
Editor editor = preferences.edit();
editor.remove(Constant.ACCOUNT);
editor.remove(Constant.NICKNAME);
editor.remove(Constant.PHPSESSID);
editor.commit();

  希望这篇文章对大家的工作有所帮助。接下来会写一篇关于httpclient配置的文章。

 [1].http://hc.apache.org/httpcomponents-client-ga/tutorial/html/statemgmt.html


本文链接: 关于安卓中的cookie管理,转载请注明。

SOA实施收益分析

$
0
0
远行科技自2007年开始即参加了中国移动集团SOA接口平台的建设和实施工作,在SOA规划咨询,建设实施方面有丰富的实践经验积累。对于SOA实施收益,先以某客户的一个真正业务背景进行分析:

业务场景:我们现在的工程项目管理,其规划,立项和工程实施计划在项目管理相关系统;工程物资采购在采购管理系统;审批在 OA系统,财务的信息又在ERP核心系统。做为领导要了解工程项目全貌,需要不断反复登录不同的系统。而且现在还存在同样一件事情要在不同系统多次重复处 理的情况。

解决思路:不实施SOA该问题很难解决。而SOA本身就是基于流程驱动IT的思路构建的平台。在前期数据集 成服务实施后,很容易通过服务组合实现跨越现有IT系统边界的BPM业务流程整合,并且通过SOA提供的管控平台实现流程的集中管理和监控。包括后续根据 业务调整流程也可以通过SOA的流程设计器快速灵活配置。

业务场景:MSS域的ERP系统向采购子系统提出了需要采购订单数据信息的数据集成和接口需求,究竟该如何做?现状是知道如何做,比如开发视图,接口表,或作个WebService,但是按照什么样的规范来做?如何保证接口的稳定和正确性不清楚。

解决思路:SOA解决方案是一整套的SOA服务识别,开发和接入规范,包括后续SOA服务管控机制。这也是远行科技多年SOA实践经验的一线积累。

业务场景:采购,项目管理,运维系统都再向ERP提同一个业务对象的接口需求,各个需求还有差异。同样一个接口反复开发,版本还无法一致。

解决思路:由于点对点连接,重复开发接口的现状是无法避免的,而且后续大量的不同版本的接口管理和运维工作量巨大。而SOA解决方案则是统一在分析流程基础上识别和定义服务,打破原来的点对点连接。

业务场景:ERP核心子系统开放了一个接口视图出去给其它的业务子系统。采购,项目管理,运维系统都在使用。究竟接口被使用了多少次,谁使用了,取走了多少数据,什么时间取走的数据我根本无法跟踪和监控。数据安全性很差。

解决思路:SOA解决方案是将接口实现为服务,对于每一个服务都可以独立进行访问授权和传输数据的安全性加密。通过通过服务运行监控能够看到每个服务的运行时间,输入输出数据等详细信息。

业务场景:ERP核心子系统向采购子系统反馈,上周给过来的一份采购订单数据有错误,采购子系统核查自己系统又反馈是正确的,双方无法确认问题源和责任方。

解决思路:SOA集成平台中,服务的每一次调用SOA集成平台都可以详细记录到调用的时间,调用的业务子系统,调用的具体数据情况。

业务场景:采购子系统不断的再向ERP核心子系统提交接口和数据集成的需求,都是流程走不通了,想到一个做一个。而且经常围绕一个采购订单业务对象不断在开发不同的数据接口。而且一个接口视图往往逻辑复杂,访问多张数据表关联才能够完成。

解决思路:SOA解决方案是通过业务流程的梳理识别和发现服务,确保没有服务遗漏。同时SOA解决方案中识 别的服务既包括了粗粒度的服务,也包括了细粒度的服务。满足流程的粗粒度的服务是由各个细粒度的服务组成的。细粒度的原子服务可以很好的进行复用。因此当 出现流程整合新需求的往往并不会开放新服务,而且组合已有的旧服务。

业务场景:我基于原有的数据接口方式和原有的IT子系统,不走SOA也能够实现流程整合,那么走SOA实现流程整合的收益在哪里?能够解决传统流程整合的什么问题?

解决思路:注意传统方式的流程整合,流程的整合实现是通过IT系统硬编码实现的,暂且不说开发工作量,其本身后续的扩展性和运维工作量就很大。其次流程整 合一般或跨越多个IT子系统,流程的全貌和流程进展情况没有一个地方可以全程跟踪和监控,流程虽然整合了但是流程没有实现可视化得监控。最后,为了流程整 合,需要多个IT子系统配合不断的需开发,实现和测试新的数据接口。而通过SOA方式本身就是流程驱动的服务发现,服务时细粒度的,流程整合需要的服务基 本在前期都已经识别,仅仅是通过对服务的组合,通过BPEL流程设计就可以实现流程整合。

下面再综述下SOA实施带来的业务收益和技术收益。

对于SOA平台项目建设的ROI(投资回报)计算往往是一种定性计算的过程,因为SOA项目的建设不仅仅是SOA集成平台的搭建已经已有的IT系统的改造,同时更重要的实现端到端业务流程的整合和商业变更。具体的项目建设收益分如下几点进行描述:

1.减少固定支出

SOA提供了四种基本收益:减少结合支出,提高资产再利用,提高商业灵活度以及降低商业风险。这四种核心收益会为这个组织的很多层面和部分带来收益,这取 决于这个将SOA应用于哪类商业问题。首选,实行松散结合方法将减少复杂度,从而减少综合和掌握分散环境计算的成本。尽管面对标准接口,如Web服务时, 结合成本将减少一些,但SOA的真正价值在于用粗颗粒,松散结构的服务取代了很小的细致间隔尺寸,从而可以比基于API的综合更方便的处理范围更更大的综 合。

使用SOA来减少综合支出的投资回报计算是相当直接的。SOA实施后我们可以将基于Web服务的SOA中的投资和一种传统的IT系统建设投资进行比较。具体固定支出减少方面如下:

  • SOA集成平台降低了IT资源和人力资源投入成本
  • 基于SOA的流程整合,降低了业务和流程变化造成的改造成本
  • SOA实施进一步优化管理流程,减低了管理本身成本
  • SOA规范和治理体系的建立,进一步降低后续IT系统运维成本

2.提高资产再利用

对于SOA项目的实施,不仅仅是减少企业的各种支出,更重要的是对对现有服务的再利用可以为寻找实施SOA的公司提供附加的投资回报。众所周知,一般企业 在为那些有持续变化的需求的项目构造新设备时花费的时间和预算都很少。缺乏发展新设备的重视的一部分原因在于这些新应用需要频繁产生且与之前已存在的应用 不相关,这会导致一个新的IT问题,这将导致必须综合新的成份,使我们之前提到综合的问题更加恶化。显然,建立新的应用时不仅需要减少开发成本,而且随着 时间的推移保持不变性。

SOA的一个重要收益在于使用者可以产生新的商业过程交与现在的服务进行合成。换句话说,浙江联通可以通过SOA集成平台提供的流程整合功能,不断的重新 整合和编排已有的服务,而不是重新开发新的IT系统和功能,通过复用以达到已有IT系统各种功能和服务的循环利用。由于这种方式可以创造新的服务,并且可 以循环利用,公司可以从他们为合成应用的投资中得到回报。因此,合成应用的开发作为SOA的杠杆的经济性将随公司创造并再重复利用的服务数量的增加而增 加。这有可能使得现在用于综合的70%的资金用于新的开发。公司在实施这种SOA的资产再利用获得的收益不仅仅是简化的综合带来的成本降低,而且改善了从 产品到市场的时间,更敏感的客房服务,总体员工数的减少以及更有能力进行外部采购或产生、实施服务。

3.增加商业活力

减少成本和增加重用为SOA提供了清楚的ROI,与之相比增加商业活力是SOA最有前途的收益同时也是最难量化的。综合简化和增加重用是以技术为中心的收 益,商业用户同时也期望从IT业获取更大的灵活性。与其一开始简单地构建所需的条件然后一头撞在长以月计的实现周期的IT“开发墙”上,商业用户更加想直 接控制他们的运作以便能够迅速地根据市场变化而改变他们的业务。

为计算商业活力所需的ROI方案着力于商业用户直接控制商业过程的精确度和管理的能力。通过面向服务的过程可以实现端到端流程的整合。流程的整合不仅仅是 企业内跨越了原有的IT系统边界,跨越了原有的业务部门便捷的流程整合,更重要的是通过SOA流程整合还能够进一步实现了企业上下游供应商和客户的流程整 合,通过这种方式显著提高了业务效率和业务全流程的管控能力,这些都应该是SOA投资所产生的商业利润。因此,利润不仅影响了底层公司的运作,同时也影响 着它的上游(产业)。增加的商业活力可能以获得浙江联通以前被认为不能取得的收入来源为结果,并且为浙江联通提供不同的途径为他们的供应商或者商业伙伴提 供利润以便获得新的重大的商业机遇。通过将 SOA的区域扩展到商业用户,可以将ROI作为一个整体发展到商业领域,而不是简单地作为IT业的一部分。

但是,计算SOA的商业活力的ROI是格外困难的,因为将要新增的IT资源是天然地不可预计的。毕竟,活力的全局点可能涉及不可预期的变化。因此,将商业 活力ROI限制在一个特定的范围是讲得通的,例如,在产品信息规则变化的情况下,商业伙伴和程序或者其他供应链角色,对应地有规律地修改。

4.降低业务风险

按照规则处理是提高业务活力的一种必不可少的方案,因为这种规则具有随意性,并且会随着时间的改变而改变。现在,像Sarbanes Oxley、PATRIOT 法案以及Base II等规则在一些IT实现的公司内部已经有了改变。如果不服从规则,浙江联通的经济状况以及主管人员的自由将会受到严重的负面影响。许多企业的业务操作并 不透明,所以他们不得不依靠制定一些聪明的决策计划来控制他们的风险,但却无视增加透明性的要求,这种透明性正是他们的规则所必需的。

对于SOA实施带来的技术收益如下:

SOA平台管理模式的优势

  • 采用平台中心集中和节点分布管理的模式,适应机构之间垂直和横向行政管理关系并存的需求;
  • 平台提供系统统一集中远程部署管理、完善的安装、远程服务组件部署、配置、远程监控等手段,保证平台高度的可管理性和维护性;
  • 系统支持多种应用管理模式,如集中控制管理和分级递阶控制管理等应用管理模式,适应机构纵向、横向、分级等多种管理模式的要求。

SOA平台软件架构的先进性、可扩展性

  • 采用完整、先进、成熟的软件技术和产品,充分利用中间件和企业服务总线(ESB)技术,采用完全分布式、事件驱动和面向服务(SOA)的架构设计;
  • 平台底层采用可靠数据传输的中间件技术,节点业务系统之间的交换采用端对端(P2P)的可靠数据安全传输机制;
  • 软件平台在架构方面保证了灵活的可扩展性,当节点和业务增加时,因为数据无须经过中央服务器,从而避免平台的效率瓶颈和中央服务器单点故障;
  • 平台采用可重用的服务组件化设计,服务组件及适配器可重用性高,并支持配置管理和分布式远程部署。

SOA平台的安全性优势

  • 基于底层的可靠数据传输的中间件技术,系统提供任何节点之间的可靠事件传输、断点续传等功能;
  • 系统支持传输数据压缩加密的技术,保证数据的保密性、完整性和有效性,并通过集成第三方提供的CA/PKI身份认证服务,可实现节点之间的安全身份认证。
  • 系统通过服务器备份和服务组件备份的两种备份机制,提供一定的容错能力与容灾能力,充分保证数据安全和系统的可靠性,重要数据的完整性、一致性和可恢复性;
  • 系统具有安全运行管理措施,提供了服务异常告警和安全日志的功能;
  • 系统平台提供了对业务数据(流程)的监控功能,以及使用工具来跟踪查找事件的功能。

SOA平台能够提供很好的互操作性、兼容性,有效地保护现有投资

  • 平台由Java语言开发,支持Windows、Linux/Unix不同的操作系统,并支持主流数据库系统的市场现行版本,包括Oracle、DB2、SQL Server、Sybase等;
  • 平台提供的预制适配服务组件,支持主流的应用服务器(J2EE 和.NET应用服务器等)软件市场现行版本,以及支持主流的消息中间件服务器(MQ, JMS Server)等产品,
  • 平台支持用不同的语言开发服务,如Java、C/C++、VB、C#等,并提供多种语言(Java、C/C++、VB、C#)的API集成接口,满足集成不同委办局异构系统的要求。
  • 平台系统具有强大的对现有各种异构系统的整合能力,有效地支持与各种消息中间件、各种异构数据库和不同语言开发的应用系统整合,最大限度地保护客户现有的投资。

遵循业界规范和开放性原则

开放性体现在平台架构和组件技术上,如采用面向服务的架构(SOA)和JMS、Web Services,JCA等通用组件标准。业界标准和开放性是保护客户投资的有效保障。

提供多种数据传输机制

提供同步传输、异步传输两种数据传输机制。支持多种通讯传输方式如HTTP(s)、异步可靠事件方式(JMS、Web Service等);提供穿透防火墙(逻辑隔离)的数据库、文件传输机制;

可扩展性、伸缩性强、部署机制灵活

随着信息化建设的发展,系统的扩展将是不可避免的,保护投资是系统设计需要考虑的。因此,提高系统的可扩展性、可维护性是提高系统性能、保护投资的重要手 段。 端对端(peer-to-peer)和面向服务(SOA)的分布式软件架构可充分保证平台的可扩展性,因为节点数的增加不会产生中央服务器的效率瓶颈。平 台提供集成一体化的服务组织工具,灵活构建电子商务/政务应用系统。变化是永恒的,集成一体化的流程建模、部署和管理工具,可以动态改变业务流程,适应企 业的需要。

SOA平台的高可靠性

平台系统底层基于成熟可靠的中间件技术,保证其高稳定性和可靠性。除了服务器热备份技术外,系统自动监测服务组件故障,提供服务组件级备份方案。
  青春就应该这样绽放   游戏测试:三国时期谁是你最好的兄弟!!   你不得不信的星座秘密

全文检索引擎Solr系列—–全文检索基本原理

$
0
0

场景:小时候我们都使用过新华字典,妈妈叫你翻开第38页,找到“坑爹”所在的位置,此时你会怎么查呢?毫无疑问,你的眼睛会从38页的第一个字开始从头至尾地扫描,直到找到“坑爹”二字为止。这种搜索方法叫做 顺序扫描法。对于少量的数据,使用顺序扫描是够用的。但是妈妈叫你查出坑爹的“坑”字在哪一页时,你要是从第一页的第一个字逐个的扫描下去,那你真的是被坑了。此时你就需要用到 索引。索引记录了“坑”字在哪一页,你只需在索引中找到“坑”字,然后找到对应的页码,答案就出来了。因为在索引中查找“坑”字是非常快的,因为你知道它的偏旁,因此也就可迅速定位到这个字。

那么新华字典的目录(索引表)是怎么编写而成的呢?首先对于新华字典这本书来说,除去目录后,这本书就是一堆没有结构的数据集。但是聪明的人类善于思考总结,发现每个字都会对应到一个页码,比如“坑”字就在第38页,“爹”字在第90页。于是他们就从中提取这些信息,构造成一个有结构的数据。类似数据库中的表结构:

word    page_no
---------------
坑        38
爹        90
...       ...

这样就形成了一个完整的目录(索引库),查找的时候就非常方便了。对于全文检索也是类似的原理,它可以归结为两个过程:1.索引创建(Indexing)2. 搜索索引(Search)。那么索引到底是如何创建的呢?索引里面存放的又是什么东西呢?搜索的的时候又是如何去查找索引的呢?带着这一系列问题继续往下看。

索引

Solr/Lucene采用的是一种反向索引,所谓 反向索引:就是从关键字到文档的映射过程,保存这种映射这种信息的索引称为反向索引

  • 左边保存的是字符串序列
  • 右边是字符串的文档(Document)编号链表,称为倒排表(Posting List)

字段串列表和文档编号链表两者构成了一个字典。现在想搜索”lucene”,那么索引直接告诉我们,包含有”lucene”的文档有:2,3,10,35,92,而无需在整个文档库中逐个查找。如果是想搜既包含”lucene”又包含”solr”的文档,那么与之对应的两个倒排表去交集即可获得:3、10、35、92。

索引创建

假设有如下两个原始文档:
文档一:Students should be allowed to go out with their friends, but not allowed to drink beer.
文档二:My friend Jerry went to school to see his students but found them drunk which is not allowed.
创建过程大概分为如下步骤:

一:把原始文档交给分词组件(Tokenizer)
分词组件(Tokenizer)会做以下几件事情(这个过程称为:Tokenize),处理得到的结果是词汇单元(Token)

  1. 将文档分成一个一个单独的单词
  2. 去除标点符号
  3. 去除停词(stop word)
    • 所谓停词(Stop word)就是一种语言中没有具体含义,因而大多数情况下不会作为搜索的关键词,这样一来创建索引时能减少索引的大小。英语中停词(Stop word)如:”the”、”a”、”this”,中文有:”的,得”等。不同语种的分词组件(Tokenizer),都有自己的停词(stop word)集合。经过分词(Tokenizer)后得到的结果称为词汇单元(Token)。上例子中,便得到以下 词汇单元(Token)
      "Students","allowed","go","their","friends","allowed","drink","beer","My","friend","Jerry","went","school","see","his","students","found","them","drunk","allowed"

二:词汇单元(Token)传给语言处理组件(Linguistic Processor)
语言处理组件(linguistic processor)主要是对得到的词元(Token)做一些语言相关的处理。对于英语,语言处理组件(Linguistic Processor)一般做以下几点:

  1. 变为小写(Lowercase)。
  2. 将单词缩减为词根形式,如”cars”到”car”等。这种操作称为:stemming。
  3. 将单词转变为词根形式,如”drove”到”drive”等。这种操作称为:lemmatization。

语言处理组件(linguistic processor)处理得到的结果称为 词(Term),例子中经过语言处理后得到的词(Term)如下:

"student","allow","go","their","friend","allow","drink","beer","my","friend","jerry","go","school","see","his","student","find","them","drink","allow"。

经过语言处理后,搜索drive时drove也能被搜索出来。 Stemming 和 lemmatization的异同:

  • 相同之处:
    1. Stemming和lemmatization都要使词汇成为词根形式。
  • 两者的方式不同:
    1. Stemming采用的是”缩减”的方式:”cars”到”car”,”driving”到”drive”。
    2. Lemmatization采用的是”转变”的方式:”drove”到”drove”,”driving”到”drive”。
  • 两者的算法不同:
    1. Stemming主要是采取某种固定的算法来做这种缩减,如去除”s”,去除”ing”加”e”,将”ational”变为”ate”,将”tional”变为”tion”。
    2. Lemmatization主要是采用事先约定的格式保存某种字典中。比如字典中有”driving”到”drive”,”drove”到”drive”,”am, is, are”到”be”的映射,做转变时,按照字典中约定的方式转换就可以了。
    3. Stemming和lemmatization不是互斥关系,是有交集的,有的词利用这两种方式都能达到相同的转换。

三:得到的词(Term)传递给索引组件(Indexer)

  1. 利用得到的词(Term)创建一个字典
    Term    Document ID
    student     1
    allow       1
    go          1
    their       1
    friend      1
    allow       1
    drink       1
    beer        1
    my          2
    friend      2
    jerry       2
    go          2
    school      2
    see         2
    his         2
    student     2
    find        2
    them        2
    drink       2
    allow       2
  2. 对字典按字母顺序排序:
    Term    Document ID
    allow       1
    allow       1
    allow       2
    beer        1
    drink       1
    drink       2
    find        2
    friend      1
    friend      2
    go          1
    go          2
    his         2
    jerry       2
    my          2
    school      2
    see         2
    student     1
    student     2
    their       1
    them        2
  3. 合并相同的词(Term)成为文档倒排(Posting List)链表
    • Document Frequency:文档频次,表示多少文档出现过此词(Term)
    • Frequency:词频,表示某个文档中该词(Term)出现过几次

对词(Term) “allow”来讲,总共有两篇文档包含此词(Term),词(Term)后面的文档链表总共有两个,第一个表示包含”allow”的第一篇文档,即1号文档,此文档中,”allow”出现了2次,第二个表示包含”allow”的第二个文档,是2号文档,此文档中,”allow”出现了1次

至此索引创建完成,搜索”drive”时,”driving”,”drove”,”driven”也能够被搜到。因为在索引中,”driving”,”drove”,”driven”都会经过语言处理而变成”drive”,在搜索时,如果您输入”driving”,输入的查询语句同样经过分词组件和语言处理组件处理的步骤,变为查询”drive”,从而可以搜索到想要的文档。

搜索步骤

搜索”microsoft job”,用户的目的是希望在微软找一份工作,如果搜出来的结果是:”Microsoft does a good job at software industry…”,这就与用户的期望偏离太远了。如何进行合理有效的搜索,搜索出用户最想要得结果呢?搜索主要有如下步骤:

一:对查询内容进行词法分析、语法分析、语言处理

  1. 词法分析:区分查询内容中单词和关键字,比如:english and janpan,”and”就是关键字,”english”和”janpan”是普通单词。
  2. 根据查询语法的语法规则形成一棵树

  3. 语言处理,和创建索引时处理方式是一样的。比如:leaned–>lean,driven–>drive

二:搜索索引,得到符合语法树的文档集合
三:根据查询语句与文档的相关性,对结果进行排序

我们把查询语句也看作是一个文档,对文档与文档之间的相关性(relevance)进行打分(scoring),分数高比较越相关,排名就越靠前。当然还可以人工影响打分,比如百度搜索,就不一定完全按照相关性来排名的。

如何评判文档之间的相关性?一个文档由多个(或者一个)词(Term)组成,比如:”solr”, “toturial”,不同的词可能重要性不一样,比如solr就比toturial重要,如果一个文档出现了10次toturial,但只出现了一次solr,而另一文档solr出现了4次,toturial出现一次,那么后者很有可能就是我们想要的搜的结果。这就引申出权重(Term weight)的概念。

权重表示该词在文档中的重要程度,越重要的词当然权重越高,因此在计算文档相关性时 影响力就更大。通过词之间的权重得到文档相关性的过程叫做 空间向量模型算法(Vector Space Model)

影响一个词在文档中的重要性主要有两个方面:

  • Term Frequencey(tf),Term在此文档中出现的频率,ft越大表示越重要
  • Document Frequency(df),表示有多少文档中出现过这个Trem,df越大表示越不重要
    物以希为贵,大家都有的东西,自然就不那么贵重了,只有你专有的东西表示这个东西很珍贵,权重的公式:

空间向量模型

文档中词的权重看作一个向量

Document = {term1, term2, …… ,term N}
Document Vector = {weight1, weight2, …… ,weight N}

把欲要查询的语句看作一个简单的文档,也用向量表示:

Query = {term1, term 2, …… , term N}
Query Vector = {weight1, weight2, …… , weight N}

把搜索出的文档向量及查询向量放入N维度的空间中,每个词表示一维:

夹角越小,表示越相似,相关性越大

参考: http://www.cnblogs.com/guochunguang/articles/3641008.html

相关文章

谈CIO思考之重点

$
0
0
在这里主要针对中大型企业有专门的IT部门和独立开发运维团队的情况,对于这种企业的CIO,核心的一些思考点在哪里,和常规软件企业又有哪些差异?

对于企业IT部门是成本中心,在开源节流上,利润中心的重要性和关注度还是远远高于成本中心,这也是很多企业IT部门往往不受重视的原因,CIO本身也没有太多的决策权,在本身没有太多独立开发能力时候更多仅仅是一个运维中心的角色。那么对于一个大中型企业的CIO,核心的思考应该包括哪些内容?

个人理解首先还是IT价值的显性化,即如何让业务部门管理,执行各层人员感受到通过信息化规划,建设和实施,切实带来了工作效率的提升,业务价值能力的提升。业务上的一些流程优化,好的管理举措等如何能够通过IT系统更好的固化和高效执行。对于IT价值的显性化最需要考虑的仍然是两大方便,一个是成本降低,一个是业务敏捷性的增强。这两点往往都很难完全量化评估,但是又不能全部定性分析。谈到提升就一定有比较,即IT类应用实施前后的比较,业务绩效的KPI通过分解后,有一部分即是IT系统所带来的贡献。

同时随着企业管理的精细化,更多管理需要业务运作数据来支撑,以方便进行业务分析和管控,而这些也是IT系统发挥价值的一个重点,业务管控分解的业务KPI和绩效分析,最终落到各个IT系统随时随地的采集数据并汇总,以提供业务分析之用。企业的IT系统规划和建设,很容易犯的毛病就是盲目的照搬其它企业的最佳实践而忽视了自身的业务背景和管控需求,或者说在业务能力不足的时候上了大而全的IT系统,期待通过IT系统来倒退业务变革是相当不现实的做法。

其次,IT部门是一个服务部门,企业内的各个业务部门就是客户,那么IT建设的系统如何在内部做好运营以提升客户满意度就相当关键了。对于运营本身包括两个方面的内容,其一是IT类系统在内部的推广和宣传,其二是IT系统内部的运维服务。即使是服务内部客户,IT部门建设的系统也应该像一个完整的产品样,需要考虑在内部如何策划和营销,如何解决系统刚开始实施一系列的问题,很多重要IT系统往往一开始是高层强制推,但是如果业务部门消极抵制也很难真正达到效果。所以很多时候IT部门应该和业务管理部门在一个战线上,要借业务部门之力进行联合策划和产品推广。运维服务就更加重要了,内部的IT服务热线,问题管理和跟踪解决闭环,内部服务满意度评估等,唯一需要考虑的就是为内部客户提供真正高可用性的IT系统。

再次,对于信息化规划,我们一直在谈的重点就是业务驱动IT,通过IT建设来实现业务价值和能力提升,但是现实情况往往更多的还是业务和IT脱节,IT对整个业务价值链的支撑出现断点或问题。要么是业务人员不懂IT,要么是IT人员不熟悉业务,对于大中型企业的内部IT,一定要培养既熟悉业务,又熟悉IT的系统分析员或叫业务分析和建模人员。这类人员往往需要比业务人员更加熟悉端到端的业务,不一定要精通到每个业务细节,但是必须要能够更好的审视全局。业务部门和IT部门人员都朝前走一步,包括形成跨部门的虚拟运作团队,成立专门的流程&IT部门,都可以较好的解决这个问题。而我们常说的基于EA企业架构的信息化规划,正好也是将业务和IT,流程和数据进一步很好的融合的表现。

最后,作为内部的IT部门,自身的管理能力和团队成熟度提升就相当重要了,在这里面涉及到产品规划,CMMI,软件工程,IT项目管理,ITIL或Cobit等多方面的知识和方法体系。一个成熟的IT部门一定不是疲于奔命的应对业务需求,而是应该逐步形成按产品规划,版本研发和实施,部署运维,需求和问题管理等一整套的方法进行运转。很多非IT类企业的信息化部门,往往较少接触到IPD或CMMI,IT项目管理等一整套的业界做法,而是自己闭门造车。而实际情况是IT管理发展到现在已经相当成熟,需要的是借鉴他人经验,再结合自身实际情况进行裁剪,逐步推荐内部IT管理和流程的规范化。

  青春就应该这样绽放   游戏测试:三国时期谁是你最好的兄弟!!   你不得不信的星座秘密

为什么不记录慢查询?

$
0
0
㈠ 背景介绍:
  
  2014/8/18 13点37分收到前端说反馈有玩家掉线情况,检查CPU、慢查询、DB请求量,并未发现异常,DB表现一如往常。


㈡ 定位原因:

INSERT INTO t (col1, col2, col3, col4, col5, col6, col7) VALUES ('3532082239485507011_130_99', '130_99', 130, 99, 3532082239485507011, 2172353000317425008, 29078) 

这个长事务执行 1个多小时没有退出,Kill 掉对应的进程,程序前端恢复正常


㈢ 处理思路:

  ⑴ 查询视图

select trx_id,trx_state,trx_started,trx_requested_lock_id,trx_weight,trx_mysql_thread_id from information_schema.innodb_trx where trx_state='RUNNING';

  ⑵ show engine innodb status\G; 关注Transactions部分提取SQL及事务信息
  

㈣ 我的疑问:


为什么这条执行了1个多小时的SQL没有被记录到慢查询日志中呢??


㈤ 原来如此:


Query_time - Lock_time > long_query_time  <===记录
Query_time - Lock_time < long_query_time  <===不记录


㈥ 模拟场景:


⑴ Query_time - Lock_time > long_query_time

Session_A:

mysql> begin;
Query OK, 0 rows affected (0.00 sec)

mysql> select emp_no,hire_date from employees where emp_no=10170 for update;
+--------+------------+
| emp_no | hire_date  |
+--------+------------+
|  10170 | 1986-01-02 |
+--------+------------+
1 row in set (0.00 sec)

Session_B:

mysql> select emp_no,hire_date,sleep(3) from employees where emp_no=10170 for update;


过段时间在A做commit,B会执行、并被记录到slow log中:

# Time: 140818 22:37:31
# User@Host: root[root] @ localhost []  Id:     1
# Query_time: 3.049016  Lock_time: 0.018891 Rows_sent: 1  Rows_examined: 1
use employees;
SET timestamp=1408372651;
select emp_no,hire_date,sleep(3) from employees where emp_no=10170 for update;




⑵ Query_time - Lock_time < long_query_time

Session_A:

mysql> begin;
Query OK, 0 rows affected (0.00 sec)

mysql> select emp_no,hire_date from employees where emp_no=10170 for update;
+--------+------------+
| emp_no | hire_date  |
+--------+------------+
|  10170 | 1986-01-02 |
+--------+------------+
1 row in set (0.00 sec)

Session_B:

mysql> select emp_no,hire_date from employees where emp_no=10170 for update;

过段时间在A做commit,B会执行、但不会被记录到slow log中


㈦ 我的收获:

我们日常做性能剖析实际上应该包括2个方面:

1)基于执行时间的分析

2)基于等待时间的分析


By water

Good Luck!


作者:linwaterbin 发表于2014-8-18 23:24:40 原文链接
阅读:81 评论:0 查看评论

跨浏览器resize事件分析

$
0
0

resize事件

原生事件分析

window一次resize事件:

  • IE7 触发3次, IE8 触发2次, IE9 触发1次, IE10 触发1次

  • Chrome 触发1次

  • FF 触发2次
  • Opera 触发1次
  • Safari 触发1次

场景分析

  • window resize时,部分组件需要重置大小(一次);部分组件不需要重置大小;

开源库分析

优点:使用简便

  $('#div1').on('resize', function (e) {
    console.log('[div1] resize');
  })
  $('#div1').resize(function (e) {
    console.log('[div1] resize2');
  });

缺点:内部使用轮询,性能堪忧

function loopy() {
    // Start the polling loop, asynchronously.
    timeout_id = window[ str_setTimeout ](function(){
      // Iterate over all elements to which the 'resize' event is bound.
      elems.each(function(){
        var elem = $(this),
          width = elem.width(),
          height = elem.height(),
          data = $.data( this, str_data );

        // If element size has changed since the last time, update the element
        // data store and trigger the 'resize' event.
        if ( width !== data.w || height !== data.h ) {
          elem.trigger( str_resize, [ data.w = width, data.h = height ] );
        }
      });
      // Loop.
      loopy();
    }, jq_resize[ str_delay ] );
};

优点:分Debounced和Throttled两种类型,类型明确

缺点:使用不算简易

$(window).on("debouncedresize", function( event ) {
    // Your event handler code goes here.
});

// or...
$(window).on("throttledresize", function( event ) {
    // Your event handler code goes here.
});

// unbind at will
$(window).off( "debouncedresize" );

结论

大多数场景使用jquery-smartresize的Debounced即可满足一次调用即可

作者:spy19881201 发表于2014-8-18 22:21:12 原文链接
阅读:0 评论:0 查看评论

java序列化与反序列化以及浅谈一下hadoop的序列化

$
0
0

1、什么是序列化和反序列化

神马是序列化呢,序列化就是把 内存中的对象的状态信息,转换成 字节序列以便于存储(持久化)和网络传输。(网络传输和硬盘持久化,你没有一定的手段来进行辨别这些字节序列是什么东西,有什么信息,这些字节序列就是垃圾)。

反序列化就是将收到 字节序列或者是硬盘的持久化数据,转换成 内存中的对象

2、JDK的序列化

JDK的序列化只有实现了serializable接口就能实现序列化与反序列化,但是记得一定要加上序列化版本ID serialVersionUID 
这个是识别序列化的之前那个类的到底是哪一个?我们显示这个序列化版本ID的目的就是为了:

1) 在某些场合,希望类的不同版本对序列化兼容,因此需要确保类的不同版本具有相同的serialVersionUID;

2) 在某些场合,不希望类的不同版本对序列化兼容,因此需要确保类的不同版本具有不同的serialVersionUID。

java的序列化算法要考虑到下面这些东西:

◆将对象实例相关的类元数据输出。

◆递归地输出类的超类描述直到不再有超类。

◆类元数据完了以后,开始从最顶层的超类开始输出对象实例的实际数据值。

◆从上至下递归输出实例的数据

所以java的序列化确实很强大,序列化后得到的信息也很详细,所以反序列化就so easy.
但是这样做也有它的坏处,序列化后很占内存,所以不一定详细就是好处,简单有时也是不错的。
在hadoop中,hadoop实现了一套自己的序列化框架,hadoop的序列化相对于JDK的序列化来说是比较简洁的。在集群中信息的传递主要就是靠这些序列化的字节序列来传递的所以更快速度更小的容量就变得非常地重要了。
说了太多的废话,还是扯回JDK的序列化吧。下面我们看一下在JDK中式如何实现序列化的。

首先我们有一个需要序列化的类如下(必须实现serializable接口)
import java.io.Serializable;

public class Block implements Serializable{

	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;

	private int id;
	private String name;

	public int getId() {
		return id;
	}

	public void setId(int id) {
		this.id = id;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public Block(int id, String name) {
		this.id = id;
		this.name = name;
	}

}

下面我们来测试一下序列化的结果:
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;

public class TestSerializable {
	public static void main(String[] args) throws IOException,
			ClassNotFoundException {
		//将序列化化的数据写到文件out里面(持久化)
		FileOutputStream fos = new FileOutputStream("./out");
		ObjectOutputStream oos = new ObjectOutputStream(fos);
		for (int i = 0; i < 100; i++) {
			Block b = new Block(i, "B"+i);
			oos.writeObject(b);
		}
		oos.flush();
		oos.close();
		//读出一个序列化的对象的字节序列(^..^)就是反序列化
		FileInputStream fis = new FileInputStream("./out");
		ObjectInputStream ois = new ObjectInputStream(fis);
		Block b2 = (Block) ois.readObject();
		ois.close();
		System.out.println(b2.getName());
	}
}

测试的结果:(取出第一个对象的name)
B0
生成一百个对象的持久化数据的大小是:1.60 KB (1,643 字节)一个对象平均16个字节,该类只有两个字段一个是int,一个字符串但是字符串的长度为2,所以我们可以感受到这冗余还是挺大的。

3、hadoop的序列化

hadoop的序列化的特点是:

1、紧凑:由于带宽是集群中信息传递的最宝贵的资源所以我们必须想法设法缩小传递信息的大小,hadoop的序列化就为了更好地坐到这一点而设计的。

2、对象可重用:JDK的反序列化会不断地创建对象,这肯定会造成一定的系统开销,但是在hadoop的反序列化中,能重复的利用一个对象的readField方法来重新产生不同的对象。

3、可扩展性:当前hadoop的序列化有多中选择
*可以利用实现hadoop的Writable接口。
*使用开源的序列化框架protocol Buffers,Avro等框架。
     我们可以注意到的是hadoop2.X之后是实现一个叫YARN的云操作系统,所有应用(如mapreduce,或者其他spark实时或者离线的计算框架都可以运行在YARN上),YARN还负责对资源的调度等等。
YARN的序列化就是用Google开发的序列化框架protocol Buffers,proto目前支持支持三种语言C++,java,Python所以RPC这一层我们就可以利用其他语言来做文章,满足其他语言开发者的需求。
我屮艸芔茻,扯得有点远。
回到hadoop原生的序列化,hadoop原生的序列化类需要实现一个叫Writeable的接口,类似于serializable接口。
还有hadoop也为我们提供了几个序列化类,他们都直接或者间接地实现了Writable接口。如:IntWritable,LongWritable,Text等等。
实现Writable接口必须实现两个方法:write(DataOutputStream out);readField(DataInputStream in)方法。
下面是一个hadoop的序列化例子:
package hadoop;

import java.io.ByteArrayOutputStream;
import java.io.DataInput;
import java.io.DataInputStream;
import java.io.DataOutput;
import java.io.DataOutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;

import org.apache.hadoop.io.Text;
import org.apache.hadoop.io.Writable;
import org.junit.Test;

public class Testhadoop_serializable_writable {
	@Test
	public void serializable() throws IOException {
		ByteArrayOutputStream out = new ByteArrayOutputStream();
		DataOutputStream dataOut = new DataOutputStream(out);
		FileOutputStream fos = new FileOutputStream("./hadoop_out");
		for (int i = 0; i < 10; i++) {
			Text t1 = new Text(String.valueOf(i));
			Text t2 = new Text("mw");
			MyWritable mw = new MyWritable(t1,t2);
			mw.write(dataOut);
		}
		dataOut.close();
		fos.write(out.toByteArray());
		fos.flush();
		fos.close();

		FileInputStream fis = new FileInputStream("./hadoop_out");
		DataInputStream dis = new DataInputStream(fis);
		for (int i = 0; i < 10; i++) {
			MyWritable mw = new MyWritable(new Text(), new Text());
			mw.readFields(dis);
			System.out.println(mw.getId() + " " + mw.getName());
		}

	}
}

class MyWritable implements Writable {
	private Text id;
	private Text name;

	public MyWritable(Text id, Text name) {
		super();
		this.id = id;
		this.name = name;
	}

	public synchronized Text getId() {
		return id;
	}

	public synchronized void setId(Text id) {
		this.id = id;
	}

	public synchronized Text getName() {
		return name;
	}

	public synchronized void setName(Text name) {
		this.name = name;
	}

	@Override
	public void write(DataOutput out) throws IOException {
		id.write(out);
		name.write(out);
	}

	@Override
	public void readFields(DataInput in) throws IOException {
		id.readFields(in);
		name.readFields(in);
	}

}

我们可以看到我们实现的自己序列化类MyWritable。他有两个字段都是Text,Text是hadoop自带的序列化类,可以看做字符串(类似吧)吧?!
write()和readField()用到的是回调函数,将流(DataOutputStream DataInputStream)写出,或者读出,都是用到回调函数(hook(钩子))。

上面的运行结果如下:
生成的字节序列:

命令行结果:

完!





















作者:oChenXiaoZuo1 发表于2014-8-18 20:24:06 原文链接
阅读:0 评论:0 查看评论

html5拖拽图片批量ajax无刷新进度上传

$
0
0

1、前端拖拽图片

之前有篇文章说到HTML5的拖拽( dragdrop,详见: /post/jquery-plugin-1-jquery-drag-and-html5-draggable-api-and-compatibility.html)。这里说的拖拽图片只是弱化了拖的概念,而强化了拽的操作。从浏览器外部拖动一个文件到浏览器中来,如:

拖动文件到浏览器之后,就会打开浏览器支持的文件,如常用的txt、图片等,如下:

操作如上常用文件,一般都有默认行为来处理这样的事件。这里说的拖拽上传也是一个道理,就是要做的是从浏览器外部拖动文件到浏览器中来,并且在当前页面上传该文件。在表面上看来,这个方法很适合用户体验,但实际情况是用户体验急剧下降。因为大多数人浏览网页的时候是全最大化窗口查看的,而如果要拖拽上传文件的话,那么就需要把浏览器窗口后,非常的麻烦。就比如wordpress的添加媒体功能,也是支持拖拽上传图片的,可用过的人又有多少呢?

倒还不如点击选择图片操作来的更加快捷,不过本文旨在说明问题。也许有更好玩的例子没有被发现而已,在此只做抛砖引玉。

1.1、拖拽文件的files对象

在拖拽文件到浏览器,我们需要处理这些文件。

$.fn.listen=function(type,fn){
	returnthis.each(function(){
		$(this)[0].addEventListener(type,function(e){
			if(!fn.call($(this),e)){
				e.stopPropagation();
				e.preventDefault();
			}
		},0);
	});
}
$(document).bind("dragenter",function(){
	returnfalse;
}).bind("dragover",function(){
	returnfalse;
}).listen("drop",function(e){
	// 这里处理拖拽进来的文件(们)
});

 

如上,可能细心的朋友发现了一些不同。那就是document使用了两个方法来绑定事件, dragenterdragover使用jquery的 bind方法绑定,而drop事件却使用自定义的 listen方法绑定,这是为什么呢?因为jquery的事件绑定,为了兼容操作处理的事件的参数event,删减了一些属性使其在各个浏览器都保持一致。而此处用的是event的HTML5属性,恰巧是不兼容低级浏览器的,所以使用jquery的 bind方法是无法获取的。我们可以来验证一下这个说法:

$(document).bind("dragenter",function(){
	returnfalse;
}).bind("dragover",function(){
	returnfalse;
}).bind("drop",function(e){
	console.log(e);
}).listen("drop",function(e){
	console.log(e);
});

 

拖拽文件到这个页面,在浏览器控制台得到两个不尽相同的对象:

如图示黄色背景的 dataTransfer是浏览器默认的event所独有的,而我们此处用的 files对象这是在这里面。

console.log(e.dataTransfer.files);

 

在浏览器控制台输出了:

由图示可知,该files对象是一个数组。 值得注意的是,该files对象只读。可以接收到文件的基本信息(最后修改时间、文件名称、大小、类型),我们就可以在客户端来处理上传文件之前的操作。比如限制文件必须为图片格式、文件的大小不能超过100KB。

$(document).bind("dragenter",function(){
	returnfalse;
}).bind("dragover",function(){
	returnfalse;
}).listen("drop",function(e){
    var files=e.dataTransfer.files;
    var error='';
    for(var i=0;i<files.length;i++){
    console.log(files[i]);
    if(files[i].size>1024*100)error+='第'+(i+1)+'个文件超过大小限制\n';
    if(!/image/i.test(files[i].type))error+='第'+(i+1)+'个文件不是图片格式\n';
}
if(error)alert(error);
});

 

会弹出如下警告:

1.2、处理文件的FileReader对象

用户拖拽了符合我们预期的文件,我们就需要对其进行操作。比如本文要做的是用户必须上传100KB以内的图片类型文件。在获取到files对象之后,我们要使用 FileReader对象来读取file的文件(该对象人如其名)。

$(document).bind("dragenter",function(){
	returnfalse;
}).bind("dragover",function(){
	returnfalse;
}).listen("drop",function(e){
    var files=e.dataTransfer.files;
    var error='';
    for(var i=0;i<files.length;i++){
    if(files[i].size>1024*100)error+='第'+(i+1)+'个文件超过大小限制\n';
    if(!/image/i.test(files[i].type))error+='第'+(i+1)+'个文件不是图片格式\n';
}
// 有错误抛弃
if(error){
    alert(error);
    return;
}
// 处理文件队列
for(var i=0;i<files.length;i++){
	read(files[i]);
}
});
function read(file){
	var reader=newFileReader();
 	reader.onload=function(e){
		$("body").append('<img src="'+e.target.result+'" alt="" />');
	}
	reader.readAsDataURL(file);
}

 

在拖拽合适大小的图片文件到该页面之后:

FileReader对象是干嘛的呢?它可以读取文件,并进行相应的操作,涉及到安全问题,该操作不会对图片的源文件产生影响。该对象有如下属性和方法以及事件:

  • 属性:为空
  • 方法:
    • about:中断文件读取
    • readAsBinaryString:读取文件为二进制
    • readAsDataURL:读取文件dataUrl(本例用到的)
    • readAsText:读取文件为文本
  • 事件:
    • onabort:读取文件中断时触发
    • onerror:读取文件出错时触发
    • onload:读取文件成功时触发(本例用到的)
    • onloadstart:读取文件开始时触发
    • onprogress:读取文件中时一直触发
    • onloadend:读取文件结束时触发(成功和失败都会触发,如 jquery.ajaxcomplete

在监听到文件读取成功时,该事件参数e有 e.target.result指向的是读取的结果(即本例描述的文件的二进制url)。

1.3、处理表单的FormData对象

选到了合适大小的图片文件,我们就需要把这些文件无刷新上传到服务器,但我们如何发送这些图片到后端呢?传统的ajax方法一直是发送文本格式(Content-Type:application/x-www-form-urlencoded)而发送图片这些大文件需要用到浏览器的原生表单(Content-Type:multipart/form-data)。所幸的是,HTML5的支持的 FromData属性可以帮忙完成这一个过程,即封装图片成表单数据以用于提交到后端。

FormData类似于 jquery.serialize,jquery这一次又走在了前列。不过 FormDataserialize要强大一点,它不仅可以在提交表单数据里增加纯文本也可以增加图片等二进制数据。其基本使用方法是:

  1. var form1=newFormData();
  2. form1.append("name1","value1");
  3. form1.append("name2","value2");
  4. form1.append("file",file对象);

如上,其作用相当于:

  1. <form>
  2. <inputtype="text"name="name1"value="value1">
  3. <inputtype="text"name="name2"value="value2">
  4. <inputtype="file"name="file"id="">
  5. </form>

所以接着1.2继续,把合适的图片组装成form数据便于异步传输。

  1. $(document).bind("dragenter",function(){
  2. returnfalse;
  3. }).bind("dragover",function(){
  4. returnfalse;
  5. }).listen("drop",function(e){
  6. var files=e.dataTransfer.files;
  7. var error='';
  8. for(var i=0;i<files.length;i++){
  9. if(files[i].size>1024*100)error+='第'+(i+1)+'个文件超过大小限制\n';
  10. if(!/image/i.test(files[i].type))error+='第'+(i+1)+'个文件不是图片格式\n';
  11. }
  12. // 有错误抛弃
  13. if(error){
  14. alert(error);
  15. return;
  16. }
  17. // 处理文件队列
  18. for(var i=0;i<files.length;i++){
  19. read(files[i]);
  20. }
  21. // 组装成表单数据
  22. var formData=newFormData();
  23. for(var i=0;i<files.length;i++){
  24. formData.append('files[]',files[i]);
  25. }
  26. });
  27. // 读取图片
  28. function read(file){
  29. var reader=newFileReader();
  30. reader.onload=function(e){
  31. $("body").append('<img src="'+e.target.result+'" alt="" />');
  32. }
  33. reader.readAsDataURL(file);
  34. }

注:以上代码仅供示例,上述的 formData.append('files[]',...),有中括号表示多文件批量上传。

1.4、ajax上传的XMLHttpRequest对象

有了表单数据,我们就可以使用异步传输发送给服务端。

  1. $(document).bind("dragenter",function(){
  2. returnfalse;
  3. }).bind("dragover",function(){
  4. returnfalse;
  5. }).listen("drop",function(e){
  6. var files=e.dataTransfer.files;
  7. var error='';
  8. for(var i=0;i<files.length;i++){
  9. if(files[i].size>1024*100)error+='第'+(i+1)+'个文件超过大小限制\n';
  10. if(!/image/i.test(files[i].type))error+='第'+(i+1)+'个文件不是图片格式\n';
  11. }
  12. // 有错误抛弃
  13. if(error){
  14. alert(error);
  15. return;
  16. }
  17. // 处理文件队列
  18. for(var i=0;i<files.length;i++){
  19. read(files[i]);
  20. }
  21. // 组装成表单数据
  22. var formData=newFormData();
  23. for(var i=0;i<files.length;i++){
  24. formData.append('files[]',files[i]);
  25. }
  26. // 异步传输
  27. ajax();
  28. });
  29. // 读取图片
  30. function read(file){
  31. var reader=newFileReader();
  32. reader.onload=function(e){
  33. $("body").append('<img src="'+e.target.result+'" alt="" />');
  34. }
  35. reader.readAsDataURL(file);
  36. }
  37. // 异步传输
  38. function ajax(formData){
  39. var xhr=newXMLHttpRequest();
  40. xhr.open("post","upload.php");
  41. xhr.onload=function(){
  42. alert("上传完成!");
  43. }
  44. xhr.send(formData);
  45. }

如果上传不出错的话,那么在上传结束的时候会弹出“上传完成!”的确认框。

1.5、ajax上传的进度

因为上传文件和上传纯文本,其数据量不是一个级别的,所以为了友好的用户体验,我们需要实时告诉用户上传的进度目前是多少。可喜的是,HTML5已经帮我们完成这个步骤,可以这么做来实时获取当前上传的进度:

  1. // 异步传输
  2. function ajax(formData){
  3. var xhr=newXMLHttpRequest();
  4. xhr.open("post","upload.php");
  5. xhr.onload=function(){
  6. alert("上传完成!");
  7. }
  8. // 上传进度
  9. xhr.upload.onprogress=function(e){
  10. if(e.lengthComputable){
  11. var percent =(e.loaded / e.total *100|0)+"%";
  12. console.log(percent);
  13. }
  14. }
  15. xhr.send(formData);
  16. }

关于 XMLHttpRequest的更多使用方法,这里不做赘述,可以参考文章末尾的参考资料。

1.6、完整的源代码

  1. <!doctype html>
  2. <htmllang="en">
  3. <head>
  4. <metacharset="UTF-8">
  5. <title>拖拽图片到这里来并上传</title>
  6. <style>
  7. h2 small{
  8. color:#888;
  9. font-weight: normal;
  10. margin-left:30px;
  11. font-size:80%;
  12. }
  13. .box{
  14. border:1px solid #ccc;
  15. background:#f5f5f5;
  16. padding:10px;
  17. margin-bottom:20px;
  18. }
  19. .box2{
  20. border:1px solid #EB9D45;
  21. background:#FFF2E3;
  22. padding:10px;
  23. margin-bottom:20px;
  24. }
  25. #progress{
  26. margin-left:10px;
  27. }
  28. .box img,
  29. .box2 img{
  30. max-height:100px;
  31. height:auto;
  32. width:auto;
  33. padding:2px;
  34. border:1px solid #ddd;
  35. background:#fff;
  36. margin-right:20px;
  37. margin-bottom:20px;
  38. }
  39. </style>
  40. </head>
  41. <body>
  42. <divclass="box">
  43. <h2>拖拽图片到这里来<smallid="message"></small></h2>
  44. <divid="box"></div>
  45. </div>
  46. <p>原文:<ahref="/post/undefined.html700">/post/undefined.html700</a></p>
  47. <divclass="box2">
  48. <h2>已上传的图片<smallid="progress"></small></h2>
  49. <divid="box2"></div>
  50. </div>
  51. <scriptsrc="http://libs.baidu.com/jquery/2.0.3/jquery.min.js"></script>
  52. <script>
  53. $.fn.listen=function(type,fn){
  54. returnthis.each(function(){
  55. $(this)[0].addEventListener(type,function(e){
  56. if(!fn.call($(this),e)){
  57. e.stopPropagation();
  58. e.preventDefault();
  59. }
  60. },0);
  61. });
  62. }
  63. var $box=$("#box");
  64. var $message=$("#message");
  65. var $box2=$("#box2");
  66. var $progress=$("#progress");
  67. var isuploading=0;
  68. var hasBtSize=0;
  69. var errorArray=[];
  70. $(document).bind("dragenter",function(){
  71. returnfalse;
  72. }).bind("dragover",function(){
  73. returnfalse;
  74. }).listen("drop",function(e){
  75. if(isuploading)return;
  76. var error='';
  77. var num=1;
  78. var files=e.dataTransfer.files;
  79. var j=files.length;
  80. $box.empty();
  81. for(var i =0; i < j; i++){
  82. (function(i){
  83. var reader =newFileReader();
  84. reader.onload =function(event){
  85. $box.append("<img src='"+ event.target.result +"' /> ");
  86. if(files[i].size>1024*400||!/image/.test(files[i].type)){
  87. errorArray.push(num);
  88. }
  89. num++;
  90. if(num>j){
  91. if(errorArray.length){
  92. error=errorArray.join(',');
  93. $message.html("其中第 "+error+" 个文件大小超过限制或不是图片,本次上传已被取消。");
  94. errorArray=[];
  95. return;
  96. }
  97. upload(files);
  98. }
  99. };
  100. reader.readAsDataURL(files[i]);
  101. })(i);
  102. }
  103. returnfalse;
  104. });
  105. function upload(files){
  106. if(isuploading)return;
  107. isuploading=1;
  108. var formData=newFormData();
  109. var isComplete=0;
  110. for(var i=0; i <files.length; i++){
  111. formData.append("files[]",files[i]);
  112. };
  113. var xhr=newXMLHttpRequest();
  114. xhr.open('post','upload.php');
  115. xhr.onload=function(){
  116. $progress.html("上传完成!");
  117. };
  118. xhr.onreadystatechange=function(){
  119. if(xhr && xhr.readyState ===4){
  120. status = xhr.status;
  121. if(!isComplete && status >=200&& status <300|| status ===304){
  122. isComplete =true;
  123. var json=$.parseJSON(xhr.responseText);
  124. $box2.empty();
  125. $box.empty();
  126. $message.empty();
  127. $.each(json,function(key,val){
  128. $box2.append("<img src='"+ val +"' />");
  129. });
  130. isuploading=0;
  131. }elseif(!isComplete){
  132. isComplete =true;
  133. $box.html("网络错误!");
  134. isuploading=0;
  135. }
  136. xhr =null;
  137. }
  138. }
  139. xhr.upload.onprogress =function(event){
  140. if(event.lengthComputable){
  141. var percent =(event.loaded / event.total *100|0)+"%";
  142. $progress.html(percent);
  143. }
  144. }
  145. xhr.send(formData);
  146. }
  147. </script>
  148. </body>
  149. </html>

在上传过程中:

2、后台上传处理

  1. <?php
  2. $uploaddir ='img/';
  3. $src_array=array();
  4. if(isset($_FILES['files'])){
  5. foreach($_FILES['files']["error"]as $key => $error){
  6. if($error==UPLOAD_ERR_OK){
  7. if(!preg_match("#image#",$_FILES["files"]["type"][$key]))continue;
  8. if($_FILES["files"]["size"][$key]>1024*400)continue;
  9. $tmp_name = $_FILES["files"]["tmp_name"][$key];
  10. $name = $_FILES["files"]["name"][$key];
  11. $name= date("YmdHis",time()).preg_replace("#[^\w\.]#","",$name);
  12. $uploadfile = $uploaddir.$name;
  13. $ret=move_uploaded_file($tmp_name, $uploadfile);
  14. if($ret){
  15. $src_array[]=$uploadfile;
  16. }
  17. }
  18. }
  19. }
  20. echo json_encode($src_array);

3、demo

demo地址: http://demo.qianduanblog.com/2700/1.html

jquery批量上传插件详细见: /post/jquery-plugin-11-jquery-upload-free-refresh-batch-ajax-progress-upload.html

4、参考资料

 

 



已有 0人发表留言,猛击->> 这里<<-参与讨论


ITeye推荐



迷宫的最短路径

$
0
0
代码如下:


package com.chapterOne.exercise;

import java.util.LinkedList;
import java.util.Queue;
import java.util.concurrent.ConcurrentLinkedQueue;

/**
 * Created by yangjianzhou on 2014/8/18 21:36.
 * TODO :给定一个大小为N*M的迷宫,迷宫由通道和墙壁组成,每一步可以向邻接的上下左右四
 * 格的通道移动。求从起点到终点所需的最小步数。
 */
public class Maze {

    private static final int INF = 100000;
    private static final int N = 10;
    private static final int M = 10;
    private static char[][] mazeMatrix = {
            {'#', 'S', '#', '#', '#', '#', '#', '#', 'o', '#'},
            {'o', 'o', 'o', 'o', 'o', 'o', '#', 'o', 'o', '#'},
            {'o', '#', 'o', '#', '#', 'o', '#', '#', 'o', '#'},
            {'o', '#', 'o', 'o', 'o', 'o', 'o', 'o', 'o', 'o'},
            {'#', '#', 'o', '#', '#', 'o', '#', '#', '#', '#'},
            {'o', 'o', 'o', 'o', '#', 'o', 'o', 'o', 'o', '#'},
            {'#', '#', '#', '#', '#', '#', '#', '#', 'o', '#'},
            {'o', 'o', 'o', '#', 'o', 'o', 'o', 'o', 'o', 'o'},
            {'o', '#', '#', '#', '#', 'o', '#', '#', '#', 'o'},
            {'o', 'o', 'o', 'o', '#', 'o', 'o', 'o', 'G', '#'}
    };
    ;
    private static int xs = 0;
    private static int ys = 1;
    private static int xe = 9;
    private static int ye = 8;
    private static int[][] distance = new int[N][M];

    private static int[] xd = {1, 0, -1, 0};
    private static int[] yd = {0, 1, 0, -1};

    public static void main(String[] args) {
        initDistance();
        Maze maze = new Maze();
        int dis = maze.bfs();
        System.out.println("shortest length is : " + dis);
        printDistance();
    }

    private int bfs() {
        Queue<Point> que = new ConcurrentLinkedQueue<Point>();
        que.add(new Point(xs, ys));
        distance[xs][ys] = 0;
        while (que.size() > 0) {
            Point point = que.poll();
            if (point.getX() == xe && point.getY() == ye) {
                break;
            }
            for (int i = 0; i < 4; i++) {
                int xp = point.getX() + xd[i];
                int yp = point.getY() + yd[i];
                if (0 <= xp && xp < N && 0 <= yp && yp < M && mazeMatrix[xp][yp] != '#' && distance[xp][yp] == INF) {
                    que.add(new Point(xp, yp));
                    distance[xp][yp] = distance[point.getX()][point.getY()] + 1;
                }
            }
        }
        return distance[xe][ye];
    }

    private static void initDistance() {
        for (int i = 0; i < N; i++) {
            for (int j = 0; j < M; j++) {
                distance[i][j] = INF;
            }
        }
    }

    private static void printDistance() {
        for (int i = 0; i < N; i++) {
            System.out.println();
            for (int j = 0; j < M; j++) {
                System.out.print("\t\t" + distance[i][j]);
            }
        }
    }

    class Point {
        int x;
        int y;

        public Point(int x, int y) {
            this.x = x;
            this.y = y;
        }

        public int getX() {
            return x;
        }

        public int getY() {
            return y;
        }

        public void setX(int x) {
            this.x = x;
        }

        public void setY(int y) {
            this.y = y;
        }
    }
}




运行结果如下:


shortest length is : 22

		100000	0		100000	100000	100000	100000	100000	100000	13		100000
		2		1		2		3		4		5		100000	13		12		100000
		3		100000	3		100000	100000	6		100000	100000	11		100000
		4		100000	4		5		6		7		8		9		10		11
		100000	100000	5		100000	100000	8		100000	100000	100000	100000
		8		7		6		7		100000	9		10		11		12		100000
		100000	100000	100000	100000	100000	100000	100000	100000	13		100000
		100000	100000	100000	100000	18		17		16		15		14		15
		100000	100000	100000	100000	100000	18		100000	100000	100000	16
		100000	100000	100000	100000	100000	19		20		21		22		100000


已有 0人发表留言,猛击->> 这里<<-参与讨论


ITeye推荐



LocationListener监听位置变化,当进入到某一距离内时发出提醒

$
0
0
项目中需要这样的要求:
启动一个服务一直在背后监听当前位置变化,如果进入到离某个地点n千米内,发出一个Notification提醒用户附近有什么什么......

这里我采用的策略是这样的:

首先监听网络,如果联网了就启动距离监听服务,否则关闭距离监听服务。因为网络一旦断了,何谈距离变化?
其次,是否需要开机自启动网络监听,这样也就等于启动了距离监听服务。
其三,一旦进入到某个范围之内,就马上关闭距离监听服务,否则会不停的提醒,用户会觉得很烦。
基于以上步骤,首先实现一个距离监听服务

package com.mobovip.app;

import java.text.DecimalFormat;
import java.util.ArrayList;

import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Bundle;
import android.os.IBinder;
import android.util.Log;

public class LocationService extends Service{

	private Context context;
	public static ArrayList<Store> stores=new ArrayList<Store>();
	public static double distance = 3;//7430km
	private LocationManager locationManager;
	private NotificationManager notificationManager;
	@Override
	public IBinder onBind(Intent intent) {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public void onCreate() {
		super.onCreate();
		context = this;
		locationManager = (LocationManager)getSystemService(Context.LOCATION_SERVICE);
		
//		if(locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER)){
//			locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER,1000, 1f, locationListener);
//		}else{
			locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER,1000, 1f,locationListener);
//		}
		
//		Location location = locationManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);     
//        if(location != null){
//        	checkDistance(location);
//        }     
        
	}

	
	private final LocationListener locationListener = new LocationListener() {
		//当坐标改变时触发此函数,如果Provider传进相同的坐标,它就不会被触发
	    public void onLocationChanged(Location location) { 
	        // log it when the location changes
	        if (location != null) {
	        	checkDistance(location);
	        }
	    }

	    // Provider被disable时触发此函数,比如GPS被关闭
	    public void onProviderDisabled(String provider) {
	    }

	    //  Provider被enable时触发此函数,比如GPS被打开
	    public void onProviderEnabled(String provider) {
	    }

	    // Provider的在可用、暂时不可用和无服务三个状态直接切换时触发此函数
	    public void onStatusChanged(String provider, int status, Bundle extras) {
	    }
	};
	
	@Override
	public void onDestroy() {
		super.onDestroy();
		if(locationManager!=null){
			locationManager.removeUpdates(locationListener); 
			locationManager=null;
		}
	}

	private void checkDistance(Location location) {
		if (location != null) {
			float[] results = new float[1];
			for (Store store : stores) {
				Location.distanceBetween(location.getLatitude(),
						location.getLongitude(), store.getLatitude(),
						store.getLongitude(), results);
				float result=(results[0] / 1000);//km
				if (result < distance) {
					showNotification(store);
					stopSelf();//不要频繁的提醒
					break;
				}
			}
		}
	}


	private static final int NOTIFY_ID = 0;
	private void showNotification(Store store) {
		notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
		
		Intent intent = new Intent(this, BGR.class);
//		intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP|Intent.FLAG_ACTIVITY_NEW_TASK);
		intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
		PendingIntent pendingIntent = PendingIntent.getActivity(this, 0,
				intent, PendingIntent.FLAG_UPDATE_CURRENT);// FLAG_ONE_SHOT
		Notification notification = new Notification.Builder(context)
				.setTicker(context.getString(R.string.app_name, ""))
				.setContentTitle(store.getStoreName()+"("+store.getDistance()+")")
				.setContentText(store.getStoreAddress())
				.setContentIntent(pendingIntent)
				.setSmallIcon(R.drawable.ic_launch_notify)
				.setAutoCancel(true)
				.setWhen(System.currentTimeMillis())
				.setDefaults(Notification.DEFAULT_ALL)
				.getNotification();
		notificationManager.notify(NOTIFY_ID, notification);
	}
}


网络监听服务,其实注册了一个广播,监听手机CONNECTIVITY_ACTION动作即可
package com.mobovip.app;

import android.app.Service;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.os.IBinder;

public class NetworkStateService extends Service {

	private static final String tag = "tag";
	private BroadcastReceiver mReceiver = new BroadcastReceiver() {

		@Override
		public void onReceive(Context context, Intent intent) {
			String action = intent.getAction();
			if (action.equals(ConnectivityManager.CONNECTIVITY_ACTION)) {
				ConnectivityManager manager = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
				NetworkInfo info = manager.getActiveNetworkInfo();
				if (info != null && info.isAvailable()) {
					Intent service = new Intent(context, LocationService.class);
					startService(service);
				} else {
					Intent service = new Intent(context, LocationService.class);
					stopService(service);
				}
			}
		}
	};

	@Override
	public boolean onUnbind(Intent intent) {
		// TODO Auto-generated method stub
		return super.onUnbind(intent);
	}

	@Override
	public IBinder onBind(Intent intent) {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public void onCreate() {
		super.onCreate();
		IntentFilter mFilter = new IntentFilter();
		mFilter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
		registerReceiver(mReceiver, mFilter);
	}

	@Override
	public void onDestroy() {
		super.onDestroy();
		unregisterReceiver(mReceiver);
	}

	@Override
	public int onStartCommand(Intent intent, int flags, int startId) {
		return super.onStartCommand(intent, flags, startId);
	}

}



如有必要加上开机启动
package com.mobovip.app;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;

/**
 * BootReceiver
 * 
 * @author NGJ
 * 
 */
public class BootReceiver extends BroadcastReceiver {

	@Override
	public void onReceive(Context context, Intent intent) {
		// TODO Auto-generated method stub
		Intent i = new Intent(context, NetworkStateService.class);
		i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
		context.startService(i);
	}

}


以上service,BroadcastReceiver都需要注册,再加上网络权限等
<service android:enabled="true" android:name="com.mobovip.app.NetworkStateService" /><service android:enabled="true" android:name="com.mobovip.app.LocationService" /><!-- <receiver android:name="com.mobovip.app.BootReceiver" ><intent-filter><action android:name="android.intent.action.BOOT_COMPLETED" /></intent-filter></receiver>
         -->


已有 0人发表留言,猛击->> 这里<<-参与讨论


ITeye推荐



中国移动裁撤劳务派遣员工:涉及近30万人

$
0
0

中国移动2

中国移动裁撤劳务派遣员工:涉及近30万人

【TechWeb报道】8月19日消息,国内有媒体报道,中移动山东、福建、山西等省公司正在进行裁员计划,其中大量劳务派遣员工被裁撤,涉及近30万人。

一份中国移动近期内部资料显示,该集团目前劳务派遣人员占比为62%。为了落实相关规定,要求劳务派遣用工占比年底前要下降到50%以下,2015年底前下降到10%以下。中国移动目前用工数约60万,按照资料内容,在2015年底之前,需要对近30万劳务工进行职位调整。

据了解,今年6月底,山东移动率先开始裁员。据山东移动省公司内部人士透露,全省17市裁员超过6000余人,其中大部分为劳务派遣人员。

此外,山西移动、黑龙江移动、福建移动等地也均在进行劳务工裁员,其中山西移动已属今年第二次裁员。山西移动给予裁员补偿,并给主动离职者提供双份补偿。

据悉,作为竞争对手的中国电信、中国联通也有相应的裁员计划。(阿茹汗)


数据库产品如何选型

$
0
0
    数据库产品如何选型:
  一.软件功能对比
  二.成本考虑
  三.满足业务场景
  四.平衡各种资源
   oraclemysql,nosql选型
   一.是否满足业务场景,各DB系统软件功能对比
  1.功能对比
  oracle功能是大而全并且非常完善,无论是锁定机制还是事物支持,无论是内置函数还是外部可扩展功能,无论OLTP和OLAP都能很好的支撑。
  mysql作为开源数据的代表,得到了广泛的应用,关系型数据库的常用功能也全面覆盖到了,但mysql的缺失大表的hash join功能,这让他在OLAP发展受阻。
  nosql主用用于K/V环境查询的场景,在事务以及Join方面都未支持,能支持多维度复杂过滤的产品比较少。
  从功能角度比较 oracle > mysql > nosql
  2.性能强弱
  2.1 write性能
  Oracle需要记录Redo Log且保证每次事务都fsync到物理磁盘以保证事务安全,属于连续写;数据的写入大多是在内存中完成,后台进程进行内存到磁盘的定期批量刷新,以随机写为主。MySQL InnoDB引擎与Oracle类似;MyISAM引擎无事务所以没有事务日志到磁盘的fsync问题,但由于其表锁的原因,并发较弱。从总体使用经验来看       和Oracle相差不大。
  NoSQL在数据存储及日志记录方面的架构及实现优化,使之在写入性能方面较传统数据库有较大优势。
  总的来说write性能 NoSQL > Oracle = Mysql
  2.2 简单查询
  Oracle在高并发场景下,由于其在事务控制实现方面的优势,以及多进程的机制,显示出了相对明显的优势。
  MySQL在并发数不是太高的前提下,如16,32个并发场景下,相对于Oracle没有显示出弱势,甚至部分存储引擎下还有一些优势,但是随着并发数        的增加,就逐步体现出了与Oracle的差距,这与其基于线程的机制也有一定关系。
  NoSQL大部分时候的简单查询性能都不如前二者
  所以简单查询的性能 Oracle > Mysql > Nosql
  2.3 复杂查询
  Oracle统计信息涉及的方面非常多,优化器相对于MySQL来说也先进很多,再加上对Join方式的全面支持,无论是从功能还是性能角度来说,多表 Join都是Oracle的优势所在。
  MySQL其查询优化器所能参考的统计信息相对较少,优化器深度也比Oracle少很多,所以在多表Join的时候出现执行计划异常并不少见。此外,不        支持 Hash Join 的天生缺陷也让其 Join 能力大打折扣。
  NoSQL不支持Join,不具可比性,无疑是最弱的
  索引复杂查询性能 Oracle > Mysql > Nosql
  3.扩展能力
  Oracle由于极高的一致性要求,采用share Everything架构,造成架构上不少限制,使其扩展陈本较高
  Mysql的Replication特性对一致性要求较弱,使其架构很灵活,但slave的延迟是个大问题。
  Nosql大都支持分布式部署,具有非常好的scale out能力
  所以扩展能力 Nosql > Mysql > Oracle
  4.商业支持
  NoSQL产品目前有商业支持的很少,MySQL的本地化商业支持选择并不多,Oracle方面的商业支持无论是大型公司还是初创团队,选择性相对比较广泛
  所以在商业支持方面:Oracle > Mysql > Nosql
  5.软件可维护性
  这一点一直是运维人最为关注的因素,毕竟任何一个软件系统都是需要后期维护的。
  NoSQL 产品由于发展时间相对较短,对于可维护性角度的支持相对要少很多,虽然大多提供了一些相应的小工具,但总体来说都还是过于简单了些,所以这方面和相对成熟的MySQL以及Oracle相比较要弱。而Oracle为后期维护所做的 工作无疑是最为全面,无论是运行状态的跟踪,还是基础的备份恢复等,都很完善。
  所以在可维护性角度方面:Oracle > Mysql > Nosql
  三.业务场景分析
  1.数据一致性要求
  虽然无论你什么时候去问任何一个业务方,都会告诉你他系统的数据是不能有任何一条丢失的,任何时候都需要实时反馈变化。但实际上是当你换一个提问方式,告诉他们如果在极端情况下(比如断电)也要确保数据不会有任何丢失,会增加几十上百万的成本,那这个时候得到的回答可能就会完全不一样了。所以我们在了解业务方对数据一致性要求的需求时候,一定要明确厉害关系,分清数据级别,并且做到最大化的信息透明,才能挖出最清晰的需求。对于数据一致性的保护,Oracle 无疑是做的最可靠的一个。
  2.并发规模
  并发规模会考验我们的扩展能力,如果并发规模很大,那我们就需要很好的扩展能力以保证后续并发增长的需求。选用一个难以扩展的系统,会导致后续并发规模增长过程中无论是时间成本还是经济成本都很高
  3.逻辑复杂度
  如果业务逻辑过于复杂,至少NoSQL肯定不是合适的选择,至于MySQL还是Oracle,那就是考验二者功能及性能的时候了。
  4.总容量规模
  我们的系统数据容量规模自然也会影响到软件选型,规模非常大的,肯定要用分布式系统支持,至少也得分库分表吧,这时候的扩展能力就会充分显示出其优势。
   四.平衡各种资源做出最后选择
  通过软件功能和成本对比,以及“场景分析”,我们已经为系统选型积累到相对充分的信息了,那是不是就可以比较明确的选择出合适的系统了呢?
  这时候我们可能会发现我们的数量规模很大,但是又希望能够维护方便容易控制。这时候我们就面临如下问题:数据量规模大选NoSQL更合适,便于维护又是Oracle的优势,怎么办? 又或者如果我们有这样一个场景:某交易系统,并发量很大,对于数据一致性要求很高,业务逻辑也并不简单,怎么办?Oracle可以为我们提供很好的数据保护,面对复杂逻辑的时候也能有最好的性能,但在扩展的时候会面临成本压力。MySQL可以提供较好的扩展方案,而且成本相对会较低,NoSQL无法解决复杂逻辑的业务场景。
  类似问题可能会频繁出现在我们的架构师面前,需要大家根据各种利弊进行权衡,做好平衡决策,在尽可能满足业务需求的前提下,选择一个更合适的系统。有些时候可能也不得不作出牺牲极少数业务需求来换取系统更大的发展,而不要为了保全某些极端场景的需求而影响整个选型。
   总结
  数据存储软件的多样化趋势势不可当,不管是传统龙头的Oracle,还是开源典范的MySQL,以及NoSQL这一新秀,各有其特色,但同样也都有其短板。没有谁是万能的,同样也没有哪一种架构能应对所有问题。
  作为一个架构师,我们的选型工作需要做到下面几点:
  1. 在平时的工作中做好积累,以获得上面的“系统功能对比”和“成本对比”中的信息。
  2. 在面对具体业务需求的时候,充分挖掘最真实的需求,并将各种利弊信息透明化
  3. 在最终决策的时候做好平衡,从需求实现,成本控制以及维护管理多个角度权衡利弊
  4. 对新技术学习的渴求不能影响选型结果,同样也不能对新技术的使用带有恐惧。
  Oracle,MySQL 以及 NoSQL,都只是一个软件而已,实际使用效果更多的取决于使用者的能力。一个优秀的使用者能够充分利用其优势避开其软肋,最终获得最大化的价值。
   二.成本考虑
  1.软件成本
  这个没有争议:Oracle > Mysql = Nosql
  2.运维成本与团队管理水平
  维护的服务器数量、耗电、自动化工具和人员配备数量
  系统是否在团队的可控范围之内,出现性能、事故,团队要有能力解决
  3.人才环境
  Oracle发展几十年,具有充足的人才储备,活跃的社区环境。
  MySQL开源数据库的王者,社区活跃,虽然人才总量常常供不应求,但总体还是处于良性状态。
  NoSQL新技术,产品众多,社区活跃度远不如前面二者,处于人才极度匮乏状态


顺其自然EVO 2014-08-19 13:28 发表评论

Java 9 新特性一览

$
0
0
Oracle 已经在开发 Java 9,Java 9 主要的增强内容之前已经出现在 OpenJDK 之上。而现在 Oracle 发布的是真正的新特性, 前一个 JDK 9 的 early access 发行版 被标注了“修复bug和小增强”。

新的 APIs 和性能特性:

下一个版本包含三个全新 API:

此外还有一些小的特性和性能提升:

Java 的本地接口也被重新作为 Java Native Runtime project的一部分,将支持多 GB 堆和一个自调整的 JVM。

模块化的源码

如果你对上述特性不感兴趣,Oracle 还承诺 modular source code,目的是重新组织 JDK 的源码,使之模块化,以及项目 Jigsaw 的结构化实现。

Jigsaw 在 Java 7 的时候被移除,并在 Java 9 中回归,这是 Oracle 下一个 Java 版本最大的正义点。该项目主要的目的是为更小的设备提供可伸缩性,改进 JDK 和 Java SE 的安全性,对大型应用的性能提升以及更易于构建。与此同时 Penrose Project用于探索 Jigsaw 和开源网关计划之间的互操作性。

Oracle 的 Java 平台组的软件开发副总裁 Georges Saab 之前 表示目前主要工作是在处理 Jigaws 项目,开发团队正在探索和制作一个简单方法的原型来确保能在Java 9发布时可用。

动荡的版本历史

不管怎么说,Oracle 知道如何应对不守时的发布 Java 版本时的吐槽,向之前的 Lambda 项目和 Applet 的一些安全问题等等,这些使得 Java 8 的发布整整推迟了 2 年,甚至到现在还有 Java 8 的一些更新 导致很多开发工具无法使用的问题

Java 9 计划在 2016 年发布,留给 Oracle 只有不足 2 年的时间。但还有大量的时间来对这些特性进行讨论、请求公告等。

Via jaxenter

感谢 newer7投递这篇资讯

资讯来源: 开源中国社区

已有 2人发表留言,猛击->> 这里<<-参与讨论


ITeye推荐



Lucene五分钟教程

$
0
0

更新:下面的代码使用Lucene 4.0版本!

Lucene大大简化了在应用中集成全文搜索的功能。但实际上Lucene十分简单,我可以在五分钟之内向你展示如何使用Lucene。

1. 建立索引

为了简单起见,我们下面为一些字符串创建内存索引:

StandardAnalyzer analyzer = new StandardAnalyzer(Version.LUCENE_40);
Directory index = new RAMDirectory();

IndexWriterConfig config = new IndexWriterConfig(Version.LUCENE_40, analyzer);

IndexWriter w = new IndexWriter(index, config);
addDoc(w, "Lucene in Action", "193398817");
addDoc(w, "Lucene for Dummies", "55320055Z");
addDoc(w, "Managing Gigabytes", "55063554A");
addDoc(w, "The Art of Computer Science", "9900333X");
w.close();

addDoc()方法把文档(译者注:这里的文档是Lucene中的Document类的实例)添加到索引中。

private static void addDoc(IndexWriter w, String title, String isbn) throws IOException {
  Document doc = new Document();
  doc.add(new TextField("title", title, Field.Store.YES));
  doc.add(new StringField("isbn", isbn, Field.Store.YES));
  w.addDocument(doc);
}

注意,对于需要分词的内容我们使用TextField,对于像id这样不需要分词的内容我们使用StringField。

2.搜索请求

我们从标准输入(stdin)中读入搜索请求,然后对它进行解析,最后创建一个Lucene中的Query对象。

String querystr = args.length > 0 ? args[0] : "lucene";
Query q = new QueryParser(Version.LUCENE_40, "title", analyzer).parse(querystr);

3.搜索

我们创建一个Searcher对象并且使用上面创建的Query对象来进行搜索,匹配到的前10个结果封装在TopScoreDocCollector对象里返回。

int hitsPerPage = 10;
IndexReader reader = IndexReader.open(index);
IndexSearcher searcher = new IndexSearcher(reader);
TopScoreDocCollector collector = TopScoreDocCollector.create(hitsPerPage, true);
searcher.search(q, collector);
ScoreDoc[] hits = collector.topDocs().scoreDocs;

4.展示

现在我们得到了搜索结果,我们需要想用户展示它。

System.out.println("Found " + hits.length + " hits.");
for(int i=0;i<hits.length;++i) {
    int docId = hits[i].doc;
    Document d = searcher.doc(docId);
    System.out.println((i + 1) + ". " + d.get("isbn") + "\t" + d.get("title"));
}

这里是这个小应用的完整代码。 下载HelloLucene.java

import org.apache.lucene.analysis.standard.StandardAnalyzer;
import org.apache.lucene.document.Document;
import org.apache.lucene.document.Field;
import org.apache.lucene.document.StringField;
import org.apache.lucene.document.TextField;
import org.apache.lucene.index.DirectoryReader;
import org.apache.lucene.index.IndexReader;
import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.index.IndexWriterConfig;
import org.apache.lucene.queryparser.classic.ParseException;
import org.apache.lucene.queryparser.classic.QueryParser;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.ScoreDoc;
import org.apache.lucene.search.TopScoreDocCollector;
import org.apache.lucene.store.Directory;
import org.apache.lucene.store.RAMDirectory;
import org.apache.lucene.util.Version;

import java.io.IOException;

public class HelloLucene {
  public static void main(String[] args) throws IOException, ParseException {
    // 0. Specify the analyzer for tokenizing text.
    //    The same analyzer should be used for indexing and searching
    StandardAnalyzer analyzer = new StandardAnalyzer(Version.LUCENE_40);

    // 1. create the index
    Directory index = new RAMDirectory();

    IndexWriterConfig config = new IndexWriterConfig(Version.LUCENE_40, analyzer);

    IndexWriter w = new IndexWriter(index, config);
    addDoc(w, "Lucene in Action", "193398817");
    addDoc(w, "Lucene for Dummies", "55320055Z");
    addDoc(w, "Managing Gigabytes", "55063554A");
    addDoc(w, "The Art of Computer Science", "9900333X");
    w.close();

    // 2. query
    String querystr = args.length > 0 ? args[0] : "lucene";

    // the "title" arg specifies the default field to use
    // when no field is explicitly specified in the query.
    Query q = new QueryParser(Version.LUCENE_40, "title", analyzer).parse(querystr);

    // 3. search
    int hitsPerPage = 10;
    IndexReader reader = DirectoryReader.open(index);
    IndexSearcher searcher = new IndexSearcher(reader);
    TopScoreDocCollector collector = TopScoreDocCollector.create(hitsPerPage, true);
    searcher.search(q, collector);
    ScoreDoc[] hits = collector.topDocs().scoreDocs;
    
    // 4. display results
    System.out.println("Found " + hits.length + " hits.");
    for(int i=0;i<hits.length;++i) {
      int docId = hits[i].doc;
      Document d = searcher.doc(docId);
      System.out.println((i + 1) + ". " + d.get("isbn") + "\t" + d.get("title"));
    }

    // reader can only be closed when there
    // is no need to access the documents any more.
    reader.close();
  }

  private static void addDoc(IndexWriter w, String title, String isbn) throws IOException {
    Document doc = new Document();
    doc.add(new TextField("title", title, Field.Store.YES));

    // use a string field for isbn because we don't want it tokenized
    doc.add(new StringField("isbn", isbn, Field.Store.YES));
    w.addDocument(doc);
  }
}

可以直接在命令行中使用这个小应用,键入 java HelloLucene

下面可以做什么?

  1. 阅读下面关于Lucene的书籍。
  2. 你需要应该使用Apache Solr代替Apache Lucene吗
  3. 更多关于 Lucene的基本概念

一些与Lucene和搜索相关的书籍

Github上的基于maven的库

Mac Luq在Github上的基于maven的库:

https://github.com/macluq/helloLucene

用下面这条命令下载它:

git clone https://github.com/macluq/helloLucene.git

PS:如果你是Java新手的话,试试下面的命令:

wget http://repo1.maven.org/maven2/org/apache/lucene/lucene-core/4.0.0/lucene-core-4.0.0.jar
wget http://repo1.maven.org/maven2/org/apache/lucene/lucene-analyzers-common/4.0.0/lucene-analyzers-common-4.0.0.jar
wget http://repo1.maven.org/maven2/org/apache/lucene/lucene-queryparser/4.0.0/lucene-queryparser-4.0.0.jar
wget http://www.lucenetutorial.com/code/HelloLucene.java
javac -classpath .:lucene-core-4.0.0.jar:lucene-analyzers-common-4.0.0.jar:lucene-queryparser-4.0.0.jar HelloLucene.java
java -classpath .:lucene-core-4.0.0.jar:lucene-analyzers-common-4.0.0.jar:lucene-queryparser-4.0.0.jar HelloLucene

你会得到下面的结果:

Found 2 hits.
1. Lucene in Action
2. Lucene for Dummies

Erik,一个可能对你有所帮助的读者抱怨到:

编译过程还算顺利,但是我不能正常运行这段代码。在网上搜索并且自己尝试了以后发现Lucene的jar文件必须在classpath中,否则运行不起来。这可能对很多像我这样的java初学者很多帮助。

安装Lucene

PS:我发现一些初学者在安装Lucene时有些困难。

你应该先 下载Lucene,然后把它解压到一个你用于编程的目录。

如果你使用Netbeans,你也可以这么做:

  • 遵循 这里的教程。
  • 按照下面的步骤:
  1. 通过以此点击Netbeans菜单栏上的“工具”,然后选择“库管理器”,把Lucene的jar文件作为外部类库加进来。
  2. 在Lucene项目上面右键,选择“属性”
  3. 在弹出来的对话框中,以此选择“类库”,”添加jar或文件夹”选项
  4. 定位到从lucene-[version].tar.gz解压出来的文件夹上,选择 lucene-core-[version].jar。
  5. 点击“确定”,现在jar文件就已经添加到你项目的classpath中去了。

相关文章

使用Fiddler对手机应用进行抓包测试

$
0
0

手机应用的抓包测试相对于PC上要麻烦一些。以下内容来自公司QA的指导,感谢~

需要的软件:

  1. 抓包工具Fiddler
  2. WIFI共享工具: 猎豹免费WIFI (使用360WIFI等均可,只要保证在同一局域网下就都可以,连接同一个路由器也可以)

现在开始真实的抓包:

1、启动Fiddler,打开菜单栏中的 Tools > Fiddler Options

fiddler-1

2、打开Fiddler Options后点击 Connections 然后将红框中标识的“Allow romote computers to connect”勾选上即可。(注意,此界面中的端口号可修改为你喜欢的,建议保持默认)

fiddler-2

3、查询当前PC的局域网IP(在命令行输入ipconfig即可)

ip

4、设置手机上的WLAN的连接信息

将手机连接上同一个WIFI,并进行设置:

  • iOS手机:设置 > WIFI > 点击进入连接上的WIFI,在最下面会有HTTP代理(默认情况下使关闭),打开手动选项,在服务器栏填写刚才查看到的PC机的IP,如’192.168.8.101′,在端口号栏填写:8888,至此设置整个流程设置完毕。
  • Android手机:设置 > 连接 > WLAN > 手指长按已连接的WIFI地址将会出现“修改网络配置”的选项,点击进去后将会看到一个“显示高级选项”,勾选上以后会出现代理服务器的设置,选择手动后将PC机的IP填写到“代理主机名”栏,将8888填写进“代理端口”即可。

Oracle rownum影响执行计划

$
0
0

   今天调优一条SQL语句,由于SQL比较复杂,用autotrace很难一眼看出哪里出了问题,直接上10046。

SELECT AB.*
FROM (SELECT A.*, rownum RN
FROM (SELECT *
        from (SELECT DISTINCT (D.DEVICE_ID), F.FUNCTION_LOCATION_ID
                from GG_device D,
                     GG_CLASSIFY_CARD C,
                     GG_function_location F,
                     GG_fl_device L,
                     GG_tech_object_node n,
                     (SELECT N.TECH_OBJECT_ID
                        FROM GG_TECH_OBJECT_NODE N
                       WHERE N.NODE_TYPE = 2
                       START WITH N.TECH_OBJECT_ID = 15773325
                      CONNECT BY PRIOR
                                  N.TECH_OBJECT_NODE_ID = N.PARENT_ID) TAB
               where F.FUNCTION_LOCATION_ID = L.FUNCTION_LOCATION_ID
                 and L.Device_Id = d.device_id
                 and d.classify_id = c.classify_id
                 AND EXISTS
               (SELECT 1
                        FROM GG_TECH_OBJECT_NODE N
                       WHERE N.TECH_OBJECT_ID = D.DEVICE_ID
                         AND N.NODE_TYPE = 2)
                 AND D.CURRENT_STATUS = 0
                 AND D.IS_SHARE_DEVICE = 1
                 AND TAB.TECH_OBJECT_ID = D.DEVICE_ID
                 and n.tech_object_id = f.function_location_id
                 AND F.SITE_ID = 1021
                 AND C.ALIAS_NAME IN ('A176')
              union all
              SELECT DISTINCT (D.DEVICE_ID), F.FUNCTION_LOCATION_ID
                FROM GG_DEVICE D,
                     GG_CLASSIFY_CARD C,
                     GG_FUNCTION_LOCATION F,
                     GG_tech_object_node n,
                     (SELECT N.TECH_OBJECT_ID
                        FROM GG_TECH_OBJECT_NODE N
                       WHERE N.NODE_TYPE = 2
                       START WITH N.TECH_OBJECT_ID = 15773325
                      CONNECT BY PRIOR
                                  N.TECH_OBJECT_NODE_ID = N.PARENT_ID) TAB
               WHERE D.CLASSIFY_ID = C.CLASSIFY_ID
                 AND F.FUNCTION_LOCATION_ID(+) =
                     D.FUNCTION_LOCATION_ID
                 and n.tech_object_id = f.function_location_id
                 AND EXISTS
               (SELECT 1
                        FROM GG_TECH_OBJECT_NODE N
                       WHERE N.TECH_OBJECT_ID = D.DEVICE_ID
                         AND N.NODE_TYPE = 2)
                 AND D.CURRENT_STATUS = 0
                 AND D.IS_SHARE_DEVICE = 0
                 AND TAB.TECH_OBJECT_ID = D.DEVICE_ID
                 AND F.SITE_ID = 1021
                 AND C.ALIAS_NAME IN ('A176'))) A
WHERE ROWNUM <= 25) AB

WHERE AB.RN > 0;

已用时间:  00: 00: 05.56

----------------------------------------------------------
Plan hash value: 1124467031
---------------------------------------------------------------------------------------------------------------------
| Id  | Operation                               | Name                      | Rows  | Bytes | Cost (%CPU)| Time     |
---------------------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT                        |                           |    18 | 67248 | 28951   (1)| 00:05:48 |
|*  1 |  VIEW                                   |                           |    18 | 67248 | 28951   (1)| 00:05:48 |
|*  2 |   COUNT STOPKEY                         |                           |       |       |         |     |
|   3 |    VIEW                                 |                           |    18 | 67014 | 28951   (1)| 00:05:48 |
|*  4 |     SORT ORDER BY STOPKEY               |                           |    18 | 67014 | 28951   (1)| 00:05:48 |
|   5 |      VIEW                               |                           |    18 | 67014 | 28950   (1)| 00:05:48 |
|   6 |       UNION-ALL                         |                           |       |       |         |     |
|   7 |        HASH UNIQUE                      |                           |     6 |  2064 | 15146   (1)| 00:03:02 |
|*  8 |         HASH JOIN                       |                           |     6 |  2064 | 15145   (1)| 00:03:02 |
|   9 |          TABLE ACCESS BY INDEX ROWID    | GG_TECH_OBJECT_NODE     |     1 |   102 |     3   (0)| 00:00:01 |
|  10 |           NESTED LOOPS                  |                           |     6 |  2022 |  5842   (1)| 00:01:11 |
|  11 |            NESTED LOOPS SEMI            |                           |     5 |  1175 |  5827   (1)| 00:01:10 |
|  12 |             NESTED LOOPS                |                           |     5 |  1125 |  5817   (1)| 00:01:10 |
|* 13 |              HASH JOIN                  |                           |   172 | 32508 |  5645   (1)| 00:01:08 |
|* 14 |               HASH JOIN                 |                           |    77 | 13629 |  5601   (1)| 00:01:08 |
|* 15 |                TABLE ACCESS FULL        | GG_CLASSIFY_CARD         |     1 |    93 |    16   (0)| 00:00:01 |
|* 16 |                TABLE ACCESS FULL        | GG_DEVICE               | 22527 |  1847K|  5584   (1)| 00:01:08 |
|  17 |               TABLE ACCESS FULL         | GG_FL_DEVICE            | 74829 |   876K|    43   (3)| 00:00:01 |
|* 18 |              TABLE ACCESS BY INDEX ROWID| GG_FUNCTION_LOCATION    |     1 |    36 |     1   (0)| 00:00:01 |
|* 19 |               INDEX UNIQUE SCAN         | PK_GG_FUNCTION_LOCATION |     1 |       |     0   (0)| 00:00:01 |
|* 20 |             INDEX RANGE SCAN            | IDX_TECH_NODE_ID          |   482K|  4712K|     2   (0)| 00:00:01 |
|* 21 |            INDEX RANGE SCAN             | IDX_TECH_OBJECT_ID        |     1 |       |     2   (0)| 00:00:01 |
|  22 |          VIEW                           |                           |  1762K|    11M|  9291   (1)| 00:01:52 |
|* 23 |           FILTER                        |                           |       |       |         |     |
|* 24 |            CONNECT BY WITH FILTERING    |                           |       |       |         |     |
|  25 |             TABLE ACCESS BY INDEX ROWID | GG_TECH_OBJECT_NODE     |       |       |         |     |
|* 26 |              INDEX RANGE SCAN           | IDX_TECH_OBJECT_ID        |     1 |     7 |     3   (0)| 00:00:01 |
|* 27 |             HASH JOIN                   |                           |       |       |         |     |
|  28 |              CONNECT BY PUMP            |                           |       |       |         |     |
|  29 |              TABLE ACCESS FULL          | GG_TECH_OBJECT_NODE     |  1762K|    40M|  9291   (1)| 00:01:52 |
|  30 |             TABLE ACCESS FULL           | GG_TECH_OBJECT_NODE     |  1762K|    40M|  9291   (1)| 00:01:52 |
|  31 |        HASH UNIQUE                      |                           |    12 |  4056 | 13804   (1)| 00:02:46 |
|* 32 |         HASH JOIN                       |                           |    12 |  4056 | 13803   (1)| 00:02:46 |
|  33 |          TABLE ACCESS BY INDEX ROWID    | GG_TECH_OBJECT_NODE     |     1 |   102 |     3   (0)| 00:00:01 |
|  34 |           NESTED LOOPS                  |                           |    11 |  3641 |  4501   (1)| 00:00:55 |
|  35 |            NESTED LOOPS SEMI            |                           |    10 |  2290 |  4471   (1)| 00:00:54 |
|* 36 |             HASH JOIN                   |                           |    10 |  2190 |  4451   (1)| 00:00:54 |
|* 37 |              TABLE ACCESS FULL          | GG_CLASSIFY_CARD         |     1 |    93 |    16   (0)| 00:00:01 |
|* 38 |              TABLE ACCESS BY INDEX ROWID| GG_DEVICE               |     4 |   360 |     5   (0)| 00:00:01 |
|  39 |               NESTED LOOPS              |                           |  2823 |   347K|  4434   (1)| 00:00:54 |
|* 40 |                TABLE ACCESS FULL        | GG_FUNCTION_LOCATION    |   685 | 24660 |  2214   (1)| 00:00:27 |
|* 41 |                INDEX RANGE SCAN         | IDX_FLOCID                |     4 |       |     2   (0)| 00:00:01 |
|* 42 |             INDEX RANGE SCAN            | IDX_TECH_NODE_ID          |   482K|  4712K|     2   (0)| 00:00:01 |
|* 43 |            INDEX RANGE SCAN             | IDX_TECH_OBJECT_ID        |     1 |       |     2   (0)| 00:00:01 |
|  44 |          VIEW                           |                           |  1762K|    11M|  9291   (1)| 00:01:52 |
|* 45 |           FILTER                        |                           |       |       |         |     |
|* 46 |            CONNECT BY WITH FILTERING    |                           |       |       |         |     |
|  47 |             TABLE ACCESS BY INDEX ROWID | GG_TECH_OBJECT_NODE     |       |       |         |     |
|* 48 |              INDEX RANGE SCAN           | IDX_TECH_OBJECT_ID        |     1 |     7 |     3   (0)| 00:00:01 |
|* 49 |             HASH JOIN                   |                           |       |       |         |     |
|  50 |              CONNECT BY PUMP            |                           |       |       |         |     |
|  51 |              TABLE ACCESS FULL          | GG_TECH_OBJECT_NODE     |  1762K|    40M|  9291   (1)| 00:01:52 |
|  52 |             TABLE ACCESS FULL           | GG_TECH_OBJECT_NODE     |  1762K|    40M|  9291   (1)| 00:01:52 |
---------------------------------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
   1 - filter("AB"."RN">0)
   2 - filter(ROWNUM<=25)
   4 - filter(ROWNUM<=25)
   8 - access("TAB"."TECH_OBJECT_ID"="D"."DEVICE_ID")
  13 - access("L"."DEVICE_ID"="D"."DEVICE_ID")
  14 - access("D"."CLASSIFY_ID"="C"."CLASSIFY_ID")
  15 - filter("C"."ALIAS_NAME"='A176')
  16 - filter("D"."IS_SHARE_DEVICE"=1 AND "D"."CURRENT_STATUS"=0)
  18 - filter("F"."SITE_ID"=1021)
  19 - access("F"."FUNCTION_LOCATION_ID"="L"."FUNCTION_LOCATION_ID")
  20 - access("N"."TECH_OBJECT_ID"="D"."DEVICE_ID" AND "N"."NODE_TYPE"=2)
  21 - access("N"."TECH_OBJECT_ID"="F"."FUNCTION_LOCATION_ID")
  23 - filter("N"."NODE_TYPE"=2)
  24 - filter("N"."TECH_OBJECT_ID"=15773325)
  26 - access("N"."TECH_OBJECT_ID"=15773325)
  27 - access("N"."PARENT_ID"=NULL)
  32 - access("TAB"."TECH_OBJECT_ID"="D"."DEVICE_ID")
  36 - access("D"."CLASSIFY_ID"="C"."CLASSIFY_ID")
  37 - filter("C"."ALIAS_NAME"='A176')
  38 - filter("D"."IS_SHARE_DEVICE"=0 AND "D"."CURRENT_STATUS"=0)
  40 - filter("F"."SITE_ID"=1021)
  41 - access("F"."FUNCTION_LOCATION_ID"="D"."FUNCTION_LOCATION_ID")
  42 - access("N"."TECH_OBJECT_ID"="D"."DEVICE_ID" AND "N"."NODE_TYPE"=2)
  43 - access("N"."TECH_OBJECT_ID"="F"."FUNCTION_LOCATION_ID")
  45 - filter("N"."NODE_TYPE"=2)
  46 - filter("N"."TECH_OBJECT_ID"=15773325)
  48 - access("N"."TECH_OBJECT_ID"=15773325)
  49 - access("N"."PARENT_ID"=NULL)
统计信息
----------------------------------------------------------
          9  recursive calls
          0  db block gets
     209163  consistent gets
          0  physical reads
          0  redo size
       2890  bytes sent via SQL*Net to client
      10811  bytes received via SQL*Net from client
          2  SQL*Net roundtrips to/from client
         63  sorts (memory)
          0  sorts (disk)
          1  rows processed

10046 trace的结果,可以一眼看出是递归出了问题,按照业务上来说一个节点下面没有多少数据啊,怎么会不走索引呢?

Rows     Row Source Operation
-------  ---------------------------------------------------
      1  VIEW  (cr=209038 pr=0 pw=0 time=5665797 us)
      1   COUNT STOPKEY (cr=209038 pr=0 pw=0 time=5665774 us)
      1    VIEW  (cr=209038 pr=0 pw=0 time=5665768 us)
      1     SORT ORDER BY STOPKEY (cr=209038 pr=0 pw=0 time=5665745 us)
      1      VIEW  (cr=209038 pr=0 pw=0 time=5665649 us)
      1       UNION-ALL  (cr=209038 pr=0 pw=0 time=5665631 us)
      0        HASH UNIQUE (cr=25205 pr=0 pw=0 time=570538 us)
      0         HASH JOIN  (cr=25205 pr=0 pw=0 time=570360 us)
      0          TABLE ACCESS BY INDEX ROWID GG_TECH_OBJECT_NODE (cr=25205 pr=0 pw=0 time=570095 us)
      1           NESTED LOOPS  (cr=25205 pr=0 pw=0 time=570075 us)
      0            NESTED LOOPS SEMI (cr=25205 pr=0 pw=0 time=570069 us)
      0             NESTED LOOPS  (cr=25205 pr=0 pw=0 time=570066 us)
      0              HASH JOIN  (cr=25205 pr=0 pw=0 time=570062 us)
      0               HASH JOIN  (cr=25205 pr=0 pw=0 time=569617 us)
      1                TABLE ACCESS FULL GG_CLASSIFY_CARD (cr=68 pr=0 pw=0 time=1467 us)
  21206                TABLE ACCESS FULL GG_DEVICE (cr=25137 pr=0 pw=0 time=424214 us)
      0               TABLE ACCESS FULL GG_FL_DEVICE (cr=0 pr=0 pw=0 time=0 us)
      0              TABLE ACCESS BY INDEX ROWID GG_FUNCTION_LOCATION (cr=0 pr=0 pw=0 time=0 us)
      0               INDEX UNIQUE SCAN PK_GG_FUNCTION_LOCATION (cr=0 pr=0 pw=0 time=0 us)(object id 508068)
      0             INDEX RANGE SCAN IDX_TECH_NODE_ID (cr=0 pr=0 pw=0 time=0 us)(object id 541613)
      0            INDEX RANGE SCAN IDX_TECH_OBJECT_ID (cr=0 pr=0 pw=0 time=0 us)(object id 508645)
      0          VIEW  (cr=0 pr=0 pw=0 time=0 us)
      0           FILTER  (cr=0 pr=0 pw=0 time=0 us)
      0            CONNECT BY WITH FILTERING (cr=0 pr=0 pw=0 time=0 us)
      0             TABLE ACCESS BY INDEX ROWID GG_TECH_OBJECT_NODE (cr=0 pr=0 pw=0 time=0 us)
      0              INDEX RANGE SCAN IDX_TECH_OBJECT_ID (cr=0 pr=0 pw=0 time=0 us)(object id 508645)
      0             HASH JOIN  (cr=0 pr=0 pw=0 time=0 us)
      0              CONNECT BY PUMP  (cr=0 pr=0 pw=0 time=0 us)
      0              TABLE ACCESS FULL GG_TECH_OBJECT_NODE (cr=0 pr=0 pw=0 time=0 us)
      0             TABLE ACCESS FULL GG_TECH_OBJECT_NODE (cr=0 pr=0 pw=0 time=0 us)
      1        HASH UNIQUE (cr=183833 pr=0 pw=0 time=5095035 us)
      1         HASH JOIN  (cr=183748 pr=0 pw=0 time=5090111 us)
    170          TABLE ACCESS BY INDEX ROWID GG_TECH_OBJECT_NODE (cr=15772 pr=0 pw=0 time=7653 us)
    341           NESTED LOOPS  (cr=15610 pr=0 pw=0 time=189743 us)
    170            NESTED LOOPS SEMI (cr=15268 pr=0 pw=0 time=5170 us)
    170             HASH JOIN  (cr=14926 pr=0 pw=0 time=3232 us)
      1              TABLE ACCESS FULL GG_CLASSIFY_CARD (cr=68 pr=0 pw=0 time=830 us)
   2867              TABLE ACCESS BY INDEX ROWID GG_DEVICE (cr=14858 pr=0 pw=0 time=28976 us)
   4728               NESTED LOOPS  (cr=13282 pr=0 pw=0 time=94565 us)
   1667                TABLE ACCESS FULL GG_FUNCTION_LOCATION (cr=9937 pr=0 pw=0 time=13539 us)
   3060                INDEX RANGE SCAN IDX_FLOCID (cr=3345 pr=0 pw=0 time=12458 us)(object id 507929)
    170             INDEX RANGE SCAN IDX_TECH_NODE_ID (cr=342 pr=0 pw=0 time=3171 us)(object id 541613)
    170            INDEX RANGE SCAN IDX_TECH_OBJECT_ID (cr=342 pr=0 pw=0 time=1854 us)(object id 508645)
     31          VIEW  (cr=167976 pr=0 pw=0 time=4864861 us)
     31           FILTER  (cr=167976 pr=0 pw=0 time=4864794 us)
     56            CONNECT BY WITH FILTERING (cr=167976 pr=0 pw=0 time=4865653 us)
      1             TABLE ACCESS BY INDEX ROWID GG_TECH_OBJECT_NODE (cr=4 pr=0 pw=0 time=58 us)
      1              INDEX RANGE SCAN IDX_TECH_OBJECT_ID (cr=3 pr=0 pw=0 time=25 us)(object id 508645)
     55             HASH JOIN  (cr=167972 pr=0 pw=0 time=1264029 us)
     56              CONNECT BY PUMP  (cr=0 pr=0 pw=0 time=56 us)
7048956              TABLE ACCESS FULL GG_TECH_OBJECT_NODE (cr=167972 pr=0 pw=0 time=488 us)
      0             TABLE ACCESS FULL GG_TECH_OBJECT_NODE (cr=0 pr=0 pw=0 time=0 us)          

  

    在无意中测试发现,去掉分页的语句之后,就非常快了,揣测是COUNT STOPKEY造成的,如果数据量大的做分页,肯定是可以提升性能的,但此条SQL语句只是返回一条数据。我的结论是rownum可以改变执行计划。       

SQL> SELECT *
from (SELECT DISTINCT (D.DEVICE_ID), F.FUNCTION_LOCATION_ID
      from GG_device D,
           GG_CLASSIFY_CARD C,
           GG_function_location F,
           GG_fl_device L,
           GG_tech_object_node n,
           (SELECT N.TECH_OBJECT_ID
              FROM GG_TECH_OBJECT_NODE N
             WHERE N.NODE_TYPE = 2
             START WITH N.TECH_OBJECT_ID = 15773325
            CONNECT BY PRIOR N.TECH_OBJECT_NODE_ID = N.PARENT_ID) TAB
     where F.FUNCTION_LOCATION_ID = L.FUNCTION_LOCATION_ID
       and L.Device_Id = d.device_id
       and d.classify_id = c.classify_id
       AND EXISTS (SELECT 1
              FROM GG_TECH_OBJECT_NODE N
             WHERE N.TECH_OBJECT_ID = D.DEVICE_ID
               AND N.NODE_TYPE = 2)
       AND D.CURRENT_STATUS = 0
       AND D.IS_SHARE_DEVICE = 1
       AND TAB.TECH_OBJECT_ID = D.DEVICE_ID
       and n.tech_object_id = f.function_location_id
       AND F.SITE_ID = 1021
       AND C.ALIAS_NAME IN ('A176')
    union all
    SELECT DISTINCT (D.DEVICE_ID), F.FUNCTION_LOCATION_ID
      FROM GG_DEVICE D,
           GG_CLASSIFY_CARD C,
           GG_FUNCTION_LOCATION F,
           GG_tech_object_node n,
           (SELECT N.TECH_OBJECT_ID
              FROM GG_TECH_OBJECT_NODE N
             WHERE N.NODE_TYPE = 2
             START WITH N.TECH_OBJECT_ID = 15773325
            CONNECT BY PRIOR N.TECH_OBJECT_NODE_ID = N.PARENT_ID) TAB
     WHERE D.CLASSIFY_ID = C.CLASSIFY_ID
       AND F.FUNCTION_LOCATION_ID(+) = D.FUNCTION_LOCATION_ID
       and n.tech_object_id = f.function_location_id
       AND EXISTS (SELECT 1
              FROM GG_TECH_OBJECT_NODE N
             WHERE N.TECH_OBJECT_ID = D.DEVICE_ID
               AND N.NODE_TYPE = 2)
       AND D.CURRENT_STATUS = 0
       AND D.IS_SHARE_DEVICE = 0
       AND TAB.TECH_OBJECT_ID = D.DEVICE_ID
       AND F.SITE_ID = 1021
       AND C.ALIAS_NAME IN ('A176'));
已用时间:  00: 00: 00.06
执行计划
----------------------------------------------------------
Plan hash value: 1345020195
------------------------------------------------------------------------------------------------------------------------
| Id  | Operation                                 | Name                       | Rows  | Bytes | Cost (%CPU)| Time     |
------------------------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT                          |                            |     2 |  7446 |    41   (5)| 00:00:01 |
|   1 |  VIEW                                     |                            |     2 |  7446 |    41   (5)| 00:00:01 |
|   2 |   UNION-ALL                               |                            |       |       |         |             |
|   3 |    HASH UNIQUE                            |                            |     1 |   345 |    21   (5)| 00:00:01 |
|   4 |     TABLE ACCESS BY INDEX ROWID           | GG_TECH_OBJECT_NODE      |     1 |   103 |     3   (0)| 00:00:01 |
|   5 |      NESTED LOOPS                         |                            |     1 |   345 |    20   (0)| 00:00:01 |
|   6 |       NESTED LOOPS                        |                            |     1 |   242 |    17   (0)| 00:00:01 |
|   7 |        NESTED LOOPS                       |                            |     1 |   206 |    16   (0)| 00:00:01 |
|   8 |         NESTED LOOPS SEMI                 |                            |     1 |   194 |    15   (0)| 00:00:01 |
|   9 |          NESTED LOOPS                     |                            |     1 |   184 |    13   (0)| 00:00:01 |
|  10 |           NESTED LOOPS                    |                            |     3 |   273 |    10   (0)| 00:00:01 |
|  11 |            VIEW                           |                            |     3 |    21 |     6   (0)| 00:00:01 |
|* 12 |             FILTER                        |                            |       |       |         |             |
|* 13 |              CONNECT BY WITH FILTERING    |                            |       |       |         |             |
|  14 |               TABLE ACCESS BY INDEX ROWID | GG_TECH_OBJECT_NODE      |       |       |         |             |
|* 15 |                INDEX RANGE SCAN           | IDX_TECH_OBJECT_ID1        |     1 |     7 |     3   (0)| 00:00:01 |
|  16 |               NESTED LOOPS                |                            |       |       |         |             |
|  17 |                BUFFER SORT                |                            |       |       |         |             |
|  18 |                 CONNECT BY PUMP           |                            |       |       |         |             |
|  19 |                TABLE ACCESS BY INDEX ROWID| GG_TECH_OBJECT_NODE      |     3 |    72 |     6   (0)| 00:00:01 |
|* 20 |                 INDEX RANGE SCAN          | IDX_TECH_OBJECT_PARENT_ID1 |     3 |       |     3   (0)| 00:00:01 |
|* 21 |               TABLE ACCESS FULL           | GG_TECH_OBJECT_NODE      |     3 |    72 |     6   (0)| 00:00:01 |
|* 22 |            TABLE ACCESS BY INDEX ROWID    | GG_DEVICE                |     1 |    84 |     2   (0)| 00:00:01 |
|* 23 |             INDEX UNIQUE SCAN             | PK_GG_DEVICE             |     1 |       |     1   (0)| 00:00:01 |
|* 24 |           TABLE ACCESS BY INDEX ROWID     | GG_CLASSIFY_CARD          |     1 |    93 |     1   (0)| 00:00:01 |
|* 25 |            INDEX UNIQUE SCAN              | SYS_C00468549              |     1 |       |     0   (0)| 00:00:01 |
|* 26 |          INDEX RANGE SCAN                 | IDX_TECH_NODE_ID1          |   587K|  5736K|     2   (0)| 00:00:01 |
|* 27 |         INDEX RANGE SCAN                  | PK_GG_FL_DEVICE          |     2 |    24 |     1   (0)| 00:00:01 |
|* 28 |        TABLE ACCESS BY INDEX ROWID        | GG_FUNCTION_LOCATION     |     1 |    36 |     1   (0)| 00:00:01 |
|* 29 |         INDEX UNIQUE SCAN                 | PK_GG_FUNCTION_LOCATION  |     1 |       |     0   (0)| 00:00:01 |
|* 30 |       INDEX RANGE SCAN                    | IDX_TECH_OBJECT_ID1        |     1 |       |     2   (0)| 00:00:01 |
|  31 |    HASH UNIQUE                            |                            |     1 |   339 |    20   (5)| 00:00:01 |
|  32 |     TABLE ACCESS BY INDEX ROWID           | GG_TECH_OBJECT_NODE      |     1 |   103 |     3   (0)| 00:00:01 |
|  33 |      NESTED LOOPS                         |                            |     1 |   339 |    19   (0)| 00:00:01 |
|  34 |       NESTED LOOPS SEMI                   |                            |     1 |   236 |    16   (0)| 00:00:01 |
|  35 |        NESTED LOOPS                       |                            |     1 |   226 |    14   (0)| 00:00:01 |
|  36 |         NESTED LOOPS                      |                            |     1 |   133 |    13   (0)| 00:00:01 |
|  37 |          NESTED LOOPS                     |                            |     3 |   291 |    10   (0)| 00:00:01 |
|  38 |           VIEW                            |                            |     3 |    21 |     6   (0)| 00:00:01 |
|* 39 |            FILTER                         |                            |       |       |         |             |
|* 40 |             CONNECT BY WITH FILTERING     |                            |       |       |         |             |
|  41 |              TABLE ACCESS BY INDEX ROWID  | GG_TECH_OBJECT_NODE      |       |       |         |             |
|* 42 |               INDEX RANGE SCAN            | IDX_TECH_OBJECT_ID1        |     1 |     7 |     3   (0)| 00:00:01 |
|  43 |              NESTED LOOPS                 |                            |       |       |         |             |
|  44 |               BUFFER SORT                 |                            |       |       |         |             |
|  45 |                CONNECT BY PUMP            |                            |       |       |         |             |
|  46 |               TABLE ACCESS BY INDEX ROWID | GG_TECH_OBJECT_NODE      |     3 |    72 |     6   (0)| 00:00:01 |
|* 47 |                INDEX RANGE SCAN           | IDX_TECH_OBJECT_PARENT_ID1 |     3 |       |     3   (0)| 00:00:01 |
|* 48 |              TABLE ACCESS FULL            | GG_TECH_OBJECT_NODE      |     3 |    72 |     6   (0)| 00:00:01 |
|* 49 |           TABLE ACCESS BY INDEX ROWID     | GG_DEVICE                |     1 |    90 |     2   (0)| 00:00:01 |
|* 50 |            INDEX UNIQUE SCAN              | PK_GG_DEVICE             |     1 |       |     1   (0)| 00:00:01 |
|* 51 |          TABLE ACCESS BY INDEX ROWID      | GG_FUNCTION_LOCATION     |     1 |    36 |     1   (0)| 00:00:01 |
|* 52 |           INDEX UNIQUE SCAN               | PK_GG_FUNCTION_LOCATION  |     1 |       |     0   (0)| 00:00:01 |
|* 53 |         TABLE ACCESS BY INDEX ROWID       | GG_CLASSIFY_CARD          |     1 |    93 |     1   (0)| 00:00:01 |
|* 54 |          INDEX UNIQUE SCAN                | SYS_C00468549              |     1 |       |     0   (0)| 00:00:01 |
|* 55 |        INDEX RANGE SCAN                   | IDX_TECH_NODE_ID1          |   587K|  5736K|     2   (0)| 00:00:01 |
|* 56 |       INDEX RANGE SCAN                    | IDX_TECH_OBJECT_ID1        |     1 |       |     2   (0)| 00:00:01 |
------------------------------------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
  12 - filter("N"."NODE_TYPE"=2)
  13 - filter("N"."TECH_OBJECT_ID"=15773325)
  15 - access("N"."TECH_OBJECT_ID"=15773325)
  20 - access("N"."PARENT_ID"=NULL)
  21 - access("N"."PARENT_ID"=NULL)
  22 - filter("D"."IS_SHARE_DEVICE"=1 AND "D"."CURRENT_STATUS"=0)
  23 - access("TAB"."TECH_OBJECT_ID"="D"."DEVICE_ID")
  24 - filter("C"."ALIAS_NAME"='A176')
  25 - access("D"."CLASSIFY_ID"="C"."CLASSIFY_ID")
  26 - access("N"."TECH_OBJECT_ID"="D"."DEVICE_ID" AND "N"."NODE_TYPE"=2)
  27 - access("L"."DEVICE_ID"="D"."DEVICE_ID")
  28 - filter("F"."SITE_ID"=1021)
  29 - access("F"."FUNCTION_LOCATION_ID"="L"."FUNCTION_LOCATION_ID")
  30 - access("N"."TECH_OBJECT_ID"="F"."FUNCTION_LOCATION_ID")
  39 - filter("N"."NODE_TYPE"=2)
  40 - filter("N"."TECH_OBJECT_ID"=15773325)
  42 - access("N"."TECH_OBJECT_ID"=15773325)
  47 - access("N"."PARENT_ID"=NULL)
  48 - access("N"."PARENT_ID"=NULL)
  49 - filter("D"."IS_SHARE_DEVICE"=0 AND "D"."CURRENT_STATUS"=0)
  50 - access("TAB"."TECH_OBJECT_ID"="D"."DEVICE_ID")
  51 - filter("F"."SITE_ID"=1021)
  52 - access("F"."FUNCTION_LOCATION_ID"="D"."FUNCTION_LOCATION_ID")
  53 - filter("C"."ALIAS_NAME"='A176')
  54 - access("D"."CLASSIFY_ID"="C"."CLASSIFY_ID")
  55 - access("N"."TECH_OBJECT_ID"="D"."DEVICE_ID" AND "N"."NODE_TYPE"=2)
  56 - access("N"."TECH_OBJECT_ID"="F"."FUNCTION_LOCATION_ID")
统计信息
----------------------------------------------------------
          7  recursive calls
          0  db block gets
        738  consistent gets
          0  physical reads
          0  redo size
       2606  bytes sent via SQL*Net to client
      10273  bytes received via SQL*Net from client
          2  SQL*Net roundtrips to/from client
         18  sorts (memory)
          0  sorts (disk)
          1  rows processed

   用另一种方式实现分页。
SELECT AB.*
  FROM  (SELECT tt.*,row_number()over(ORDER BY SORT_NO, name) nr
                   from (SELECT DISTINCT (D.DEVICE_ID),
                                         D.NAME,
                                         N.Full_Path SORT_NO,
                                         F.FUNCTION_LOCATION_ID
                           from GG_device D,
                                GG_CLASSIFY_CARD C,
                                GG_function_location F,
                                GG_fl_device L,
                                GG_tech_object_node n,
                                (SELECT N.TECH_OBJECT_ID
                                   FROM GG_TECH_OBJECT_NODE N
                                  WHERE N.NODE_TYPE = 2
                                  START WITH N.TECH_OBJECT_ID = 15773325
                                 CONNECT BY PRIOR
                                             N.TECH_OBJECT_NODE_ID = N.PARENT_ID) TAB
                          where F.FUNCTION_LOCATION_ID =
                                L.FUNCTION_LOCATION_ID
                            and L.Device_Id = d.device_id
                            and d.classify_id = c.classify_id
                            AND EXISTS
                          (SELECT 1
                                   FROM GG_TECH_OBJECT_NODE N
                                  WHERE N.TECH_OBJECT_ID = D.DEVICE_ID
                                    AND N.NODE_TYPE = 2)
                            AND D.CURRENT_STATUS = 0
                            AND D.IS_SHARE_DEVICE = 1
                            AND TAB.TECH_OBJECT_ID = D.DEVICE_ID
                            and n.tech_object_id = f.function_location_id
                            AND F.SITE_ID = 1021
                            AND C.ALIAS_NAME IN ('A176')
                         union all
                         SELECT DISTINCT (D.DEVICE_ID),
                                         D.NAME,
                                         N.Full_Path SORT_NO,
                                         F.FUNCTION_LOCATION_ID
                           FROM GG_DEVICE D,
                                GG_CLASSIFY_CARD C,
                                GG_FUNCTION_LOCATION F,
                                GG_tech_object_node n,
                                (SELECT N.TECH_OBJECT_ID
                                   FROM GG_TECH_OBJECT_NODE N
                                  WHERE N.NODE_TYPE = 2
                                  START WITH N.TECH_OBJECT_ID = 15773325
                                 CONNECT BY PRIOR
                                             N.TECH_OBJECT_NODE_ID = N.PARENT_ID) TAB
                          WHERE D.CLASSIFY_ID = C.CLASSIFY_ID
                            AND F.FUNCTION_LOCATION_ID(+) =
                                D.FUNCTION_LOCATION_ID
                            and n.tech_object_id = f.function_location_id
                            AND EXISTS
                          (SELECT 1
                                   FROM GG_TECH_OBJECT_NODE N
                                  WHERE N.TECH_OBJECT_ID = D.DEVICE_ID
                                    AND N.NODE_TYPE = 2)
                            AND D.CURRENT_STATUS = 0
                            AND D.IS_SHARE_DEVICE = 0
                            AND TAB.TECH_OBJECT_ID = D.DEVICE_ID
                            AND F.SITE_ID = 1021
                            AND C.ALIAS_NAME IN ('A176')) tt
                   ) AB where ab.nr between 1 and 25;
  
已用时间:  00: 00: 00.06
执行计划
----------------------------------------------------------
Plan hash value: 3880620066
--------------------------------------------------------------------------------------------------------------------------
| Id  | Operation                                   | Name                       | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT                            |                            |     2 |  7472 |    42   (8)| 00:00:01 |
|*  1 |  VIEW                                       |                            |     2 |  7472 |    42   (8)| 00:00:01 |
|*  2 |   WINDOW SORT PUSHED RANK                   |                            |     2 |  7446 |    42   (8)| 00:00:01 |
|   3 |    VIEW                                     |                            |     2 |  7446 |    41   (5)| 00:00:01 |
|   4 |     UNION-ALL                               |                            |       |       |         |     |
|   5 |      HASH UNIQUE                            |                            |     1 |   345 |    21   (5)| 00:00:01 |
|   6 |       TABLE ACCESS BY INDEX ROWID           | GG_TECH_OBJECT_NODE      |     1 |   103 |     3   (0)| 00:00:01 |
|   7 |        NESTED LOOPS                         |                            |     1 |   345 |    20   (0)| 00:00:01 |
|   8 |         NESTED LOOPS                        |                            |     1 |   242 |    17   (0)| 00:00:01 |
|   9 |          NESTED LOOPS                       |                            |     1 |   206 |    16   (0)| 00:00:01 |
|  10 |           NESTED LOOPS SEMI                 |                            |     1 |   194 |    15   (0)| 00:00:01 |
|  11 |            NESTED LOOPS                     |                            |     1 |   254 |    13   (0)| 00:00:01 |
|  12 |             NESTED LOOPS                    |                            |     3 |   273 |    10   (0)| 00:00:01 |
|  13 |              VIEW                           |                            |     3 |    21 |     6   (0)| 00:00:01 |
|* 14 |               FILTER                        |                            |       |       |         |     |
|* 15 |                CONNECT BY WITH FILTERING    |                            |       |       |         |     |
|  16 |                 TABLE ACCESS BY INDEX ROWID | GG_TECH_OBJECT_NODE      |       |       |         |     |
|* 17 |                  INDEX RANGE SCAN           | IDX_TECH_OBJECT_ID1        |     1 |     7 |     3   (0)| 00:00:01 |
|  25 |                 NESTED LOOPS                |                            |       |       |         |     |
|  19 |                  BUFFER SORT                |                            |       |       |         |     |
|  20 |                   CONNECT BY PUMP           |                            |       |       |         |     |
|  21 |                  TABLE ACCESS BY INDEX ROWID| GG_TECH_OBJECT_NODE      |     3 |    72 |     6   (0)| 00:00:01 |
|* 22 |                   INDEX RANGE SCAN          | IDX_TECH_OBJECT_PARENT_ID1 |     3 |       |     3   (0)| 00:00:01 |
|* 23 |                 TABLE ACCESS FULL           | GG_TECH_OBJECT_NODE      |     3 |    72 |     6   (0)| 00:00:01 |
|* 24 |              TABLE ACCESS BY INDEX ROWID    | GG_DEVICE                |     1 |    84 |     2   (0)| 00:00:01 |
|* 25 |               INDEX UNIQUE SCAN             | PK_GG_DEVICE             |     1 |       |     1   (0)| 00:00:01 |
|* 26 |             TABLE ACCESS BY INDEX ROWID     | GG_CLASSIFY_CARD          |     1 |    93 |     1   (0)| 00:00:01 |
|* 27 |              INDEX UNIQUE SCAN              | SYS_C00468549              |     1 |       |     0   (0)| 00:00:01 |
|* 28 |            INDEX RANGE SCAN                 | IDX_TECH_NODE_ID1          |   587K|  5736K|     2   (0)| 00:00:01 |
|* 29 |           INDEX RANGE SCAN                  | PK_GG_FL_DEVICE          |     2 |    24 |     1   (0)| 00:00:01 |
|* 30 |          TABLE ACCESS BY INDEX ROWID        | GG_FUNCTION_LOCATION     |     1 |    36 |     1   (0)| 00:00:01 |
|* 31 |           INDEX UNIQUE SCAN                 | PK_GG_FUNCTION_LOCATION  |     1 |       |     0   (0)| 00:00:01 |
|* 32 |         INDEX RANGE SCAN                    | IDX_TECH_OBJECT_ID1        |     1 |       |     2   (0)| 00:00:01 |
|  33 |      HASH UNIQUE                            |                            |     1 |   339 |    20   (5)| 00:00:01 |
|  34 |       TABLE ACCESS BY INDEX ROWID           | GG_TECH_OBJECT_NODE      |     1 |   103 |     3   (0)| 00:00:01 |
|  35 |        NESTED LOOPS                         |                            |     1 |   339 |    19   (0)| 00:00:01 |
|  36 |         NESTED LOOPS SEMI                   |                            |     1 |   236 |    16   (0)| 00:00:01 |
|  37 |          NESTED LOOPS                       |                            |     1 |   226 |    14   (0)| 00:00:01 |
|  38 |           NESTED LOOPS                      |                            |     1 |   133 |    13   (0)| 00:00:01 |
|  39 |            NESTED LOOPS                     |                            |     3 |   291 |    10   (0)| 00:00:01 |
|  40 |             VIEW                            |                            |     3 |    21 |     6   (0)| 00:00:01 |
|* 41 |              FILTER                         |                            |       |       |         |     |
|* 42 |               CONNECT BY WITH FILTERING     |                            |       |       |         |     |
|  43 |                TABLE ACCESS BY INDEX ROWID  | GG_TECH_OBJECT_NODE      |       |       |         |     |
|* 44 |                 INDEX RANGE SCAN            | IDX_TECH_OBJECT_ID1        |     1 |     7 |     3   (0)| 00:00:01 |
|  45 |                NESTED LOOPS                 |                            |       |       |         |     |
|  46 |                 BUFFER SORT                 |                            |       |       |         |     |
|  47 |                  CONNECT BY PUMP            |                            |       |       |         |     |
|  48 |                 TABLE ACCESS BY INDEX ROWID | GG_TECH_OBJECT_NODE      |     3 |    72 |     6   (0)| 00:00:01 |
|* 49 |                  INDEX RANGE SCAN           | IDX_TECH_OBJECT_PARENT_ID1 |     3 |       |     3   (0)| 00:00:01 |
|* 50 |                TABLE ACCESS FULL            | GG_TECH_OBJECT_NODE      |     3 |    72 |     6   (0)| 00:00:01 |
|* 51 |             TABLE ACCESS BY INDEX ROWID     | GG_DEVICE                |     1 |    90 |     2   (0)| 00:00:01 |
|* 52 |              INDEX UNIQUE SCAN              | PK_GG_DEVICE             |     1 |       |     1   (0)| 00:00:01 |
|* 53 |            TABLE ACCESS BY INDEX ROWID      | GG_FUNCTION_LOCATION     |     1 |    36 |     1   (0)| 00:00:01 |
|* 54 |             INDEX UNIQUE SCAN               | PK_GG_FUNCTION_LOCATION  |     1 |       |     0   (0)| 00:00:01 |
|* 55 |           TABLE ACCESS BY INDEX ROWID       | GG_CLASSIFY_CARD          |     1 |    93 |     1   (0)| 00:00:01 |
|* 56 |            INDEX UNIQUE SCAN                | SYS_C00468549              |     1 |       |     0   (0)| 00:00:01 |
|* 57 |          INDEX RANGE SCAN                   | IDX_TECH_NODE_ID1          |   587K|  5736K|     2   (0)| 00:00:01 |
|* 58 |         INDEX RANGE SCAN                    | IDX_TECH_OBJECT_ID1        |     1 |       |     2   (0)| 00:00:01 |
--------------------------------------------------------------------------------------------------------------------------


Predicate Information (identified by operation id):
---------------------------------------------------


   1 - filter("AB"."NR">=1 AND "AB"."NR"<=25)
   2 - filter(ROW_NUMBER() OVER ( ORDER BY "SORT_NO","NAME")<=25)
  14 - filter("N"."NODE_TYPE"=2 AND 1<=25)
  15 - filter("N"."TECH_OBJECT_ID"=15773325)
  17 - access("N"."TECH_OBJECT_ID"=15773325)
  22 - access("N"."PARENT_ID"=NULL)
  23 - access("N"."PARENT_ID"=NULL)
  24 - filter("D"."IS_SHARE_DEVICE"=1 AND "D"."CURRENT_STATUS"=0)
  25 - access("TAB"."TECH_OBJECT_ID"="D"."DEVICE_ID")
  26 - filter("C"."ALIAS_NAME"='A176')
  27 - access("D"."CLASSIFY_ID"="C"."CLASSIFY_ID")
  28 - access("N"."TECH_OBJECT_ID"="D"."DEVICE_ID" AND "N"."NODE_TYPE"=2)
  29 - access("L"."DEVICE_ID"="D"."DEVICE_ID")
  30 - filter("F"."SITE_ID"=1021)
  31 - access("F"."FUNCTION_LOCATION_ID"="L"."FUNCTION_LOCATION_ID")
  32 - access("N"."TECH_OBJECT_ID"="F"."FUNCTION_LOCATION_ID")
  41 - filter("N"."NODE_TYPE"=2 AND 1<=25)
  42 - filter("N"."TECH_OBJECT_ID"=15773325)
  44 - access("N"."TECH_OBJECT_ID"=15773325)
  49 - access("N"."PARENT_ID"=NULL)
  50 - access("N"."PARENT_ID"=NULL)
  51 - filter("D"."IS_SHARE_DEVICE"=0 AND "D"."CURRENT_STATUS"=0)
  52 - access("TAB"."TECH_OBJECT_ID"="D"."DEVICE_ID")
  53 - filter("F"."SITE_ID"=1021)
  54 - access("F"."FUNCTION_LOCATION_ID"="D"."FUNCTION_LOCATION_ID")
  55 - filter("C"."ALIAS_NAME"='A176')
  56 - access("D"."CLASSIFY_ID"="C"."CLASSIFY_ID")
  57 - access("N"."TECH_OBJECT_ID"="D"."DEVICE_ID" AND "N"."NODE_TYPE"=2)
  58 - access("N"."TECH_OBJECT_ID"="F"."FUNCTION_LOCATION_ID")
统计信息
----------------------------------------------------------
          8  recursive calls
          0  db block gets
        863  consistent gets
          0  physical reads
          0  redo size
       2890  bytes sent via SQL*Net to client
      10807  bytes received via SQL*Net from client
          2  SQL*Net roundtrips to/from client
         76  sorts (memory)
          0  sorts (disk)
          1  rows processed  
作者:guogang83 发表于2014-8-20 19:42:40 原文链接
阅读:0 评论:0 查看评论
Viewing all 15843 articles
Browse latest View live


<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>