20K技术总结知识点梳理汇总_第1页
20K技术总结知识点梳理汇总_第2页
20K技术总结知识点梳理汇总_第3页
20K技术总结知识点梳理汇总_第4页
20K技术总结知识点梳理汇总_第5页
已阅读5页,还剩94页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

一:20K技术总结:1.基本的OO,AOP设计能力,设计模式基本框架:SSH,SSM,Springboot,dubbo.项目构建,mavenLinux操作,基本命令。Nginx原理,常见web服务器安装,调优JVM基本原理,调优。几种数据库,缓存系统redis。消息中心,rabbitmq。原理及应用。大数据基础,Hadoop,Hbase,Hive,Spark,Scala。数据分析,数据采集throwable:继承自Object类,实现serializable接口,两个子类error和exception二者的不同之处:Exception:1.可以是可被控制(checked)或不可控制的(unchecked)。2.表示一个由程序员导致的错误。3.应该在应用程序级被处理。Error:1.总是不可控制的(unchecked)。2.经常用来用于表示系统错误或低层资源的错误。一般指与虚拟机相关的问题,如系统崩溃,内存溢出等。对于这类错误,仅靠程序本身无法恢复和预防,遇到这样的错误,建议让程序终止。3.如何可能的话,应该在系统级被捕捉。Java中定义了两类异常:1)Checkedexception:这类异常都是Exception的子类。异常的向上抛出机制进行处理,假如子类可能产生A异常,那么在父类中也必须throwsA异常。可能导致的问题:代码效率低,耦合度过高。2)Uncheckedexception:这类异常都是RuntimeException的子类,虽然RuntimeException同样也是Exception的子类,但是它们是非凡的,它们不能通过clientcode来试图解决,所以称为Uncheckedexception。常见的几种RuntimeException如下:NullPointerException-空指针引用异常

ClassCastException-类型强制转换异常。

IllegalArgumentException-传递非法参数异常。

ArithmeticException-算术运算异常

ArrayStoreException-向数组中存放与声明类型不兼容对象异常

IndexOutOfBoundsException-下标越界异常

NegativeArraySizeException-创建一个大小为负数的数组错误异常

NumberFormatException-数字格式异常

SecurityException-安全异常

UnsupportedOperationException-不支持的操作异常Jvm和垃圾回收:Jvm的物理结构1)堆:所有通过new创建的对象的内存都在堆中分配,其大小可以通过-Xmx和-Xms来控制。堆被划分为新生代和旧生代,新生代又被进一步划分为Eden和Survivor区,最后Survivor由FromSpace和ToSpace组成,新生代。新建的对象都是用新生代分配内存,Eden空间不足的时候,会把存活的对象转移到Survivor中,新生代大小可以由-Xmn来控制,也可以用-XX:SurvivorRatio来控制Eden和Survivor的比例旧生代。用于存放新生代中经过多次垃圾回收仍然存活的对象2)栈每个线程执行每个方法的时候都会在栈中申请一个栈帧,每个栈帧包括局部变量区和操作数栈,用于存放此次方法调用过程中的临时变量、参数和中间结果3)本地方法栈用于支持native方法的执行,存储了每个native方法调用的状态4)方法区存放了要加载的类信息、静态变量、final类型的常量、属性和方法信息。JVM用持久代(PermanetGeneration)来存放方法区,可通过-XX:PermSize和-XX:MaxPermSize来指定最小值和最大值一、JavaJVM内存介绍JVM管理两种类型的内存,堆和非堆。按照官方的说法:“Java虚拟机具有一个堆,堆是运行时数据区域,所有类实例和数组的内存均从此处分配。堆是在Java虚拟机启动时创建的。”“在JVM中堆之外的内存称为非堆内存(Non-heapmemory)”。简单来说堆就是Java代码可及的内存,是留给开发人员使用的;非堆就是JVM留给自己用的,所以方法区、JVM内部处理或优化所需的内存(如JIT编译后的代码缓存)、每个类结构(如运行时常数池、字段和方法数据)以及方法和构造方法的代码都在非堆内存中,它和堆不同,运行期内GC不会释放其空间。Jvm虚拟机JVM=

类加载器

classloader+

执行引擎

executionengine+

运行时数据区域

runtimedataarea首先Java源代码文件被Java编译器编译为字节码文件,然后JVM中的类加载器加载完毕之后,交由JVM执行引擎执行。在整个程序执行过程中,JVM中的运行时数据区(内存)会用来存储程序执行期间需要用到的数据和相关信息。因此,在Java中我们常常说到的内存管理就是针对这段空间进行管理(如何分配和回收内存空间)。Java堆(1)Java堆是JVM所管理的最大的一块内存。它是被所有线程共享的一块内存区域,在虚拟机启动时创建。(2)几乎所有的实例对象都是在这块区域中存放。(JIT编译器貌似不是这样的)。(3)Java堆是垃圾收集管理的主要战场。所有Java堆可以细分为:新生代和老年代。再细致分就是把新生代分为:Eden空间、FromSurvivor空间、ToSurvivor空间4.UNION用的比较多unionall是直接连接,取到得是所有值,记录可能有重复union是取唯一值,记录没有重复1、对重复结果的处理:UNION在进行表链接后会筛选掉重复的记录,UnionAll不会去除重复记录。

2、对排序的处理:Union将会按照字段的顺序进行排序;UNIONALL只是简单的将两个结果合并后就返回。

从效率上说,UNIONALL要比UNION快很多,所以,如果可以确认合并的两个结果集中不包含重复数据且不需要排序时的话,那么就使用UNIONALL。5.Oracle查询优化原则一:注意WHERE子句中的连接顺序:

ORACLE采用自下而上的顺序解析WHERE子句,根据这个原理,表之间的连接必须写在其他WHERE条件之前,那些可以过滤掉最大数量记录的条件必须写在WHERE子句的末尾.

尤其是“主键ID=?”这样的条件。原则二:SELECT子句中避免使用‘*‘:

ORACLE在解析的过程中,会将'*'依次转换成所有的列名,这个工作是通过查询数据字典完成的,这意味着将耗费更多的时间。简单地讲,语句执行的时间越短越好(尤其对于系统的终端用户来说)。而对于查询语句,由于全表扫描读取的数据多,尤其是对于大型表不仅查询速度慢,而且对磁盘IO造成大的压力,通常都要避免,而避免的方式通常是使用索引Index使用索引的优势与代价。

优势:

1)索引是表的一个概念部分,用来提高检索数据的效率,ORACLE使用了一个复杂的自平衡B-tree结构.通常,通过索引查询数据比全表扫描要快.当ORACLE找出执行查询和Update语句的最佳路径时,ORACLE优化器将使用索引.同样在联结多个表时使用索引也可以提高效率.

2)另一个使用索引的好处是,它提供了主键(primarykey)的唯一性验证.。那些LONG或LONGRAW数据类型,你可以索引几乎所有的列.通常,在大型表中使用索引特别有效.当然,你也会发现,在扫描小表时,使用索引同样能提高效率.

代价:

虽然使用索引能得到查询效率的提高,但是我们也必须注意到它的代价.索引需要空间来存储,也需要定期维护,每当有记录在表中增减或索引列被修改时,索引本身也会被修改.这意味着每条记录的INSERT,DELETE,UPDATE将为此多付出4,5次的磁盘I/O.因为索引需要额外的存储空间和处理,那些不必要的索引反而会使查询反应时间变慢.。而且表越大,影响越严重。1、避免在索引列上使用NOT,

我们要避免在索引列上使用NOT,NOT会产生在和在索引列上使用函数相同的影响.当ORACLE”遇到”NOT,他就会停止使用索引转而执行全表扫描.2、避免在索引列上使用计算.

WHERE子句中,如果索引列是函数的一部分.优化器将不使用索引而使用全表扫描.举例:低效:SELECT…FROMDEPTWHERESAL*12>25000;高效:SELECT…FROMDEPTWHERESAL>25000/12;3、避免在索引列上使用ISNULL和ISNOTNULL

避免在索引中使用任何可以为空的列,ORACLE性能上将无法使用该索引.对于单列索引,如果列包含空值,索引中将不存在此记录.对于复合索引,如果每个列都为空,索引中同样不存在此记录.如果至少有一个列不为空,则记录存在于索引中.举例:如果唯一性索引建立在表的A列和B列上,并且表中存在一条记录的A,B值为(123,null),ORACLE将不接受下一条具有相同A,B值(123,null)的记录(插入).然而如果所有的索引列都为空,ORACLE将认为整个键值为空而空不等于空.因此你可以插入1000条具有相同键值的记录,当然它们都是空!因为空值不存在于索引列中,所以WHERE子句中对索引列进行空值比较将使ORACLE停用该索引.低效:(索引失效)SELECT…FROMDEPARTMENTWHEREDEPT_CODEISNOTNULL;高效:(索引有效)SELECT…FROMDEPARTMENTWHEREDEPT_CODE>=0;4、注意通配符%的影响

使用通配符的情况下Oracle可能会停用该索引。如:6、索引的一些“脾气”

a.如果检索数据量超过30%的表中记录数.使用索引将没有显著的效率提高.

b.在特定情况下,使用索引也许会比全表扫描慢,但这是同一个数量级上的区别.而通常情况下,使用索引比全表扫描要块几倍乃至几千倍!

除了使用索引,我们还有其他能减少资源消耗的方法:

1、用EXISTS替换DISTINCT:

当提交一个包含一对多表信息(比如部门表和雇员表)的查询时,避免在SELECT子句中使用DISTINCT.一般可以考虑用EXIST替换,EXISTS使查询更为迅速,因为RDBMS核心模块将在子查询的条件一旦满足后,立刻返回结果.

7、通常来说,如果语句能够避免子查询的使用,就尽量不用子查询。因为子查询的开销是相当昂贵的。具体的例子在后面的案例“一条SQL的优化过程”中。8.当一个线程进入一个对象的一个synchronized方法后,其它线程是否可进入此对象的其它方法?分几种情况:1.其他方法前是否加了synchronized关键字,如果没加,则能。2.如果这个方法内部调用了wait,则可以进入其他synchronized方法。3.如果其他个方法都加了synchronized关键字,并且内部没有调用wait,则不能。4.如果其他方法是static,它用的同步锁是当前类的字节码,与非静态的方法不能同步,因为非静态的方法用的是this。状态:就绪,运行,synchronize阻塞,wait和sleep挂起,结束。wait必须在synchronized内部调用。调用线程的start方法后线程进入就绪状态,线程调度系统将就绪状态的线程转为运行状态,遇到synchronized语句时,由运行状态转为阻塞9.HashMap和Hashtable的区别HashMap是Hashtable的轻量级实现(非线程安全的实现),他们都完成了Map接口,HashMap允许将null作为一个entry的key或者value,而Hashtable不允许。10.62、List,Set,Map是否继承自Collection接口?List,Set是,Map不是11.为什么Java中1000==1000为false而100==100为true?这就是它有趣的地方了。如果你看去看Integer.Java类,你会发现有一个内部私有类,IntegerCache.java,它缓存了从-128到127之间的所有的整数对象。如果值的范围在-128到127之间,它就从高速缓存返回实例。在此范围内的“小”整数使用率比大整数要高,因此,使用相同的底层对象是有价值的,可以减少潜在的内存占用。而超过这个范围,就要new对象了,不是同一个对象(在这个范围内,直接从缓存中获取)12,说说String/StringBuffer/StringBuilder它们之间的区别?在大部分情况下,字符串的拼接速度为:StringBuilder>StringBuffer>String。String是不可变的,因此每次对其操作改变其变量值,其实是生成一个新的对象,然后将变量引用指向新对象;因此速度慢。StringBuffer则不同,对其操作即直接操作对象指向的引用,无需产生新对象,速度很快;它是线程安全的,在维护多线程的同步等也会消耗一点性能。StringBuilder是jdk5之后新增的,其用法与StringBuffer完全一致,但它是线程不安全的,在单线程中最佳,因为其不需要维护线程的安全,因此是最快的。String字符串常量(线程安全)。StringBuffer字符串变量(线程安全)。StringBuilder字符串变量(非线程安全)。String是不可变的,StringBuffer/StringBuilder是可变的;String/StringBuffer是线程安全的,StringBuilder是非线程安全的。String是存放在常量池,在编译期已经被确定了。newString()不是字符串常量,它有自己的地址空间,存放在堆空间。而其它两个都存放在堆空间。13.14.Stirng是最基本的数据类型吗?

答:不是.

java中的基本数据类型就八种:byte,short,int,long,float,double,char,

boolean.剩下的都是引用类型(referencetype).15.floatf=1.1;正确吗?答:不正确.1.1是双精度,将双精度赋值给浮点型,属于向下转型,会造成精度的丢失.如果要强制类型转换,可以写成这样floatf=(float)1.1;或者floatf=1.1F;16.shorta=1;a=a+1和shorta=1;a+=1有什么区别?

答:对于a=a+1因为1是int值类型,所以计算的结果是int,要赋值给short,需要强制类型装换才能赋值给short.对于a+=1;其相当于a=(short)(a+1);其中已经做了强制类型装换.17.下面代码打印结果?Integera=100,b=100,c=130,d=130;

System.out.println(a==>b);

System.out.println(c==d);第一个是true,第二个是false.

因为a,b,c,d四个变量都是integer对象的引用,所以==比较的不是值,而是引用.如果整型字面量的值在-128到127之间,那么不会new新的Integer对象,而是直接引用常量池中的Integer对象.18.String类可以被继承吗?答:不可以.因为String类是final类.19.String和StringBuilder,StringBuffer的区别?答:String是只读字符串,String引用的字符串内容是不能被改变的.而StringBuffer和StringBuilder是可变字符串.StringBuilder和StringBuffer的用法相同,区别是StringBuffer被synchronized修饰,效率比StringBuilder低。20.构造器是否可以被重写?答:构造器不能被继承,因此不能被重写,但是可以被重载.21.抽象类和接口的相同点和不同点.答:1.抽象类和接口都不能实例化对象,但是可以定义抽象类和接口类型的引用.

2.继承抽象类和实现接口都要对其中的抽象方法全部实现

3.接口比抽象类更加抽象,抽象类中可以定义构造器,可以有抽象方法和具体方法.

4.接口中方法全部都是抽象方法.

5.抽象类中的成员可以是private,protected,public,接口全部都是public

6.抽象类中可以定义成员变量,而接口中定义的成员变量实际上都是常量.

7.有抽象方法的类必须声明为抽象类,而抽象类未必要有抽象方法.22.java中会存在内存泄露吗?答:理论上java不会存在内存泄露的问题,应为有垃圾回收机制(GC).然而在实际开发中,可能会存在无用但可达的对象,这些对象不能被GC回收,因此会导致内存泄露.例如hibernated的Session中的对象属于持久态,垃圾回收器不会回收这些对象,这些对象中有可能存在无用的垃圾对象.如果关闭不及时,一级缓存就可能导致内存泄露.23.try{}里面return,finally里的代码会不会执行,什么时候被执行?答:会执行.在方法返回给调用者前执行.因为如果存在finally代码块,try中的return语句不会立马返回调用者,而是记录下返回值待finally代码块执行完毕之后在返回.24.List,Map,Set三个接口存取元素时,各自有什么特点?答:List以特定的索引来存取元素,可以有重复元素Set不能存放重复元素.Map保存键值对的映射,映射关系可以是一对一或多对一.Set和Map容器都有基于哈希存储和排序树的两种实现版本,基于哈希存储理论存取时间复杂度是O(1).25.Thread类中的sleep()和对象的wait()有什么区别?答:sleep()方法是线程类的静态方法,调用此方法会让当前线程暂停执行指定时间.将CPU时间片分给其他线程,但是对象的锁依然保持,休眠时间结束会自动回复到就绪状态.wait()是Object类的方法,调用对象的wait()方法导致当前线程放弃对象的锁,线程暂停执行,进入对象的等待池,只有调用对象的notify()方法或notifyAll()方法时,才能唤醒等待池中的线程进入等锁池,如果线程重新获得对象的锁就可以进入就绪状态26.当一个线程进入一个对象的synchronized方法A之后,其它线程是否可进入此对象的synchronized方法B?答:不能。其它线程只能访问该对象的非同步方法,同步方法则不能进入。因为非静态方法上的synchronized修饰符要求执行方法时要获得对象的锁,如果已经进入A方法说明对象锁已经被取走,那么试图进入B方法的线程就只能在等锁池(注意不是等待池哦)中等待对象的锁27.说说synchronized关键字的用法?

答:synchronized关键字可以将对象或者方法标记为同步,以实现对对象和方法的互斥访问,可以用synchronized(对象){…}定义同步代码块,或者在声明方法时将synchronized作为方法的修饰符28.Java如何实现序列化,有什么意义?答:序列化就是一种用来处理对象流的机制,所谓对象流也就是将对象的内容进行流化。可以对流化后的对象进行读写操作,也可将流化后的对象传输于网络之间。序列化是为了解决对象流读写操作时可能引发的问题(如果不进行序列化可能会存在数据乱序的问题)要实现序列化,让类实现Serializable接口.该接口是一个标识性接口,标注该类对象是可被序列化的,然后使用一个输出流来构造一个对象输出流并通过writeObject(Object)方法就可以将实现对象写出如果需要反序列化则可以用一个输入流建立对象输入流,然后通过readObject方法从流中读取对象。序列化除了能够实现对象的持久化之外,还能够用于对象的深度克隆29.线程的sleep()方法和yield()方法有什么区别?答:sleep()方法给其他线程运行机会时不考虑线程的优先级,因此会给低优先级的线程以运行的机会;yield()方法只会给相同优先级或更高优先级的线程以运行的机会;

线程执行sleep()方法后转入阻塞(blocked)状态,而执行yield()方法后转入就绪(ready)状态;

sleep()方法声明抛出InterruptedException,而yield()方法没有声明任何异常;sleep()方法比yield()方法(跟操作系统CPU调度相关)具有更好的可移植性。30.说说你对同步和异步的理解.答:如果系统中存在临界资源(资源数量少于竞争资源的线程数量的资源),例如正在写的数据以后可能被另一个线程读到,或者正在读的数据可能已经被另一个线程写过了,那么这些数据就必须进行同步存取(数据库操作中的排他锁就是最好的例子)当应用程序在对象上调用了一个需要花费很长时间来执行的方法,并且不希望让程序等待方法的返回时,就应该使用异步编程,在很多情况下采用异步途径往往更有效率。事实上,所谓的同步就是指阻塞式操作,而异步就是非阻塞式操作。31.转发(forward)和重定向(redirect)的区别?答:forward是容器中控制权的转向,是服务器请求资源,服务器直接访问目标地址的URL,把那个URL的响应内容读取过来,然后把这些内容再发给浏览器,浏览器根本不知道服务器发送的内容是从哪儿来的,所以它的地址栏中还是原来的地址redirect就是服务器端根据逻辑,发送一个状态码,告诉浏览器重新去请求那个地址,因此从浏览器的地址栏中可以看到跳转后的链接地址,很明显redirect无法访问到服务器保护起来资源,但是可以从一个网站redirect到其他网站。32.说一说spring中依赖注入和AOP的实现机制。答:实现依赖注入的方式包括:构造器注入、设值注入和接口(回调)注入。Spring中可以通过设值注入(setter方法注入)和构造器注入实现IoC,推荐使用的方式为设值注入。实现AOP的方式包括:编译时AOP(需要特殊的编译器)、运行时AOP(代理模式)、加载时AOP(需要特殊的类加载器)。Spring中使用了运行时的AOP,主要通过代理的方式对原来的代码进行增强实现。对于实现了接口的类,Spring通过Java的动态代理(请参考Proxy类和InvocationHandler接口)来进行增强;对于没有实现接口的类,Spring使用第三方字节码生成工具CGLIB,通过继承的方式对原有代码进行增强33.什么是ORM?答:对象关系映射(Object-RelationalMapping,简称ORM)是一种为了解决程序的面向对象模型与数据库的关系模型互不匹配问题的技术;简单的说,ORM是通过使用描述对象和数据库之间映射的元数据(在Java中可以用XML或者是注解),将程序中的对象自动持久化到关系数据库中或者将关系数据库表中的行转换成Java对象,其本质上就是将数据从一种形式转换到另外一种形式。

34.简述一下面向对象的"六原则一法则"答:单一职责原则:一个类只做它该做的事情。单一职责原则想表达的就是"高内聚"开闭原则:软件实体应当对扩展开放,对修改关闭.要做到开闭有两个要点:抽象是关键,一个系统中如果没有抽象类或接口系统就没有扩展点;封装可变性,将系统中的各种可变因素封装到一个继承结构中,依赖倒转原则:面向接口编程,就是声明方法的参数类型、方法的返回类型、变量的引用类型时,尽可能使用抽象类型而不用具体类型,因为抽象类型可以被它的任何一个子类型所替代里氏替换原则:任何时候都可以用子类型替换掉父类型接口隔离原则:接口要小而专,绝不能大而全。接口也应该是高度内聚的.Java中的接口代表能力、代表约定、代表角色,能否正确的使用接口一定是编程水平高低的重要标识合成聚合复用原则:优先使用聚合或合成关系复用代码33.Oracle。Oracle的应用,主要在传统行业的数据化业务中,比如:银行、金融这样的对可用性、健壮性、安全性、实时性要求极高的业务;零售、物流这样对海量数据存储分析要求很高的业务MySQL。MySQL基本是生于互联网,长于互联网。其应用实例也大都集中于互联网方向,MySQL的高并发存取能力并不比大型数据库差,同时价格便宜,安装使用简便快捷,深受广大互联网公司的喜爱。并且由于MySQL的开源特性,针对一些对数据库有特别要求的应用,可以通过修改代码来实现定向优化MSSQLServer。windows生态系统的产品,好处坏处都很分明。好处就是,高度集成化,微软也提供了整套的软件方案,基本上一套win系统装下来就齐活了。因此,不那么缺钱,但很缺IT人才的中小企业,会偏爱MSSQLServer。例如,自建ERP系统、商业智能、垂直领域零售商、餐饮、事业单位等等。35.10、实现一种排序?答: //冒泡排序 publicclassBubbleSort{ publicBubbleSort(){ int[]arr={30,12,34,56,78,48}; for(inti=1;i<arr.length;i++){ for(intj=0;j<arr.length-i;j++){ inttemp; if(arr[j]>arr[j+1]){ temp=arr[j]; arr[j]=arr[j+1]; arr[j+1]=temp; } } } for(inti=0;i<arr.length;i++){ System.out.print(arr[i]+""); } } publicstaticvoidmain(String[]args){ //TODOAuto-generatedmethodstub BubbleSortbs=newBubbleSort(); }}36.8、得到Class的三个过程是什么答: (1)类.class (2)对象.getClass(); (3)Class.forName("类全名")37.3、Hibernate的优化策略答: 1、尽量使用新版本的hibernate; 2、制定合理的缓存策略; 3、采用合理的session管理机制; 4、尽量使用延迟加载; 5、设定合理的批处理参数; 6、尽量使用uuid作为主键生成策略; 7、就有可能的话,使用vision的乐观锁代替悲观锁; 8、开发过程中,打开hibernate的Sql日志输出(hibernate.show_sql=true),观察sql语句进一步的指定实施策略;38.数据库的三大范式?答:1、不可拆分(原子性):数据库的第一范式是在数据库表的设计时,确保数据库表的字段具有不可拆分的原子性;比如, 一格字段为地址,而在实际查询中多次用到省、市,那么我们要将地址改为两个字段省和市。 2、完全依赖:确保表中的每列都和主键相关,也就是说一张数据库表只能存储一种数据,不能将多种数据存储在一张表 中,比如,将订单信息和商品信息存在同一张表中。 3、消除传递依赖:每一列数据都和主键直接相关,而不能间接相关; 34,常见设计模式以及spring用了哪些设计模式?设计模式的六大原则1、开闭原则(OpenClosePrinciple)开闭原则的意思是:对扩展开放,对修改关闭。在程序需要进行拓展的时候,不能去修改原有的代码,实现一个热插拔的效果。简言之,是为了使程序的扩展性好,易于维护和升级。想要达到这样的效果,我们需要使用接口和抽象类,后面的具体设计中我们会提到这点。2、里氏代换原则(LiskovSubstitutionPrinciple)里氏代换原则是面向对象设计的基本原则之一。里氏代换原则中说,任何基类可以出现的地方,子类一定可以出现。LSP是继承复用的基石,只有当派生类可以替换掉基类,且软件单位的功能不受到影响时,基类才能真正被复用,而派生类也能够在基类的基础上增加新的行为。里氏代换原则是对开闭原则的补充。实现开闭原则的关键步骤就是抽象化,而基类与子类的继承关系就是抽象化的具体实现,所以里氏代换原则是对实现抽象化的具体步骤的规范。3、依赖倒转原则(DependenceInversionPrinciple)这个原则是开闭原则的基础,具体内容:针对接口编程,依赖于抽象而不依赖于具体。4、接口隔离原则(InterfaceSegregationPrinciple)这个原则的意思是:使用多个隔离的接口,比使用单个接口要好。它还有另外一个意思是:降低类之间的耦合度。由此可见,其实设计模式就是从大型软件架构出发、便于升级和维护的软件设计思想,它强调降低依赖,降低耦合。5、迪米特法则,又称最少知道原则(DemeterPrinciple)最少知道原则是指:一个实体应当尽量少地与其他实体之间发生相互作用,使得系统功能模块相对独立。6、合成复用原则(CompositeReusePrinciple)合成复用原则是指:尽量使用合成/聚合的方式,而不是使用继承。38.spring中用到哪些设计模式1.工厂模式,这个很明显,在各种BeanFactory以及ApplicationContext创建中都用到了;2.模版模式,这个也很明显,在各种BeanFactory以及ApplicationContext实现中也都用到了;3.代理模式,在Aop实现中用到了JDK的动态代理;4.单例模式,这个比如在创建bean的时候。5.Tomcat中有很多场景都使用到了外观模式,因为Tomcat中有很多不同的组件,每个组件需要相互通信,但又不能将自己内部数据过多地暴露给其他组件。用外观模式隔离数据是个很好的方法。6.策略模式在Java中的应用,这个太明显了,因为Comparator这个接口简直就是为策略模式而生的。Comparable和Comparator的区别一文中,详细讲了Comparator的使用。比方说Collections里面有一个sort方法,因为集合里面的元素有可能是复合对象,复合对象并不像基本数据类型,可以根据大小排序,复合对象怎么排序呢?基于这个问题考虑,Java要求如果定义的复合对象要有排序的功能,就自行实现Comparable接口或Comparator接口.7.原型模式:使用原型模式创建对象比直接new一个对象在性能上好得多,因为Object类的clone()方法是一个native方法,它直接操作内存中的二进制流,特别是复制大对象时,性能的差别非常明显。8.迭代器模式:Iterable接口和Iterator接口

这两个都是迭代相关的接口,可以这么认为,实现了Iterable接口,则表示某个对象是可被迭代的;Iterator接口相当于是一个迭代器,实现了Iterator接口,等于具体定义了这个可被迭代的对象时如何进行迭代的39,Hibernate的缓存处理 Hibernate就是对JDBC进行的封装 带来的就是数据访问效率的降低,和性能的下降 对于Hibernate这类ORM而言,缓存显的尤为重要,它是持久层性能提升的关键####缓存分类 使用的生命周期和Session的生命周期同步(从openSession到mit再到session.rollback()都属于事务范围) 1.一级缓存(事务级缓存):即在当前事务范围内的数据缓存 -就Hibernate来讲,(一级缓存)事务级缓存是基于 Session的生命周期实现的。 在一级缓存失效的时候,才开始二级缓存。 2.应用级(二级)缓存:即在某个应用中或应用中某个独立数据库访问子集中的共享缓存,此缓存可由多个事务共享. 在Hibernate中,应用级缓存由SessionFactory实现。 对同一资源的访问,可能会引起数据同步错误,但如果对访问线程进行同步处理,又会影响并发性能。 3.分布式缓存:即在多个应用实例,多个JVM间共享的缓存策略。 分布式服务器:多个服务器之间使用网关——————把多个请求随机分布在多个服务器上进行处理; 还可以使用均衡的分配方式,设定某一个服务器最大承载量,超过的话就会分配黑另外一个服务器; 这些服务器之间有个要求,就是同步,服务器处理之后的数据是同步的,服务器之间都会认可##持久层框架的查询顺序 1.先找一级缓存:如果有就拿来用。 2.如果没有一级缓存,就进入二级缓存,从二级缓存再找一次。 3.如果还是没有二级缓存,那么就进入数据库进行SQL查询在二级缓存和数据库之间会加一个**即时加载**或**延迟加载**(关联关系时候用的最多)##Hibernate的延迟加载 在有关联的持久类对象中,对一个对象进行的查询也会向另一个对象进行查询。 所谓延迟加载就是当在真正需要数据的时候,才真正执行数据加载操作。 hibernate3.X的lazy(延迟加载)默认值是true,需要注意。 延迟加载类型 1.实体对象的延迟加载 2.集合的延迟加载 3.属性的延迟加载40.applicationContext.xml配置 第一步,制定自动扫描规则,将@Service,@Repository,@Component <context:component-scanbase-package="com"> </context:component-scan> 第二步,配置数据源连接信息 <beanid="dataSource"class="org.springframework.jdbc.datasource.DriverManagerDataSource"> <propertyname="driverClassName"value="org.gjt.mm.mysql.Driver"></property> <propertyname="url"value="jdbc:mysql://localhost:3306/sm?useUnicode=true&characterEncoding=UTF-8&useSSL=true"></property> <propertyname="username"value="root"></property> <propertyname="password"value="lovo"></property> </bean> 第三步,配置Session工厂 <beanid="sqlSessionFactory"class="org.mybatis.spring.SqlSessionFactoryBean"> <propertyname="dataSource"ref="dataSource"></property> <propertyname="configLocation"value="classpath:mybatis.cfg.xml"></property> <propertyname="typeAliasesPackage"value="com.forest.datamag.beans,com.forest.eventmag.beans,com.forest.logmag.beans,com.forest.usermag.beans"></property> </bean> 扫描MapperScanner文件,并与Session进行关联 <beanid="mapperScanner"class="org.mybatis.spring.mapper.MapperScannerConfigurer"> <propertyname="basePackage"value="com.forest.datamag.mapper,com.forest.eventmag.mapper,com.forest.logmag.mapper,com.forest.usermag.mapper"></property> <propertyname="sqlSessionFactory"ref="sqlSessionFactory"></property> </bean> 配置事务管理 <beanid="txManage"class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <propertyname="dataSource"ref="dataSource"></property> </bean> 第一种事务管理方式,注解来管理事务,只適合单数据库操作,并且在开发中使用较少,因为这种方式,还是属于编程式事务范畴 <tx:annotation-driventransaction-manager="txManage"/> 第二种声明式事务方式,采用AOP的思想来完成 <tx:adviceid="txAdvice"transaction-manager="txManage"> <tx:attributes> <tx:methodname="*"propagation="REQUIRED"read-only="true"rollback-for="java.lang.Exception"></tx:method> <tx:methodname="insert*"propagation="REQUIRED"read-only="false"rollback-for="java.lang.Exception"isolation="REPEATABLE_READ"></tx:method> <tx:methodname="save*"propagation="REQUIRED"read-only="false"rollback-for="java.lang.Exception"isolation="REPEATABLE_READ"></tx:method> <tx:methodname="update*"propagation="REQUIRED"read-only="false"rollback-for="java.lang.Exception"isolation="REPEATABLE_READ"></tx:method> <tx:methodname="delete*"propagation="REQUIRED"read-only="false"rollback-for="java.lang.Exception"isolation="REPEATABLE_READ"></tx:method> <tx:methodname="get*"propagation="SUPPORTS"read-only="true"></tx:method> <tx:methodname="query*"propagation="SUPPORTS"read-only="true"></tx:method> <tx:methodname="select*"propagation="SUPPORTS"read-only="true"></tx:method> </tx:attributes> </tx:advice> <aop:config> <aop:pointcutexpression="execution(*com.forest.*.service.impl.*.*(..))"id="serviceMethods"></aop:pointcut> <aop:advisoradvice-ref="txAdvice"pointcut-ref="serviceMethods"></aop:advisor> </aop:config> 编程事务管理声明事务管理:将事务声明在Spring配置文件中,被容器进行事务管理,通过AOP的思想进行事务管理。##事务传播级别7种事务的传播:当多个具有事务控制能力的Service实现类的方法互调时,事务是如何传播控制的。 1.REQUIRED 如果当前没有事务,就新建一个事务--CUD使用。如果已经存在一个事务中,加入到这个事务中。这是最常见的选择. 2.SUPPORTS 支持当前事务,如果当前没有事务,就以非事务方式执行 3.MANDATORY 使用当前的事务,如果当前没有事务,就抛出异常。 4.REQUIRES_NEW 无论有没有事务,都新建一个事务,如果当前存在事务,把当前事务挂起。 5.NOT_SUPPORTED 以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。 6.NEVER 以非事务方式执行,如果当前存在事务,则抛出异常。 7.NESTED 如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则执行与REQUIRED类似的操作HashMap概述HashMap是基于哈希表的Map接口的非同步实现。此实现提供所有可选的映射操作,并允许使用null值和null键。此类不保证映射的顺序,特别是它不保证该顺序恒久不变。HashMap的数据结构在Java编程语言中,最基本的结构就是两种,一个是数组,另外一个是模拟指针(引用),所有的数据结构都可以用这两个基本结构来构造的,HashMap也不例外。HashMap实际上是一个“链表散列”的数据结构,即数组和链表的结合体。从上图中可以看出,HashMap底层就是一个数组结构,数组中的每一项又是一个链表。当新建一个HashMap的时候,就会初始化一个数组。简单来说,HashMap由数组+链表组成的,数组是HashMap的主体,链表则是主要为了解决哈希冲突而存在的,如果定位到的数组位置不含链表(当前entry的next指向null),那么对于查找,添加等操作很快,仅需一次寻址即可;如果定位到的数组包含链表,对于添加操作,其时间复杂度依然为O(1),因为最新的Entry会插入链表头部,仅需简单改变引用链即可,而对于查找操作来讲,此时就需要遍历链表,然后通过key对象的equals方法逐一比对查找。所以,性能考虑,HashMap中的链表出现越少,性能才会越好HashMap的工作原理以及存取方法过程HashMap的工作原理:HashMap是基于散列法(又称哈希法hashing)的原理,使用put(key,value)存储对象到HashMap中,使用get(key)从HashMap中获取对象。当我们给put()方法传递键和值时,我们先对键调用hashCode()方法,返回的hashCode用于找到bucket(桶)位置来储存Entry对象。”HashMap是在bucket中储存键对象和值对象,作为Map.Entry。并不是仅仅只在bucket中存储值。HashMap具体的存取过程如下:

put键值对的方法的过程是:

1、获取key;

2、通过hash函数得到hash值;

inthash=key.hashCode();//获取key的hashCode,这个值是一个固定的int值3、得到桶号(一般都为hash值对桶数求模),也即数组下标intindex=hash%Entry[].length。//获取数组下标:key的hash值对Entry数组长度进行取余4、存放key和value在桶内。

table[index]=Entry对象;get值方法的过程是:

1、获取key

2、通过hash函数得到hash值

inthash=key.hashCode();3、得到桶号(一般都为hash值对桶数求模)

intindex=hash%Entry[].length;4、比较桶的内部元素是否与key相等,若都不相等,则没有找到。5、取出相等的记录的value。HashMap中直接地址用hash函数生成;解决冲突,用比较函数解决。如果每个桶内部只有一个元素,那么查找的时候只有一次比较。当许多桶内没有值时,许多查询就会更快了(指查不到的时候)。HashMap和HashTable的区别一种比较简单的回答是:(1)HashMap是非线程安全的,HashTable是线程安全的。(2)HashMap的键和值都允许有null存在,而HashTable则都不行。(3)因为线程安全、哈希效率的问题,HashMap效率比HashTable的要高。6.

HashTable和ConCurrentHashMap的对比

先对ConcurrentHashMap进行一些介绍吧,它是线程安全的HashMap的实现。HashTable里使用的是synchronized关键字,这其实是对对象加锁,锁住的都是对象整体,当Hashtable的大小增加到一定的时候,性能会急剧下降,因为迭代时需要被锁定很长的时间。ConcurrentHashMap算是对上述问题的优化ConcurrentHashMap引入了分割(Segment),上面代码中的最后一行其实就可以理解为把一个大的Map拆分成N个小的HashTable,在put方法中,会根据hash(paramK.hashCode())来决定具体存放进哪个Segment,如果查看Segment的put操作,我们会发现内部使用的同步机制是基于lock操作的,这样就可以对Map的一部分(Segment)进行上锁,这样影响的只是将要放入同一个Segment的元素的put操作,保证同步的时候,锁住的不是整个Map(HashTable就是这么做的),相对于HashTable提高了多线程环境下的性能,因此HashTable已经被淘汰了。

7.

HashMap和ConCurrentHashMap的对比最后对这俩兄弟做个区别总结吧:(1)经过4.2的分析,我们知道ConcurrentHashMap对整个桶数组进行了分割分段(Segment),然后在每一个分段上都用lock锁进行保护,相对于HashTable的syn关键字锁的粒度更精细了一些,并发性能更好,而HashMap没有锁机制,不是线程安全的。(2)HashMap的键值对允许有null,但是ConCurrentHashMap都不允许。(3)有并发访问的时候用concurrentHashMap效率比用锁的hashmap好,功能上是可以的,但是毕竟concurrentHashMap这种数据结构要复杂一些,如果能保证只在单一县城下读写,不会发生并发的读写,就可以使用hashMap,concurrentHashMap读不加锁,写只加部分锁。在多线程下得高性能读写用比较好。但是这也是要用空间来换的。(4)HashMap.所有已经实现的接口:serializable,cloneable,Map。基于哈希表的map接口的实现。此实现提供所有可选的映射操作。并允许使用null值和null键。(除了非同步和允许使用null之外,hashmap类与hashtable大致相同。此类不保证映射顺序,特别是它不保证该顺序恒久不变)类concurrenthashmap实现接口:serializable,concurrentmap,map4.数据库索引:索引有单列索引

复合索引之说

如何某表的某个字段有主键约束和唯一性约束,则Oracle则会自动在相应的约束列上建议唯一索引。数据库索引主要进行提高访问速度。建设原则:1、索引应该经常建在Where子句经常用到的列上。如果某个大表经常使用某个字段进行查询,并且检索行数小于总表行数的5%。则应该考虑。2、对于两表连接的字段,应该建立索引。如果经常在某表的一个字段进行OrderBy则也经过进行索引。3、不应该在小表上建设索引。创建索引:

单一索引:CreateIndex<Index-Name>On<Table_Name>(Column_Name);复合索引:CreateIndexi_deptno_jobonemp(deptno,job);—>在emp表的deptno、job列建立索引。select*fromempwheredeptno=66andjob='sals'->走索引。select*fromempwheredeptno=66ORjob='sals'->将进行全表扫描。不走索引select*fromempwheredeptno=66->走索引。select*fromempwherejob='sals'->进行全表扫描、不走索引。如果在where子句中有OR操作符或单独引用Job列(索引列的后面列)则将不会走索引,将会进行全表扫描。Sql优化:当Oracle数据库拿到SQL语句时,其会根据查询优化器分析该语句,并根据分析结果生成查询执行计划。

也就是说,数据库是执行的查询计划,而不是Sql语句。

查询优化器有rule-based-optimizer(基于规则的查询优化器)和Cost-Based-optimizer(基于成本的查询优化器)。

其中基于规则的查询优化器在10g版本中消失。

对于规则查询,其最后查询的是全表扫描。而CBO则会根据统计信息进行最后的选择。

1、先执行From->Where->GroupBy->聚集函数->having->计算表达式->select字段->OrderBy2、执行From字句是从右往左进行执行。因此必须选择记录条数最少的表放在右边。这是为什么呢?3、对于Where字句其执行顺序是从后向前执行、因此可以过滤最大数量记录的条件必须写在Where子句的末尾,而对于多表之间的连接,则写在之前。

因为这样进行连接时,可以去掉大多不重复的项。4.SELECT子句中避免使用(*)ORACLE在解析的过程中,会将’*’依次转换成所有的列名,这个工作是通过查询数据字典完成的,这意味着将耗费更多的时间5、索引失效的情况:

①NotNull/Null如果某列建立索引,当进行Select*fromempwheredeptoisnotnull/isnull。则会是索引失效。

②索引列上不要使用函数,SELECTColFROMtblWHEREsubstr(name,1,3)='ABC'

或者SELECTColFROMtblWHEREnameLIKE'%ABC%'而SELECTColFROMtblWHEREnameLIKE'ABC%'会使用索引。③索引列上不能进行计算SELECTColFROMtblWHEREcol/10>10则会使索引失效,应该改成

SELECTColFROMtblWHEREcol>10*10④索引列上不要使用NOT(!=、<>)如:SELECTColFROMtblWHEREcol!=10

应该改成:SELECTColFROMtblWHEREcol>10ORcol<10。6、用UNION替换OR(适用于索引列)

union:是将两个查询的结果集进行追加在一起,它不会引起列的变化。由于是追加操作,需要两个结果集的列数应该是相关的,

并且相应列的数据类型也应该相当的。union返回两个结果集,同时将两个结果集重复的项进行消除。如果不进行消除,用UNOINALL.通常情况下,用UNION替换WHERE子句中的OR将会起到较好的效果.对索引列使用OR将造成全表扫描.注意,以上规则只针对多个索引列有效.

如果有column没有被索引,查询效率可能会因为你没有选择OR而降低.在下面的例子中,LOC_ID和REGION上都建有索引.高效:

SELECTLOC_ID,LOC_DESC,REGION

FROMLOCATION

WHERELOC_ID=10

UNION

SELECTLOC_ID,LOC_DESC,REGION

FROMLOCATION

WHEREREGION=“MELBOURNE”低效:

SELECTLOC_ID,LOC_DESC,REGION

FROMLOCATION

WHERELOC_ID=10ORREGION=“MELBOURNE”

如果你坚持要用OR,那就需要返回记录最少的索引列写在最前面.7.用EXISTS替代IN、用NOTEXISTS替代NOTIN

在许多基于基础表的查询中,为了满足一个条件,往往需要对另一个表进行联接.在这种情况下,使用EXISTS(或NOTEXISTS)通常将提高查询的效率.

在子查询中,NOTIN子句将执行一个内部的排序和合并.无论在哪种情况下,NOTIN都是最低效的(因为它对子查询中的表执行了一个全表遍历).

为了避免使用NOTIN,我们可以把它改写成外连接(OuterJoins)或NOTEXISTS.例子:高效:SELECT*FROMEMP(基础表)WHEREEMPNO>0ANDEXISTS(SELECT‘X’FROMDEPTWHEREDEPT.DEPTNO=EMP.DEPTNOANDLOC=‘MELB’)低效:SELECT*FROMEMP(基础表)WHEREEMPNO>0ANDDEPTNOIN(SELECTDEPTNOFROMDEPTWHERELOC=‘MELB’)EXISTS与IN的使用效率的问题,通常情况下采用exists要比in效率高,因为IN不走索引,但要看实际情况具体使用:

IN适合于外表大而内表小的情况;EXISTS适合于外表小而内表大的情况应该在表中经常搜索的列或者按照顺序访问的列上创建聚簇索引。当创建聚簇索引时,应该考虑这些因素:每一个表只能有一个聚簇索引,因为表中数据的物理顺序

只能有一个;在创建任何非聚簇索引之前创建聚簇索引,这是因为聚簇索引改变了表中行的物理顺序,数据行按

照一定的顺序排列,并且自动维护这个顺序.聚簇索引的平均大小大约是数据表的百分之五,但是,实际的聚簇索引的大小常常根据索引列的大小变化而变化;在索引的创建过程中,SQLServer临时使用当前\o"MySQL知识库"数据库的磁盘空间,当创建聚簇索引时,需要1.2倍的表空间的大小,因此,一定要保证有足够的空间来创建聚簇索引。

当系统访问有非聚簇索引的表中数据时,并且这种非聚簇索引创建在聚簇索引上,那么

它首先从非聚簇索引来找到指向聚簇索引的指针,然后通过使用聚簇索引来找到数据。

当需要以多种方式检索数据时,非聚簇索引是非常有用的。当创建非聚簇索引时,要考虑这些情况:在缺省情况下,所创建的索引是非聚簇索引;在每一个表上面,可以创建不多于249个非聚簇索引,而聚簇索引最多只能有一个。

6.mysql索引的优缺点一、为什么要创建索引呢(优点)?创建索引可以大大提高系统的性能。

第一,

通过创建唯一性索引,可以保证数据库表中每一行数据的唯一性。

第二,

可以大大加快数据的检索速度,这也是创建索引的最主要的原因。

第三,

可以加速表和表之间的连接,特别是在实现数据的参考完整性方面特别有意义。

第四,

在使用分组和排序子句进行数据检索时,同样可以显著减少查询中分组和排序的时间。

第五,

通过使用索引,可以在查询的过程中,使用优化隐藏器,提高系统的性能。

二、建立方向索引的不利因素(缺点)也许会有人要问:增加索引有如此多的优点,为什么不对表中的每一个列创建一个索引呢?这种想法固然有其合理性,然而也有其片面性。虽然,索引有许多优点,但是,为表中的每一个列都增加索引,是非常不明智的。这是因为,增加索引也有许多不利的一个方面。

第一,

创建索引和维护索引要耗费时间,这种时间随着数据量的增加而增加。

第二,

索引需要占物理空间,除了数据表占数据空间之外,每一个索引还要占一定的物理空间,如果要建立聚簇索引,那么需要的空间就会更大。

第三,

当对表中的数据进行增加、删除和修改的时候,索引也要动态的维护,这样就降低了数据的维护速度。

三、创建方向索引的准则索引是建立在数据库表中的某些列的上面。因此,在创建索引的时候,应该仔细考虑在哪些列上可以创建索引,在哪些列上不能创建索引。

一般来说,应该在这些列上创建索引。

第一,

在经常需要搜索的列上,可以加快搜索的速度;

第二,

在作为主键的列上,强制该列的唯一性和组织表中数据的排列结构;

第三,

在经常用在连接的列上,这些列主要是一些外键,可以加快连接的速度;

第四,

在经常需要根据范围进行搜索的列上创建索引,因为索引已经排序,其指定的范围是连续的;

第五,

在经常需要排序的列上创建索引,因为索引已经排序,这样查询可以利用索引的排序,加快排序查询时间;

第六,

在经常使用在WHERE子句中的列上面创建索引,加快条件的判断速度。

同样,对于有些列不应该创建索引。一般来说,不应该创建索引的的这些列具有下列特点:

第一,

对于那些在查询中很少使用或者参考的列不应该创建索引。这是因为,既然这些列很少使用到,因此有索引或者无索引,并不能提高查询速度。相反,由于增加了索引,反而降低了系统的维护速度和增大了空间需求。

第二,

对于那些只有很少数据值的列也不应该增加索引。这是因为,由于这些列的取值很少,例如人事表的性别列,在查询的结果中,结果集的数据行占了表中数据行的很大比例,即需要在表中搜索的数据行的比例很大。增加索引,并不能明显加快检索速度。

第三,

对于那些定义为text,image和bit数据类型的列不应该增加索引。这是因为,这些列的数据量要么相当大,要么取值很少。

第四,

当修改性能远远大于检索性能时,不应该创建索引。这是因为,修改性能和检索性能是互相矛盾的。当增加索引时,会提高检索性能,但是会降低修改性能。当减少索引时,会提高修改性能,降低检索性能。因此,当修改性能远远大于检索性能时,不应该创建索引。

四、创建索引的方法创建索引有多种方法,这些方法包括直接创建索引的方法和间接创建索引的方法。

第一,

直接创建索引,例如使用CREATEINDEX语句或者使用创建索引向导。

第二,

间接创建索引,例如在表中定义主键约束或者唯一性键约束时,同时也创建了索引。

虽然,这两种方法都可以创建索引,但是,它们创建索引的具体内容是有区别的。

使用CREATEINDEX语句或者使用创建索引向导来创建索引,这是最基本的索引创建方式,并且这种方法最具有柔性,可以定制创建出符合自己需要的索引。在使用这种方式创建索引时,可以使用许多选项,例如指定数据页的充满度、进行排序、整理统计信息等,这样可以优化索引。使用这种方法,可以指定索引的类型、唯一性和复合性,也就是说,既可以创建聚簇索引,也可以创建非聚簇索引,既可以在一个列上创建索引,也可以在两个或者两个以上的列上创建索引。

通过定义主键约束或者唯一性键约束,也可以间接创建索引。主键约束是一种保持数据完整性的逻辑,它限制表中的记录有相同的主键记录。在创建主键约束时,系统自动创建了一个唯一性的聚簇索引。虽然,在逻辑上,主键约束是一种重要的结构,但是,在物理结构上,与主键约束相对应的结构是唯一性的聚簇索引。换句话说,在物理实现上,不存在主键约束,而只存在唯一性的聚簇索引。同样,在创建唯一性键约束时,也同时创建了索引,这种索引则是唯一性的非聚簇索引。因此,当使用约束创建索引时,索引的类型和特征基本上都已经确定了,由用户定制的余地比较小。

当在表上定义主键或者唯一性键约束时,如果表中已经有了使用CREATEINDEX语句创建的标准索引时,那么主键约束或者唯一性键约束创建的索引覆盖以前创建的标准索引。也就是说,主键约束或者唯一性键约束创建的索引的优先级高于使用CREATEINDEX语句创建的索引。

五、索引的特征

索引有两个特征,即唯一性索引和复合索引。

唯一性索引保证在索引列中的全部数据是唯一的,不会包含冗余数据。如果表中已经有一个主键约束或者唯一性键约束,那么当创建表或者修改表时,SQLServer自动创建一个唯一性索引。然而,如果必须保证唯一性,那么应该创建主键约束或者唯一性键约束,而不是创建一个唯一性索引。当创建唯一性索引时,应该认真考虑这些规则:当在表中创建主键约束或者唯一性键约束时,SQLServer自动创建一个唯一性索引;如果表中已经包含有数据,那么当创建索引时,SQLServer检查表中已有数据的冗余性;每当使用插入语句插入数据或者使用修改语句修改数据时,SQLServer检查数据的冗余性:如果有冗余值,那么SQLServer取消该语句的执行,并且返回一个错误消息;确保表中的每一行数据都有一个唯一值,这样可以确保每一个实体都可以唯一确认;只能在可以保证实体完整性的列上创建唯一性索引,例如,不能在人事表中的姓名列上创建唯一性索引,因为人们可以有相同的姓名。

复合索引就是一个索引创建在两个列或者多个列上。在搜索时,当两个或者多个列作为一个关键值时,最好在这些列上创建复合索引。当创建复合索引时,应该考虑这些规则:最多可以把16个列合并成一个单独的复合索引,构成复合索引的列的总长度不能超过900字节,也就是说复合列的长度不能太长;在复合索引中,所有的列必须来自同一个表中,不能跨表建立复合列;在复合索引中,列的排列顺序是非常重要的,因此要认真排列列的顺序,原则上,应该首先定义最唯一的列,例如在(COL1,COL2)上的索引与在(COL2,COL1)上的索引是不相同的,因为两个索引的列的顺序不同;为了使查询优化器使用复合索引,查询语句中的WHERE子句必须参考复合索引中第一个列;当表中有多个关键列时,复合索引是非常有用的;使用复合索引可以提高查询性能,减少在一个表中所创建的索引数量。

六、索引的类型根据索引的顺序与数据表的物理顺序是否相同,可以把索引分成两种类型。一种是数据表的物理顺序与索引顺序相同的聚簇索引,另一种是数据表的物理顺序与索引顺序不相同的非聚簇索引。

七、聚簇索引的体系结构索引的结构类似于树状结构,树的顶部称为叶级,树的其它部分称为非叶级,树的根部在非叶级中。同样,在聚簇索引中,聚簇索引的叶级和非叶级构成了一个树状结构,索引的最低级是叶级。在聚簇索引中,表中的数据所在的数据页是叶级,在叶级之上的索引页是非叶级,索引数据所在的索引页是非叶级。在聚簇索引中,数据值的顺序总是按照升序排列。

应该在表中经常搜索的列或者按照顺序访问的列上创建聚簇索引。当创建聚簇索引时,应该考虑这些因素:每一个表只能有一个聚簇索引,因为表中数据的物理顺序只能有一个;表中行的物理顺序和索引中行的物理顺序是相同的,在创建任何非聚簇索引之前创建聚簇索引,这是因为聚簇索引改变了表中行的物理顺序,数据行按照一定的顺序排列,并且自动维护这个顺序;关键值的唯一性要么使用UNIQUE关键字明确维护,要么由一个内部的唯一标识符明确维护,这些唯一性标识符是系统自己使用的,用户不能访问;聚簇索引的平均大小大约是数据表的百分之五,但是,实际的聚簇索引的大小常常根据索引列的大小变化而变化;在索引的创建过程中,SQLServer临时使用当前数据库的磁盘空间,当创建聚簇索引时,需要1.2倍的表空间的大小,因此,一定要保证有足够的空间来创建聚簇索引。

当系统访问表中的数据时,首先确定在相应的列上是否存在有索引和该索引是否对要检索的数据有意义。如果索引存在并且该索引非常有意义,那么系统使用该索引访问表中的记录。系统从索引开始浏览到数据,索引浏览则从树状索引的根部开始。从根部开始,搜索值与每一个关键值相比较,确定搜索值是否大于或者等于关键值。这一步重复进行,直到碰上一个比搜索值大的关键值,或者该搜索值大于或者等于索引页上所有的关键值为止。

系统如何访问表中的数据

一般地,系统访问数据库中的数据,可以使用两种方法:表扫描和索引查找。第一种方法是表扫描,就是指系统将指针放置在该表的表头数据所在的数据页上,然后按照数据页的排列顺序,一页一页地从前向后扫描该表数据所占有的全部数据页,直至扫描完表中的全部记录。在扫描时,如果找到符合查询条件的记录,那么就将这条记录挑选出来。最后,将全部挑选出来符合查询语句

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论