随笔 - 18, 文章 - 0, 评论 - 8, 引用 - 0
数据加载中……

2017年7月13日

CyclicBarrier 简单举例

一句话解释:预备~~~开始

 1 import java.util.concurrent.BrokenBarrierException;
 2 import java.util.concurrent.CyclicBarrier;
 3 
 4 import org.slf4j.Logger;
 5 import org.slf4j.LoggerFactory;
 6 
 7 public class CyclicBarrierLearn {
 8     
 9     private Logger log = LoggerFactory.getLogger(CyclicBarrierLearn.class);
10     
11     private class Work extends Thread {
12         
13         private String name;
14         private CyclicBarrier cyclicBarrier;
15         
16         public Work(String name, CyclicBarrier cyclicBarrier) {
17             this.name = name;
18             this.cyclicBarrier = cyclicBarrier;
19         }
20         
21         @Override
22         public void run() {
23             try {
24                 log.debug("thread name: " + name + " waiting work");
25                 cyclicBarrier.await();
26                 log.debug("thread name: " + name + " working");
27             } catch (InterruptedException e) {
28                 e.printStackTrace();
29             } catch (BrokenBarrierException e) {
30                 e.printStackTrace();
31             }
32             
33         }
34     }
35     
36     public void cyclicBarrier() {
37         CyclicBarrier cyclicBarrier = new CyclicBarrier(50, new Runnable() {
38             
39             @Override
40             public void run() {
41                 log.debug("let's begin work");
42             }
43         });
44         
45         for (int i = 0; i < cyclicBarrier.getParties(); i++) {
46             Work work = new Work(String.valueOf(i), cyclicBarrier);
47             work.start();
48         }
49         
50     }
51 
52     public static void main(String[] args) {
53         CyclicBarrierLearn cyclicBarrierLearn = new CyclicBarrierLearn();
54         cyclicBarrierLearn.cyclicBarrier();
55 
56     }
57 
58 }
59 

posted @ 2017-07-13 11:39 丑男 阅读(158) | 评论 (0)编辑 收藏

CountDownLatch 简单举例

一句话解释:主线程阻塞,其他线程完成后,主线程被唤醒后继续执行

 1 import java.util.Random;
 2 import java.util.concurrent.CountDownLatch;
 3 
 4 import org.slf4j.Logger;
 5 import org.slf4j.LoggerFactory;
 6 
 7 public class CountDownLatchLearn {
 8     
 9     private Logger log = LoggerFactory.getLogger(CountDownLatchLearn.class);
10     private CountDownLatch countDownLatch;
11     
12     public CountDownLatchLearn() {
13         countDownLatch = new CountDownLatch(50);
14     }
15     
16     public void countDown() {
17         Long count = countDownLatch.getCount();
18         log.debug("countDownLatch count is:" + count.toString());
19         
20         for (int i = 0; i < count; i++) {
21             Work work = new Work(String.valueOf(i), countDownLatch);
22             work.start();
23         }
24         try {
25             countDownLatch.await();
26         } catch (InterruptedException e) {
27             e.printStackTrace();
28         }
29         log.debug("work finish!!!");
30     }
31     
32     private class Work extends Thread {
33         
34         private String name;
35         private CountDownLatch countDownLatch;
36         
37         public Work(String name, CountDownLatch countDownLatch) {
38             this.name = name;
39             this.countDownLatch = countDownLatch;
40         }
41         
42         @Override
43         public void run() {
44             Random r = new Random();
45             int sleep = r.nextInt(2000);
46             try {
47                 log.debug("thread sleep: "+ sleep);
48                 Thread.sleep(sleep);
49             } catch (InterruptedException e) {
50                 e.printStackTrace();
51             }
52             log.debug("thread: " + name + ": do work");
53             countDownLatch.countDown();
54         }
55     }
56 
57     public static void main(String[] args) {
58         System.out.println("main start!!!");
59         
60         CountDownLatchLearn countDownLatchLearn = new CountDownLatchLearn();
61         countDownLatchLearn.countDown();
62         
63         System.out.println("main end!!!");
64     }
65 
66 }

posted @ 2017-07-13 11:18 丑男 阅读(293) | 评论 (0)编辑 收藏

2017年7月10日

mysql 5.7 for windows安装过程

环境说明:

OSwindows 7 64bit Databasemysql-5.7.18-winx64 Noinstall版本

 

1. 解压Mysql安装目录

2. 编写my.ini配置文件

3. mysqld --defaults-file=../my.ini --initialize

4. ALTER USER 'root'@'localhost' IDENTIFIED BY 'password';

5. mysql –u root –p

6. 密码在logs/*.err日志中

 
my.ini文件内容

 1 # my.ini文件内容
 2 # For advice on how to change settings please see
 3 # http://dev.mysql.com/doc/refman/5.7/en/server-configuration-defaults.html
 4 # *** DO NOT EDIT THIS FILE. It's a template which will be copied to the
 5 # *** default location during install, and will be replaced if you
 6 # *** upgrade to a newer version of MySQL.
 7 
 8 [mysqld]
 9 
10 # Remove leading # and set to the amount of RAM for the most important data
11 # cache in MySQL. Start at 70% of total RAM for dedicated server, else 10%.
12 # innodb_buffer_pool_size = 128M
13 
14 # Remove leading # to turn on a very important data integrity option: logging
15 # changes to the binary log between backups.
16 # log_bin
17 
18 # These are commonly set, remove the # and set as required.
19 basedir=D:\\mysql-5.7.18-winx64
20 datadir=D:\\mysql-5.7.18-winx64\\data
21 # port = ..
22 # server_id = ..
23 
24 
25 # Remove leading # to set options mainly useful for reporting servers.
26 # The server defaults are faster for transactions and fast SELECTs.
27 # Adjust sizes as needed, experiment to find the optimal values.
28 # join_buffer_size = 128M
29 # sort_buffer_size = 2M
30 # read_rnd_buffer_size = 2M 
31 
32 sql_mode=NO_ENGINE_SUBSTITUTION,STRICT_TRANS_TABLES
33 
34 long_query_time=0.1
35 slow_query_log=on
36 slow_query_log_file=D:\\mysql-5.7.18-winx64\\logs\\mysqlslow.log
37 

posted @ 2017-07-10 00:53 丑男 阅读(173) | 评论 (0)编辑 收藏

2013年5月6日

添加用户【备份】

useradd -g 501 -s /sbin/nologin builder

posted @ 2013-05-06 17:25 丑男 阅读(108) | 评论 (0)编辑 收藏

2009年4月29日

[ZT]Java虚拟机JVM的调优参数选择

在任何一个的生产系统上线前,系统性能调优(Tuning)都是很重要的一步。通常,应用系统的软硬件的缺省值都是给开发平台(或小规模系统)设计的,用来跑生产系统几乎都无法发挥出软硬件的最佳性能。有时,系统调优前后的性能会差好几倍。另一方面,由于应用程序的开发人员通常都是针对功能作开发的,因此,开发硬件都是比生产环境要小的机器。例如,生产系统是一台8个CPU,64GB内存服务器,而开发服务器可能只有1个CPU和4GB内存。所以,在开发人员中常常不具备做性能方面测试的软硬件环境。另外,有的程序员甚至在开发时都没有考虑到多用户并发的环境,程序中存在单点瓶颈等问题。在做压力测试和调优时,往往就会发现这些关键点。

  由于应用系统是个软硬件的完整统一体,系统调优往往需要涉及硬件、网络操作系统、中间件,应用程序和数据库等方面。在调优的过程中,往往需要发现存在瓶颈的地方(也就是导致系统变慢的部分),分析原因,从而改进和确定较优的参数。

  我们在作JVM的调优前,通常先要了解运行的硬件平台,操作系统和中间件,然后针对这些情况配置相应的系统参数,在测试中不断完善参数。由于性能调优需要对系统非常了解,并且需要丰富的经验,因此不是一件容易的事情。这里介绍一些很好的参考资料,就是SPEC.org的网站。这是硬件厂商公布benchmark测试结果的地方,通常硬件厂商会把系统调到最优化才公布结果的,因此很有借鉴意义。常见和JVM有关的benchmark值主要有SPECjAppServer2004和SPECjbb2005。前者是J2EE应用服务器的性能指标,后者是服务器端Java虚拟机的性能指标。给大家介绍这个网站的目的是说大家可以参考硬件厂商给出的JVM配置,在根据自己应用环境的特点,较快的得出较好的参数。例如,这个网页给出了SUN公司T5120服务器+应用服务器9.1 +JDK1.5的SPECjAppServer2004值是8,439.36:

  http://www.spec.org/jAppServer2004/results/res2007q4/jAppServer2004-20071106-00092.html

  我们现在要关心的不是Benchmark的值(注:实际上,Sun公司的这个值是个很不错的结果),而是留意在这种环境下JVM的参数配置,可以找到一个栏目“Notes / Tuning Information”:

  JVM Options: -server -XX:+AggressiveHeap

-Xmx2560m -Xms2560m -Xmn1024m -Xss128k

-XX:PermSize=256m

-XX:+DisableExplicitGC

-XX:ParallelGCThreads=24

-XX:LargePageSizeInBytes=256m

-XX:+UseParallelOldGC

-XX:+AggressiveOpts

-DAllowManagedFieldsInDefaultFetchGroup=true

-DAllowMediatedWriteInDefaultFetchGroup=true

-XX:-UseBiasedLocking

-Dcom.sun.ejb.containers.readonly.relative.refresh.mode=true

-Dcom.sun.jts.dblogging.insertquery=insert into

txn_log_table_0 values (
? , ? , ? )

-Dcom.sun.jts.dblogging.deletequery=delete from

txn_log_table_0 where localtid
= ? and servername = ?

-Dcom.sun.jdo.spi.persistence.support.sqlstore.

MULTILEVEL_PREFETCH
=true

  那么上面那些参数是什么意思呢?上述段落中“-XX”的参数是SUN JVM的扩展选项,其中以下的这些都是和垃圾回收(GC)有关:

  -XX:PermSize=256m

-XX:+DisableExplicitGC

-XX:ParallelGCThreads=24

-XX:+UseParallelOldGC

-XX:+AggressiveHeap

  下面这个选项是选择大的内存页面:

  -XX:LargePageSizeInBytes=256m

  "-XX:+AggressiveOpts"是一些试验性优化参数,“-XX:-UseBiasedLocking”是非竞争性的同步选项。

  而选项“-Xmx2560m -Xms2560m -Xmn1024m -Xss128k”则是初始堆栈的内存值,注意-Xmx和-Xms的值是一样的,这样系统性能会较平稳些。

  至于这些参数详细代表什么意义,大家可以google一下就很容易了解。这是Sun网站上的说明,有兴趣的可以读一下: http://java.sun.com/performance/reference/whitepapers/tuning.html

  如果你的应用系统是JDK1.5,硬件是T5120,操作系统是Solaris,那么这些参数就很有借鉴意义。如果你的硬件系统不是T5120,但是使用SUN的JDK1.5 ,这些参数也是有一定参考作用。当然,最理想的是选择一个和自己的环境最近似的结果来参考。大多数软硬件的测试结果都可以在SPEC.org上找到,如果你的系统是J2EE的3层架构,可以用jAppServer2004指标,如果是纯JAVA的应用,可用jbb2005的结果:

  http://www.spec.org/jAppServer2004/

  http://www.spec.org/jbb2005/

  需要注意的是,这些调优参数只是提供了一个思路,具体是否合适你的应用还要看实测结果。

posted @ 2009-04-29 19:24 丑男 阅读(248) | 评论 (0)编辑 收藏

2008年8月23日

[转帖]Hibernate常用保存

hibernate对于对象的保存提供了太多的方法,他们之间有很多不同,这里细说一下,以便区别:
一、预备知识:
在所有之前,说明一下,对于hibernate,它的对象有三种状态,transient、persistent、detached
下边是常见的翻译办法:
transient:瞬态或者自由态
persistent:持久化状态
detached:脱管状态或者游离态
脱管状态的实例可以通过调用save()、persist()或者saveOrUpdate()方法进行持久化。
持久化实例可以通过调用 delete()变成脱管状态。通过get()或load()方法得到的实例都是持久化状态的。
脱管状态的实例可以通过调用 update()、0saveOrUpdate()、lock()或者replicate()进行持久化。
save() 和persist()将会引发SQL的INSERT,delete()会引发SQLDELETE,而update()或merge()会引发 SQLUPDATE.对持久化(persistent)实例的修改在刷新提交的时候会被检测到,它也会引起 SQLUPDATE.saveOrUpdate()或者replicate()会引发SQLINSERT或者UPDATE
二、save 和update区别
把这一对放在第一位的原因是因为这一对是最常用的。
save的作用是把一个新的对象保存
update是把一个脱管状态的对象保存
三、update 和saveOrUpdate区别
这个是比较好理解的,顾名思义,saveOrUpdate基本上就是合成了save和update引用hibernate reference中的一段话来解释他们的使用场合和区别。
通常下面的场景会使用update()或saveOrUpdate():
程序在第一个session中加载对象
该对象被传递到表现层
对象发生了一些改动
该对象被返回到业务逻辑层
程序调用第二个session的update()方法持久这些改动
saveOrUpdate()做下面的事:
如果对象已经在本session中持久化了,不做任何事
如果另一个与本session关联的对象拥有相同的持久化标识(identifier),抛出一个异常
如果对象没有持久化标识(identifier)属性,对其调用save()
如果对象的持久标识(identifier)表明其是一个新实例化的对象,对其调用save()
如果对象是附带版本信息的(通过或) 并且版本属性的值表明其是一个新实例化的对象,save()它。
四、persist和save区别
这个是最迷离的一对,表面上看起来使用哪个都行,在hibernate reference文档中也没有明确的区分他们。
这里给出一个明确的区分。(可以跟进src看一下,虽然实现步骤类似,但是还是有细微的差别)
1.persist把一个瞬态的实例持久化,但是并"不保证"标识符被立刻填入到持久化实例中,标识符的填入可能被推迟到flush的时间。
2.persist" 保证",当它在一个transaction外部被调用的时候并不触发一个Sql Insert,这个功能是很有用的,当我们通过继承Session/persistence context来封装一个长会话流程的时候,一个persist这样的函数是需要的。
3.save"不保证"第2条,它要返回标识符,所以它会立即执行Sql insert,不管是不是在transaction内部。
五、saveOrUpdateCopy,merge和update区别
首先说明merge是用来代替saveOrUpdateCopy的,然后比较update和merge,update的作用上边说了,这里说一下merge的作用。
如果session中存在相同持久化标识(identifier)的实例,用用户给出的对象的状态覆盖旧有的持久实例
如果session没有相应的持久实例,则尝试从数据库中加载,或创建新的持久化实例,最后返回该持久实例
用户给出的这个对象没有被关联到session上,它依旧是脱管的
重点是最后一句:
当我们使用update的时候,执行完成后,我们提供的对象A的状态变成持久化状态
但当我们使用merge的时候,执行完成,我们提供的对象A还是脱管状态,hibernate或者new了一个B,或者检索到一个持久对象,并把我们提供的对象A的所有的值拷贝到这个B,执行完成后B是持久状态,而我们提供的A还是托管状态。
六、flush和update区别
这两个的区别好理解
update操作的是在脱管状态的对象,而flush是操作的在持久状态的对象。
默认情况下,一个持久状态的对象是不需要update的,只要你更改了对象的值,等待hibernate flush就自动保存到数据库了。hibernate flush发生再几种情况下:
1.调用某些查询的时候
2.transaction commit的时候
3.手动调用flush的时候
七、lock和update区别
update是把一个已经更改过的脱管状态的对象变成持久状态
lock是把一个没有更改过的脱管状态的对象变成持久状态
对应更改一个记录的内容,两个的操作不同:
update的操作步骤是:
更改脱管的对象->调用update
lock的操作步骤是:
调用lock把对象从脱管状态变成持久状态——>更改持久状态的对象的内容——>等待flush或者手动flush

posted @ 2008-08-23 21:22 丑男 阅读(210) | 评论 (0)编辑 收藏

2008年8月22日

[转帖]Oracle执行计划解释

一.相关的概念

    Rowid的概念:rowid是一个伪列,既然是伪列,那么这个列就不是用户定义,而是系统自己给加上的。 对每个表都有一个rowid的伪列,但是表中并不物理存储ROWID列的值。不过你可以像使用其它列那样使用它,但是不能删除改列,也不能对该列的值进行 修改、插入。一旦一行数据插入数据库,则rowid在该行的生命周期内是唯一的,即即使该行产生行迁移,行的rowid也不会改变。

    Recursive SQL概念:有时为了执行用户发出的一个sql语句,oracle必须执行一些额外的语句,我们将这些额外的语句称之为''recursive calls''或''recursive sql statements''.如当一个DDL语句发出后,ORACLE总是隐含的发出一些recursive SQL语句,来修改数据字典信息,以便用户可以成功的执行该DDL语句。当需要的数据字典信息没有在共享内存中时,经常会发生Recursive calls,这些Recursive calls会将数据字典信息从硬盘读入内存中。用户不比关心这些recursive SQL语句的执行情况,在需要的时候,ORACLE会自动的在内部执行这些语句。当然DML语句与SELECT都可能引起recursive sql.简单的说,我们可以将触发器视为recursive sql.

    Row Source(行源):用在查询中,由上一操作返回的符合条件的行的集合,即可以是表的全部行数据的集合;也可以是表的部分行数据的集合;也可以为对上2个row source进行连接操作(如join连接)后得到的行数据集合。

    Predicate(谓词):一个查询中的WHERE限制条件

    Driving table(驱动表):该表又称为外层表(OUTER table)。 这个概念用于嵌套与HASH连接中。如果该row source返回较多的行数据,则对所有的后续操作有负面影响。注意此处虽然翻译为驱动表,但实际上翻译为驱动行源(driving row source)更为确切。一般说来,是应用查询的限制条件后,返回较少行源的表作为驱动表,所以如果一个大表在WHERE条件有有限制条件(如等值限 制),则该大表作为驱动表也是合适的,所以并不是只有较小的表可以作为驱动表,正确说法应该为应用查询的限制条件后,返回较少行源的表作为驱动表。在执行 计划中,应该为靠上的那个row source,后面会给出具体说明。在我们后面的描述中,一般将该表称为连接操作的row source 1.

    Probed table(被探查表):该表又称为内层表(INNER table)。在我们从驱动表中得到具体一行的数据后,在该表中寻找符合连接条件的行。所以该表应当为大表(实际上应该为返回较大row source的表)且相应的列上应该有索引。在我们后面的描述中,一般将该表称为连接操作的row source 2.

    组合索引(concatenated index):由多个列构成的索引,如create index idx_emp on emp(col1, col2, col3, ……),则我们称idx_emp索引为组合索引。在组合索引中有一个重要的概念:引导列(leading column),在上面的例子中,col1列为引导列。当我们进行查询时可以使用“where col1 = ? ”,也可以使用“where col1 = ? and col2 = ?”,这样的限制条件都会使用索引,但是“where col2 = ? ”查询就不会使用该索引。所以限制条件中包含先导列时,该限制条件才会使用该组合索引。

    可选择性(selectivity):比较一下列中唯一键的数量和表中的行数,就可以判断该列的可选择性。 如果该列的“唯一键的数量/表中的行数”的比值越接近1,则该列的可选择性越高,该列就越适合创建索引,同样索引的可选择性也越高。在可选择性高的列上进 行查询时,返回的数据就较少,比较适合使用索引查询。

欢迎进入Oracle社区论坛,与200万技术人员互动交流 >>进入
二.oracle访问数据的存取方法

    1) 全表扫描(Full table Scans, FTS)

    为实现全表扫描,oracle读 取表中所有的行,并检查每一行是否满足语句的WHERE限制条件一个多块读 操作可以使一次I/O能读取多块数据块(db_block_multiblock_read_count参数设定),而不是只读取一个数据块,这极大的减 少了I/O总次数,提高了系统的吞吐量,所以利用多块读的方法可以十分高效地实现全表扫描,而且只有在全表扫描的情况下才能使用多块读操作。在这种访问模 式下,每个数据块只被读一次。

    使用FTS的前提条件:在较大的表上不建议使用全表扫描,除非取出数据的比较多,超过总量的5% —— 10%,或你想使用并行查询功能时。

    使用全表扫描的例子:

    ~~~~~~~~~~~~~~~~~~~~~~~~ sql> explain plan for select * from dual;

    Query Plan

    -----------------------------------------

    SELECT STATEMENT[CHOOSE] Cost=

    table ACCESS FULL DUAL

    2) 通过ROWID的表存取(Table Access by ROWID或rowid lookup)

    行的ROWID指出了该行所在的数据文件、数据块以及行在该块中的位置,所以通过ROWID来存取数据可以快速定位到目标数据上,是Oracle存取单行数据的最快方法。

    这种存取方法不会用到多块读操作,一次I/O只能读取一个数据块。我们会经常在执行计划中看到该存取方法,如通过索引查询数据。

    使用ROWID存取的方法: sql> explain plan for select * from dept where rowid = ''AAAAyGAADAAAAATAAF'';

    Query Plan

    ------------------------------------

    SELECT STATEMENT [CHOOSE] Cost=1

    table ACCESS BY ROWID DEPT [ANALYZED]


    3)索引扫描(Index Scan或index lookup)

    我们先通过index查找到数据对应的rowid值(对于非唯一索引可能返回多个rowid值),然后根据rowid直接从表中得到具体的数据,这 种查找方式称为索引扫描或索引查找(index lookup)。一个rowid唯一的表示一行数据,该行对应的数据块是通过一次i/o得到的,在此情况下该次i/o只会读取一个数据库块。

    在索引中,除了存储每个索引的值外,索引还存储具有此值 的行对应的ROWID值。索引扫描可以由2步组成:(1) 扫描索引得到对应的rowid值。 (2) 通过找到的rowid从表中读出具体的数据。每步都是单独的一次I/O,但是对于索引,由于经常使用,绝大多数都已经CACHE到内存中,所以第1步的 I/O经常是逻辑I/O,即数据可以从内存中得到。但是对于第2步来说,如果表比较大,则其数据不可能全在内存中,所以其I/O很有可能是物理I/O,这 是一个机械操作,相对逻辑I/O来说,是极其费时间的。所以如果多大表进行索引扫描,取出的数据如果大于总量的5% —— 10%,使用索引扫描会效率下降很多。如下列所示:SQL> explain plan for select empno, ename from emp where empno=10;

    Query Plan

    ------------------------------------

    SELECT STATEMENT [CHOOSE] Cost=1

    table ACCESS BY ROWID EMP [ANALYZED]

    INDEX UNIQUE SCAN EMP_I1


    但是如果查询的数据能全在索引中找到,就可以避免进行第2步操作,避免了不必要的I/O,此时即使通过索引扫描取出的数据比较多,效率还是很高的

    sql> explain plan for select empno from emp where empno=10;-- 只查询empno列值

    Query Plan

    ------------------------------------

    SELECT STATEMENT [CHOOSE] Cost=1

    INDEX UNIQUE SCAN EMP_I1

    进一步讲,如果sql语句中对索引列进行排序,因为索引已经预先排序好了,所以在执行计划中不需要再对索引列进行排序
    sql> explain plan for select empno, ename from emp

    where empno > 7876 order by empno;

    Query Plan

    --------------------------------------------------------------------------------

    SELECT STATEMENT[CHOOSE] Cost=1

    table ACCESS BY ROWID EMP [ANALYZED]

    INDEX RANGE SCAN EMP_I1 [ANALYZED]


    从这个例子中可以看到:因为索引是已经排序了的,所以将按照索引的顺序查询出符合条件的行,因此避免了进一步排序操作。

根据索引的类型与where限制条件的不同,有4种类型的索引扫描:

    索引唯一扫描(index unique scan)

    索引范围扫描(index range scan)

    索引全扫描(index full scan)

    索引快速扫描(index fast full scan)

    (1) 索引唯一扫描(index unique scan)

    通过唯一索引查找一个数值经常返回单个ROWID.如果存在UNIQUE 或PRIMARY KEY 约束(它保证了语句只存取单行)的话,Oracle经常实现唯一性扫描。

    使用唯一性约束的例子:

    sql> explain plan for

    select empno,ename from emp where empno=10;

    Query Plan

------------------------------------

    SELECT STATEMENT [CHOOSE] Cost=1

    table ACCESS BY ROWID EMP [ANALYZED]

    INDEX UNIQUE SCAN EMP_I1

    (2) 索引范围扫描(index range scan)

    使用一个索引存取多行数据,在唯一索引上使用索引范围扫描的典型情况下是在谓词(where限制条件)中使用了范围操作符(如>、<、<>、>=、<=、between)

    使用索引范围扫描的例子:

    sql> explain plan for select empno,ename from emp

    where empno > 7876 order by empno;

    Query Plan

--------------------------------------------------------------------------------

    SELECT STATEMENT[CHOOSE] Cost=1

    table ACCESS BY ROWID EMP [ANALYZED]

    INDEX RANGE SCAN EMP_I1 [ANALYZED]

    在非唯一索引上,谓词col = 5可能返回多行数据,所以在非唯一索引上都使用索引范围扫描。

    使用index rang scan的3种情况:

    (a) 在唯一索引列上使用了range操作符(> < <> >= <= between)

    (b) 在组合索引上,只使用部分列进行查询,导致查询出多行

    (c) 对非唯一索引列上进行的任何查询。

    (3) 索引全扫描(index full scan)

    与全表扫描对应,也有相应的全索引扫描。而且此时查询出的数据都必须从索引中可以直接得到。

    全索引扫描的例子:

    An Index full scan will not perform single block i/o''s and so it may prove to be inefficient.

    e.g.

    Index BE_IX is a concatenated index on big_emp (empno, ename)

    sql> explain plan for select empno, ename from big_emp order by empno,ename;

    Query Plan

--------------------------------------------------------------------------------

    SELECT STATEMENT[CHOOSE] Cost=26

    INDEX FULL SCAN BE_IX [ANALYZED]

    (4) 索引快速扫描(index fast full scan)

    扫描索引中的所有的数据块,与 index full scan很类似,但是一个显著的区别就是它不对查询出的数据进行排序,即数据不是以排序顺序被返回。在这种存取方法中,可以使用多块读功能,也可以使用并行读入,以便获得最大吞吐量与缩短执行时间。

    索引快速扫描的例子:

    BE_IX索引是一个多列索引: big_emp (empno,ename)

    sql> explain plan for select empno,ename from big_emp;

    Query Plan

------------------------------------------

    SELECT STATEMENT[CHOOSE] Cost=1

    INDEX FAST FULL SCAN BE_IX [ANALYZED]

    只选择多列索引的第2列:

    sql> explain plan for select ename from big_emp;

    Query Plan

------------------------------------------

    SELECT STATEMENT[CHOOSE] Cost=1

    INDEX FAST FULL SCAN BE_IX [ANALYZED]

   三、表之间的连接

    Join是一种试图将两个表结合在一起的谓词,一次只能连接2个表,表连接也可以被称为表关联。在后面的叙 述中,我们将会使用“row source”来代替“表”,因为使用row source更严谨一些,并且将参与连接的2个row source分别称为row source1和row source 2.Join过程的各个步骤经常是串行操作,即使相关的row source可以被并行访问,即可以并行的读取做join连接的两个row source的数据,但是在将表中符合限制条件的数据读入到内存形成row source后,join的其它步骤一般是串行的。有多种方法可以将2个表连接起来,当然每种方法都有自己的优缺点,每种连接类型只有在特定的条件下才会 发挥出其最大优势。

    row source(表)之间的连接顺序对于查询的效率有非常大的影响。通过首先存取特定的表,即将该表作为驱动表,这样可以先应用某些限制条件,从而得到一个 较小的row source,使连接的效率较高,这也就是我们常说的要先执行限制条件的原因。一般是在将表读入内存时,应用where子句中对该表的限制条件。

    根据2个row source的连接条件的中操作符的不同,可以将连接分为等值连接(如WHERE A.COL3 = B.COL4)、非等值连接(WHERE A.COL3 > B.COL4)、外连接(WHERE A.COL3 = B.COL4(+))。上面的各个连接的连接原理都基本一样,所以为了简单期间,下面以等值连接为例进行介绍。

    在后面的介绍中,都已:

    SELECT A.COL1, B.COL2

    FROM A, B

    WHERE A.COL3 = B.COL4;

    为例进行说明,假设A表为Row Soruce1,则其对应的连接操作关联列为COL 3;B表为Row Soruce2,则其对应的连接操作关联列为COL 4;

    连接类型:

    目前为止,无论连接操作符如何,典型的连接类型共有3种:

    排序 - - 合并连接(Sort Merge Join (SMJ) )

    嵌套循环(Nested Loops (NL) )

    哈希连接(Hash Join)

    排序 - - 合并连接(Sort Merge Join, SMJ)

    内部连接过程:

    1) 首先生成row source1需要的数据,然后对这些数据按照连接操作关联列(如A.col3)进行排序。

    2) 随后生成row source2需要的数据,然后对这些数据按照与sort source1对应的连接操作关联列(如B.col4)进行排序。

    3) 最后两边已排序的行被放在一起执行合并操作,即将2个row source按照连接条件连接起来

    下面是连接步骤的图形表示:

    MERGE

    /"

    SORTSORT

    ||

    Row Source 1Row Source 2

    如果row source已经在连接关联列上被排序,则该连接操作就不需要再进行sort操作,这样可以大大提高这种连接操作的连接速度,因为排序是个极其费资源的操 作,特别是对于较大的表。预先排序的row source包括已经被索引的列(如a.col3或b.col4上有索引)或row source已经在前面的步骤中被排序了。尽管合并两个row source的过程是串行的,但是可以并行访问这两个row source(如并行读入数据,并行排序)。

    SMJ连接的例子:SQL> explain plan for

    select /*+ ordered */ e.deptno, d.deptno

    from emp e, dept d

    where e.deptno = d.deptno

    order by e.deptno, d.deptno;

    Query Plan

-------------------------------------

    SELECT STATEMENT [CHOOSE] Cost=17

    MERGE JOIN

    SORT JOIN

    table ACCESS FULL EMP [ANALYZED]

    SORT JOIN

    table ACCESS FULL DEPT [ANALYZED]


    排序是一个费时、费资源的操作,特别对于大表。基于这个原因,SMJ经常不是一个特别有效的连接方法,但是如果2个row source都已经预先排序,则这种连接方法的效率也是蛮高的。

    嵌套循环(Nested Loops, NL)

    这个连接方法有驱动表(外部表)的概念。其实,该连接过程就是一个2层嵌套循环,所以外层循环的次数越少越好,这也就是我们为什么将小表或返回较小 row source的表作为驱动表(用于外层循环)的理论依据。但是这个理论只是一般指导原则,因为遵循这个理论并不能总保证使语句产生的I/O次数最少。有时 不遵守这个理论依据,反而会获得更好的效率。如果使用这种方法,决定使用哪个表作为驱动表很重要。有时如果驱动表选择不正确,将会导致语句的性能很差、很 差。

    内部连接过程:

    Row source1的Row 1 —— Probe ->Row source 2

    Row source1的Row 2 —— Probe ->Row source 2

    Row source1的Row 3 —— Probe ->Row source 2

    ……。

    Row source1的Row n —— Probe ->Row source 2

    从内部连接过程来看,需要用row source1中的每一行,去匹配row source2中的所有行,所以此时保持row source1尽可能的小与高效的访问row source2(一般通过索引实现)是影响这个连接效率的关键问题。这只是理论指导原则,目的是使整个连接操作产生最少的物理I/O次数,而且如果遵守这 个原则,一般也会使总的物理I/O数最少。但是如果不遵从这个指导原则,反而能用更少的物理I/O实现连接操作,那尽管违反指导原则吧!因为最少的物理 I/O次数才是我们应该遵从的真正的指导原则,在后面的具体案例分析中就给出这样的例子。

    在上面的连接过程中,我们称Row source1为驱动表或外部表。Row Source2被称为被探查表或内部表。

    在NESTED LOOPS连接中,Oracle读取row source1中的每一行,然后在row sourc2中检查是否有匹配的行,所有被匹配的行都被放到结果集中,然后处理row source1中的下一行。这个过程一直继续,直到row source1中的所有行都被处理。这是从连接操作中可以得到第一个匹配行的最快的方法之一,这种类型的连接可以用在需要快速响应的语句中,以响应速度为 主要目标。

    如果driving row source(外部表)比较小,并且在inner row source(内部表)上有唯一索引,或有高选择性非唯一索引时,使用这种方法可以得到较好的效率。NESTED LOOPS有其它连接方法没有的的一个优点是:可以先返回已经连接的行,而不必等待所有的连接操作处理完才返回数据,这可以实现快速的响应时间。

    如果不使用并行操作,最好的驱动表是那些应用了where 限制条件后,可以返回较少行数据的的表,所以大表也可能称为驱动表,关键看限制条件。对于并行查询,我们经常选择大表作为驱动表,因为大表可以充分利用并 行功能。当然,有时对查询使用并行操作并不一定会比查询不使用并行操作效率高,因为最后可能每个表只有很少的行符合限制条件,而且还要看你的硬件配置是否 可以支持并行(如是否有多个CPU,多个硬盘控制器),所以要具体问题具体对待。

    NL连接的例子:

    sql> explain plan for

    select a.dname,b.sql

    from dept a,emp b

    where a.deptno = b.deptno;

    Query Plan

-------------------------

    SELECT STATEMENT [CHOOSE] Cost=5

    NESTED LOOPS

    table ACCESS FULL DEPT [ANALYZED]

    table ACCESS FULL EMP [ANALYZED]


    哈希连接(Hash Join, HJ)

    这种连接是在oracle 7.3以后引入的,从理论上来说比NL与SMJ更高效,而且只用在CBO优化器中。

    较小的row source被用来构建hash table与bitmap,第2个row source被用来被hansed,并与第一个row source生成的hash table进行匹配,以便进行进一步的连接。Bitmap被用来作为一种比较快的查找方法,来检查在hash table中是否有匹配的行。特别的,当hash table比较大而不能全部容纳在内存中时,这种查找方法更为有用。这种连接方法也有NL连接中所谓的驱动表的概念,被构建为hash table与bitmap的表为驱动表,当被构建的hash table与bitmap能被容纳在内存中时,这种连接方式的效率极高。

    HASH连接的例子:

    sql> explain plan for

    select /*+ use_hash(emp) */ empno

    from emp, dept

    where emp.deptno = dept.deptno;

    Query Plan

----------------------------

    SELECT STATEMENT[CHOOSE] Cost=3

    HASH JOIN

    table ACCESS FULL DEPT

    table ACCESS FULL EMP


    要使哈希连接有效,需要设置HASH_JOIN_ENABLED=TRUE,缺省情况下该参数为TRUE,另外,不要忘了还要设置 hash_area_size参数,以使哈希连接高效运行,因为哈希连接会在该参数指定大小的内存中运行,过小的参数会使哈希连接的性能比其他连接方式还 要低。

    总结一下,在哪种情况下用哪种连接方法比较好:

    排序 - - 合并连接(Sort Merge Join, SMJ):

    a) 对于非等值连接,这种连接方式的效率是比较高的。

    b) 如果在关联的列上都有索引,效果更好。

    c) 对于将2个较大的row source做连接,该连接方法比NL连接要好一些。

    d) 但是如果sort merge返回的row source过大,则又会导致使用过多的rowid在表中查询数据时,数据库性能下降,因为过多的I/O.

    嵌套循环(Nested Loops, NL):

    a) 如果driving row source(外部表)比较小,并且在inner row source(内部表)上有唯一索引,或有高选择性非唯一索引时,使用这种方法可以得到较好的效率。

    b) NESTED LOOPS有其它连接方法没有的的一个优点是:可以先返回已经连接的行,而不必等待所有的连接操作处理完才返回数据,这可以实现快速的响应时间。

    哈希连接(Hash Join, HJ):

    a) 这种方法是在oracle7后来引入的,使用了比较先进的连接理论,一般来说,其效率应该好于其它2种连接,但是这种连接只能用在CBO优化器中,而且需要设置合适的hash_area_size参数,才能取得较好的性能。

    b) 在2个较大的row source之间连接时会取得相对较好的效率,在一个row source较小时则能取得更好的效率。

    c) 只能用于等值连接中

    笛卡儿乘积(Cartesian Product)

    当两个row source做连接,但是它们之间没有关联条件时,就会在两个row source中做笛卡儿乘积,这通常由编写代码疏漏造成(即程序员忘了写关联条件)。笛卡尔乘积是一个表的每一行依次与另一个表中的所有行匹配。在特殊情 况下我们可以使用笛卡儿乘积,如在星形连接中,除此之外,我们要尽量使用笛卡儿乘积,否则,自己想结果是什么吧!

    注意在下面的语句中,在2个表之间没有连接。

    sql> explain plan for

    select emp.deptno,dept,deptno

    from emp,dept

    Query Plan

------------------------

    SLECT STATEMENT [CHOOSE] Cost=5

    MERGE JOIN CARTESIAN

    table ACCESS FULL DEPT

    SORT JOIN

    table ACCESS FULL EMP

    CARTESIAN关键字指出了在2个表之间做笛卡尔乘积。假如表emp有n行,dept表有m行,笛卡尔乘积的结果就是得到n * m行结果。

posted @ 2008-08-22 22:33 丑男 阅读(2484) | 评论 (0)编辑 收藏

2007年7月29日

Fedora 7 安装 nvidia显卡驱动

第一步,到nvidia官方下载驱动,根据自己显卡的型号选择,一定要看readme
第二步,驱动只能在命令行方式下安装,所以要修改/etc/inittab文件
    id:3:initdefault
                3代表文本方式,5代表图形方式
    修改后重启系统
第三步,执行驱动,不出意外会非常的顺利,之后shutdown -r now就完成了

本人也是第一次安装,有不对的地方请大家指正,祝好运

posted @ 2007-07-29 13:48 丑男 阅读(762) | 评论 (0)编辑 收藏

2007年7月16日

apache rewrite 简单应用

主要需求,DNSwww.mydomain.com指向www.mydomain.com/app/login.do

目前是DNS指向某一个IP,不能将IP对应到10.11.xxx.xxx/app/login.do

生产环境WEB服务器是apache server


解决办法
利用apache rewriter功能,在httpd.conf中找到

#LoadModule rewrite_module modules/mod_rewrite.so

将#号去掉,也就是把mod_rewrite.so模块加载进来

之后在文件结尾处添加

rewriteengine on
rewriterule ^/$ http://10.11.xxx.xxx/app/login.do [R]

posted @ 2007-07-16 21:47 丑男 阅读(293) | 评论 (0)编辑 收藏

2005年12月11日

[转贴]jasperreport可以用Collection做为数据源



jasperreport可以用Collection做为数据源,这种方式比用Connection方式更为灵活方便
 

posted @ 2005-12-11 18:12 丑男 阅读(397) | 评论 (0)编辑 收藏