#
第一,谈谈final, finally, finalize的区别。
第二,Anonymous Inner Class (匿名内部类) 是否可以extends(继承)其它类,是否可以implements(实现)interface(接口)?
第三,Static Nested Class 和 Inner Class的不同,说得越多越好(面试题有的很笼统)。
第四,&和&&的区别。
第五,HashMap和Hashtable的区别。
第六,Collection 和 Collections的区别。
第七,什么时候用assert。
第八,GC是什么? 为什么要有GC?
第九,String s = new String("xyz");创建了几个String Object?
第十,Math.round(11.5)等於多少? Math.round(-11.5)等於多少?
第十一,short s1 = 1; s1 = s1 + 1;有什么错? short s1 = 1; s1 += 1;有什么错?
第十二,sleep() 和 wait() 有什么区别?
第十三,Java有没有goto?
第十四,数组有没有length()这个方法? String有没有length()这个方法?
第十五,Overload和Override的区别。Overloaded的方法是否可以改变返回值的类型?
第十六,Set里的元素是不能重复的,那么用什么方法来区分重复与否呢? 是用==还是equals()? 它们有何区别?
第十七,给我一个你最常见到的runtime exception。
第十八,error和exception有什么区别?
第十九,List, Set, Map是否继承自Collection接口?
第二十,abstract class和interface有什么区别?
第二十一,abstract的method是否可同时是static,是否可同时是native,是否可同时是synchronized?
第二十二,接口是否可继承接口? 抽象类是否可实现(implements)接口? 抽象类是否可继承实体类(concrete class)?
第二十三,启动一个线程是用run()还是start()?
第二十四,构造器Constructor是否可被override?
第二十五,是否可以继承String类?
第二十六,当一个线程进入一个对象的一个synchronized方法后,其它线程是否可进入此对象的其它方法?
第二十七,try {}里有一个return语句,那么紧跟在这个try后的finally {}里的code会不会被执行,什么时候被执行,在return前还是后?
第二十八,编程题: 用最有效率的方法算出2乘以8等於几?
第二十九,两个对象值相同(x.equals(y) == true),但却可有不同的hash code,这句话对不对?
第三十,当一个对象被当作参数传递到一个方法后,此方法可改变这个对象的属性,并可返回变化后的结果,那么这里到底是值传递还是引用传递?
第三十一,swtich是否能作用在byte上,是否能作用在long上,是否能作用在String上?
第三十二,编程题: 写一个Singleton出来。
以下是答案
第一,谈谈final, finally, finalize的区别。
final—修饰符(关键字)如果一个类被声明为final,意味着它不能再派生出新的子类,不能作为父类被继承。因此一个类不能既被声明为 abstract的,又被声明为final的。将变量或方法声明为final,可以保证它们在使用中不被改变。被声明为final的变量必须在声明时给定初值,而在以后的引用中只能读取,不可修改。被声明为final的方法也同样只能使用,不能重载
finally—再异常处理时提供 finally 块来执行任何清除操作。如果抛出一个异常,那么相匹配的 catch 子句就会执行,然后控制就会进入 finally 块(如果有的话)。
finalize—方法名。Java 技术允许使用 finalize() 方法在垃圾收集器将对象从内存中清除出去之前做必要的清理工作。这个方法是由垃圾收集器在确定这个对象没有被引用时对这个对象调用的。它是在 Object 类中定义的,因此所有的类都继承了它。子类覆盖 finalize() 方法以整理系统资源或者执行其他清理工作。finalize() 方法是在垃圾收集器删除对象之前对这个对象调用的。
第二,Anonymous Inner Class (匿名内部类) 是否可以extends(继承)其它类,是否可以implements(实现)interface(接口)?
匿名的内部类是没有名字的内部类。不能extends(继承) 其它类,但一个内部类可以作为一个接口,由另一个内部类实现。
第三,Static Nested Class 和 Inner Class的不同,说得越多越好(面试题有的很笼统)。
Nested Class (一般是C++的说法),Inner Class (一般是JAVA的说法)。Java内部类与C++嵌套类最大的不同就在于是否有指向外部的引用上。具体可见http: //www.frontfree.net/articles/services/view.asp?id=704&page=1
注: 静态内部类(Inner Class)意味着1创建一个static内部类的对象,不需要一个外部类对象,2不能从一个static内部类的一个对象访问一个外部类对象
第四,&和&&的区别。
&是位运算符。&&是布尔逻辑运算符。
第五,HashMap和Hashtable的区别。
都属于Map接口的类,实现了将惟一键映射到特定的值上。
HashMap 类没有分类或者排序。它允许一个 null 键和多个 null 值。
Hashtable 类似于 HashMap,但是不允许 null 键和 null 值。它也比 HashMap 慢,因为它是同步的。
第六,Collection 和 Collections的区别。
Collections是个java.util下的类,它包含有各种有关集合操作的静态方法。
Collection是个java.util下的接口,它是各种集合结构的父接口。
第七,什么时候用assert。
断言是一个包含布尔表达式的语句,在执行这个语句时假定该表达式为 true。如果表达式计算为 false,那么系统会报告一个 AssertionError。它用于调试目的:
assert(a > 0); // throws an AssertionError if a <= 0
断言可以有两种形式:
assert Expression1 ;
assert Expression1 : Expression2 ;
Expression1 应该总是产生一个布尔值。
Expression2 可以是得出一个值的任意表达式。这个值用于生成显示更多调试信息的 String 消息。
断言在默认情况下是禁用的。要在编译时启用断言,需要使用 source 1.4 标记:
javac -source 1.4 Test.java
要在运行时启用断言,可使用 -enableassertions 或者 -ea 标记。
要在运行时选择禁用断言,可使用 -da 或者 -disableassertions 标记。
要系统类中启用断言,可使用 -esa 或者 -dsa 标记。还可以在包的基础上启用或者禁用断言。
可以在预计正常情况下不会到达的任何位置上放置断言。断言可以用于验证传递给私有方法的参数。不过,断言不应该用于验证传递给公有方法的参数,因为不管是否启用了断言,公有方法都必须检查其参数。不过,既可以在公有方法中,也可以在非公有方法中利用断言测试后置条件。另外,断言不应该以任何方式改变程序的状态。
第八,GC是什么? 为什么要有GC? (基础)。
GC是垃圾收集器。Java 程序员不用担心内存管理,因为垃圾收集器会自动进行管理。要请求垃圾收集,可以调用下面的方法之一:
System.gc()
Runtime.getRuntime().gc()
第九,String s = new String("xyz");创建了几个String Object?
两个对象,一个是“xyx”,一个是指向“xyx”的引用对象s。
第十,Math.round(11.5)等於多少? Math.round(-11.5)等於多少?
Math.round(11.5)返回(long)12,Math.round(-11.5)返回(long)-11;
第十一,short s1 = 1; s1 = s1 + 1;有什么错? short s1 = 1; s1 += 1;有什么错?
short s1 = 1; s1 = s1 + 1;有错,s1是short型,s1+1是int型,不能显式转化为short型。可修改为s1 =(short)(s1 + 1) 。short s1 = 1; s1 += 1正确。
第十二,sleep() 和 wait() 有什么区别? 搞线程的最爱
sleep()方法是使线程停止一段时间的方法。在sleep 时间间隔期满后,线程不一定立即恢复执行。这是因为在那个时刻,其它线程可能正在运行而且没有被调度为放弃执行,除非(a)“醒来”的线程具有更高的优先级
(b)正在运行的线程因为其它原因而阻塞。
wait()是线程交互时,如果线程对一个同步对象x 发出一个wait()调用,该线程会暂停执行,被调对象进入等待状态,直到被唤醒或等待时间到。
第十三,Java有没有goto?
Goto—java中的保留字,现在没有在java中使用。
第十四,数组有没有length()这个方法? String有没有length()这个方法?
数组没有length()这个方法,有length的属性。
String有有length()这个方法。
第十五,Overload和Override的区别。Overloaded的方法是否可以改变返回值的类型?
方法的重写Overriding和重载Overloading是Java多态性的不同表现。重写Overriding是父类与子类之间多态性的一种表现,重载Overloading是一个类中多态性的一种表现。如果在子类中定义某方法与其父类有相同的名称和参数,我们说该方法被重写 (Overriding)。子类的对象使用这个方法时,将调用子类中的定义,对它而言,父类中的定义如同被“屏蔽”了。如果在一个类中定义了多个同名的方法,它们或有不同的参数个数或有不同的参数类型,则称为方法的重载(Overloading)。Overloaded的方法是可以改变返回值的类型。
第十六,Set里的元素是不能重复的,那么用什么方法来区分重复与否呢? 是用==还是equals()? 它们有何区别?
Set里的元素是不能重复的,那么用iterator()方法来区分重复与否。equals()是判读两个Set是否相等。
equals()和==方法决定引用值是否指向同一对象equals()在类中被覆盖,为的是当两个分离的对象的内容和类型相配的话,返回真值。
第十七,给我一个你最常见到的runtime exception。
ArithmeticException, ArrayStoreException, BufferOverflowException, BufferUnderflowException, CannotRedoException, CannotUndoException, ClassCastException, CMMException, ConcurrentModificationException, DOMException, EmptyStackException, IllegalArgumentException, IllegalMonitorStateException, IllegalPathStateException, IllegalStateException,
ImagingOpException, IndexOutOfBoundsException, MissingResourceException, NegativeArraySizeException, NoSuchElementException, NullPointerException, ProfileDataException, ProviderException, RasterFormatException, SecurityException, SystemException, UndeclaredThrowableException, UnmodifiableSetException, UnsupportedOperationException
第十八,error和exception有什么区别?
error 表示恢复不是不可能但很困难的情况下的一种严重问题。比如说内存溢出。不可能指望程序能处理这样的情况。
exception 表示一种设计或实现问题。也就是说,它表示如果程序运行正常,从不会发生的情况。
第十九,List, Set, Map是否继承自Collection接口?
List,Set是
Map不是
第二十,abstract class和interface有什么区别?
声明方法的存在而不去实现它的类被叫做抽象类(abstract class),它用于要创建一个体现某些基本行为的类,并为该类声明方法,但不能在该类中实现该类的情况。不能创建abstract 类的实例。然而可以创建一个变量,其类型是一个抽象类,并让它指向具体子类的一个实例。不能有抽象构造函数或抽象静态方法。Abstract 类的子类为它们父类中的所有抽象方法提供实现,否则它们也是抽象类为。取而代之,在子类中实现该方法。知道其行为的其它类可以在类中实现这些方法。
接口(interface)是抽象类的变体。在接口中,所有方法都是抽象的。多继承性可通过实现这样的接口而获得。接口中的所有方法都是抽象的,没有一个有程序体。接口只可以定义static final成员变量。接口的实现与子类相似,除了该实现类不能从接口定义中继承行为。当类实现特殊接口时,它定义(即将程序体给予)所有这种接口的方法。然后,它可以在实现了该接口的类的任何对象上调用接口的方法。由于有抽象类,它允许使用接口名作为引用变量的类型。通常的动态联编将生效。引用可以转换到接口类型或从接口类型转换,instanceof 运算符可以用来决定某对象的类是否实现了接口。
第二十一,abstract的method是否可同时是static,是否可同时是native,是否可同时是synchronized?
都不能
第二十二,接口是否可继承接口? 抽象类是否可实现(implements)接口? 抽象类是否可继承实体类(concrete class)?
接口可以继承接口。抽象类可以实现(implements)接口,抽象类是否可继承实体类,但前提是实体类必须有明确的构造函数。
第二十三,启动一个线程是用run()还是start()?
启动一个线程是调用start()方法,使线程所代表的虚拟处理机处于可运行状态,这意味着它可以由JVM调度并执行。这并不意味着线程就会立即运行。run()方法可以产生必须退出的标志来停止一个线程。
第二十四,构造器Constructor是否可被override?
构造器Constructor不能被继承,因此不能重写Overriding,但可以被重载Overloading。
第二十五,是否可以继承String类?
String类是final类故不可以继承。
第二十六,当一个线程进入一个对象的一个synchronized方法后,其它线程是否可进入此对象的其它方法?
不能,一个对象的一个synchronized方法只能由一个线程访问。
第二十七,try {}里有一个return语句,那么紧跟在这个try后的finally {}里的code会不会被执行,什么时候被执行,在return前还是后?
会执行,在return前执行。
第二十八,编程题: 用最有效率的方法算出2乘以8等於几?
有C背景的程序员特别喜欢问这种问题。
2 << 3
第二十九,两个对象值相同(x.equals(y) == true),但却可有不同的hash code,这句话对不对?
不对,有相同的hash code。
第三十,当一个对象被当作参数传递到一个方法后,此方法可改变这个对象的属性,并可返回变化后的结果,那么这里到底是值传递还是引用传递?
是值传递。Java 编程语言只由值传递参数。当一个对象实例作为一个参数被传递到方法中时,参数的值就是对该对象的引用。对象的内容可以在被调用的方法中改变,但对象的引用是永远不会改变的。
第三十一,swtich是否能作用在byte上,是否能作用在long上,是否能作用在String上?
switch(expr1)中,expr1是一个整数表达式。因此传递给 switch 和 case 语句的参数应该是 int、 short、 char 或者 byte。long,string 都不能作用于swtich。
第三十二,编程题: 写一个Singleton出来。
Singleton模式主要作用是保证在Java应用程序中,一个类Class只有一个实例存在。
一般Singleton模式通常有几种种形式:
第一种形式: 定义一个类,它的构造函数为private的,它有一个static的private的该类变量,在类初始化时实例话,通过一个public的getInstance方法获取对它的引用,继而调用其中的方法。
public class Singleton {
private Singleton(){}
//在自己内部定义自己一个实例,是不是很奇怪?
//注意这是private 只供内部调用
private static Singleton instance = new Singleton();
//这里提供了一个供外部访问本class的静态方法,可以直接访问
public static Singleton getInstance() {
return instance;
}
}
第二种形式:
public class Singleton {
private static Singleton instance = null;
public static synchronized Singleton getInstance() {
//这个方法比上面有所改进,不用每次都进行生成对象,只是第一次
//使用时生成实例,提高了效率!
if (instance==null)
instance=new Singleton();
return instance; }
}
其他形式:
定义一个类,它的构造函数为private的,所有方法为static的。
一般认为第一种形式要更加安全些
第三十三 Hashtable和HashMap
Hashtable继承自Dictionary类,而HashMap是Java1.2引进的Map interface的一个实现
HashMap允许将null作为一个entry的key或者value,而Hashtable不允许
还有就是,HashMap把Hashtable的contains方法去掉了,改成containsvalue和containsKey。因为contains方法容易让人引起误解。
最大的不同是,Hashtable的方法是Synchronize的,而HashMap不是,在
多个线程访问Hashtable时,不需要自己为它的方法实现同步,而HashMap
就必须为之提供外同步。
Hashtable和HashMap采用的hash/rehash算法都大概一样,所以性能不会有很大的差异。
Javascript是一种由
Netscape的LiveScript发展而来的脚本语言,主要目的是为了解决服务器终端语言,比如Perl,遗留的速度问题。当时服务端需要对数据进行验证,由于网络速度相当缓慢,只有28.8kbps,验证步骤浪费的时间太多。于是Netscape的浏览器Navigator加入了Javascript,提供了数据验证的基本功能。
历史
在1992年,Nombas开始开发一种嵌入式脚本语言,叫做C-minus-minus(Cmm)。[待续...
能够具有交互性,能够包含更多活跃的元素,就有必要在网页中嵌入其它的技术。如:Javascript、VBScript、Document Object Model(文件目标模块)、Layers和 Cascading Style Sheets(
CSS),这里主要讲Javascript。那么Javascript是什么东东?Javascript就是适应动态网页制作的需要而诞生的一种新的编程语言,如今越来越广泛地使用于Internet网页制作上。 Javascript是由 Netscape公司开发的一种脚本语言(scripting language),或者称为描述语言。在HTML基础上,使用Javascript可以开发交互式Web网页。Javascript的出现使得网页和用户之间实现了一种实时性的、动态的、交互性的关系,使网页包含更多活跃的元素和更加精彩的内容。 运行用Javascript编写的程序需要能支持Javascript语言的浏览器。Netscape公司 Navigator 3.0以上版本的浏览器都能支持 Javascript程序,
微软公司 Internet Explorer 3.0以上版本的浏览器基本上支持Javascript。微软公司还有自己开发的Javascript,称为JScript。 Javascript和Jscript基本上是相同的,只是在一些细节上有出入。 Javascript短小精悍, 又是在客户机上执行的,大大提高了网页的浏览速度和交互能力。 同时它又是专门为制作Web网页而量身定做的一种简单的编程语言。
虽然,在
Dreamweaver的Behaviors可以为我们方便地使用Javascript程序而不用编写代码,但我们自己了解了Javascript的编程方法后,将能更加方便灵活地应用,也使Javascript的代码更简练。本专题通过对一系列典型程序的剖析,使你快速地掌握Javascript的编程技巧,设计出质量上乘的动态网页打下坚实的基础。在此之前,我们先了解一些Javascript 的基本概念。
JavaScript 有什么特点
JavaScript 使网页增加互动性。JavaScript 使有规律地重复的HTML文段简化,减少下载时间。JavaScript 能及时响应用户的操作,对提交表单做即时的检查,无需浪费时间交由 CGI 验证。JavaScript 的特点是无穷无尽的,只要你有创意。
Java 与 JavaScript 有什么不同
很多人看到 Java 和 JavaScript 都有“Java”四个字,就以为它们是同一样东西,连我自己当初也是这样。其实它们是完完全全不同的两种东西。Java,全称应该是 Java Applet,是嵌在网页中,而又有自己独立的运行窗口的小程序。Java Applet 是预先编译好的,一个 Applet 文件(.class)用 Notepad 打开阅读,根本不能理解。Java Applet 的功能很强大,可以访问 http、ftp等协议,甚至可以在电脑上种病毒(已有先例了)。相比之下,JavaScript 的能力就比较小了。JavaScript 是一种“脚本”(“Script”),它直接把代码写到 HTML 文档中,浏览器读取它们的时候才进行编译、执行,所以能查看 HTML 源文件就能查看JavaScript 源代码。JavaScript 没有独立的运行窗口,浏览器当前窗口就是它的运行窗口。它们的相同点,我想只有同是以 Java 作编程语言一点了。
开发 JavaScript 该用什么软件
一个 JavaScript 程序其实是一个文档,一个文本文件。它是嵌入到 HTML 文档中的。所以,任何可以编写 HTML 文档的软件都可以用来开发 JavaScript。在此我推荐大家用 FrontPage 2000 附带的 Microsoft 脚本编辑器(在 FrontPage 菜单 | 工具 | 宏 | Microsoft 脚本编辑器)。它是个像 Visual Basic / C++ 一样的程序开发器,能对正在输入的语句作出简要提示。配合 FrontPage 2000,使工作量大大减少。
一、Javascript在网页的用法
Javascript加入网页有两种方法:
1、直接加入HTML文档
这是最常用的方法,大部分含有Javascript的网页都采用这种方法,如:
<script language="Javascript">
<!--
document.writeln("这是Javascript!采用直接插入的方法!");
//-Javascript结束-->
</script>
在这个例子中,我们可看到一个新的标签: <script>……</script>,而<script language="Javascript”> 用来告诉浏览器这是用Javascript编写的程序,需要调动相应的解释程序进行解释。
HTML的注释标签<!--和-->:用来去掉浏览器所不能识别的Javascript源代码的,这对不支持 Javascript 语言的浏览器来说是很有用的。
//-Javascript结束:双斜杠表示 Javascript的注释部分,即从//开始到行尾的字符都被忽略。 至于程序中所用到的document.write()函数则表示将括号中的文字输出到窗口中去, 这在后面将会详细介绍。 另外一点需要注意的是,<script>……</script>的位置并不是固定的,可以包含在<head>......</head> 或<body>.....</body>中的任何地方。
2、引用方式 如果已经存在一个Javascript源文件(以js为扩展名),则可以采用这种引用的方式,以提高程序代码的利用率。其基本格式如下:
<script src=url language="Javascript"></script>
其中的Url就是程序文件的地址。同样的,这样的语句可以放在HTML文档头部或主体的任何部分。 如果要实现“直接插入方式”中所举例子的效果,可以首先创建一个Javascript源代码文件“Script.js”,其内容如下:
document.writeln("这是Javascript!采用直接插入的方法!");
在网页中可以这样调用程序:<script src="Script.js" language="Javascript"></script> 。
二、Javascript基本概念
在这里只作简单介绍,在以后的例子中结程序再作具体解释其作用。
1、运算符
运算符就是完成操和的一系列符号,它有七类:
赋值运算符、算术运算符、比较运算符、逻辑运算符、条件运算、位操作运算符和字符串运算符。
2、表达式
运算符和操作数的组合称为表达式,通常分为四类:赋值表达式、算术表达式、布尔表达式和字符串表达式。
3、语句
Javascript程序是由若干语句组成的,语句是编写程序的指令。Javascript提供了完整的基本编程语句,它们是:
赋值语句、switch选择语句、while循环语句、for循环语句、do while循环语句、break循环中止语句和continue循环中断语句。
4、函数
函数是命名的语句段,这个语句段可以被当作一个整体来引用不着和执行。使用函数要注意以下几点:
1)函数由关键字function定义;
2)函数必须先定义后使用,否则将出错;
3)函数名是调用函数时引用的名称,它对大小写是敏感的,调用函数时不可写错函数名;
4)参数表示传递给函数使用或操作的值,它可以是常量,也可以是变量;
5)return语句用于返回表达式的值,也可以没有。
5、对象
Javascript的一个重要功能就是基于对象的功能,通过基于对象的程序设计,可以用更直观、模块化和可重复使用的方式进行程序开发。
一组包含数据的属性和对属性中包含数据进行操作的方法,称为对象。比如要设定网页的背景颜色,所针对的对象就是document,所用的属性名是bgcolor,如document.bgcolor="blue",就是表示使背景的颜色为蓝色。
6、事件
用户与网页交互时产生的操作,称为事件。绝大部分事都由用户的动作所引发,如:用户按鼠标的按钮,就产生onclick事件,若鼠标的指针的链接上移动,就产生onmouseover事件等等。在Javascript中,事件往往与事件处理程序配套使用。
学习Javascript比较快速有效的方法是先熟悉一些基本概念,然后找几个别人设计好的程序认真仔细地分析一遍,再稍作改动,再看看能否达到预期目的,不断地举一反三,既可以加深对一些参数、设计方法的理解,又可以快速地提高自己的水平。另外,再提醒一下:Javascript对大小写是敏感的,特别是一些对象、方法、属性的大小写一定要一致,要养成一种良好的习惯,否则在调试程序时可要累死你了。
7、
变量如 var myVariable = "some value";
很明显先前的这个仁兄只是对JAVASCRIPT很厉害,他所说的JAVA其实是错误的
Java是由Sun Microsystems公司于1995年5月推出的Java程序设计语言和Java平台的总称。用Java实现的HotJava浏览器(支持Java applet)显示了Java的魅力:跨平台、动感的Web、Internet计算。从此,Java被广泛接受并推动了Web的迅速发展,常用的浏览器现在均支持Java applet。另一方面,Java技术也不断更新。
Java平台由Java虚拟机(Java Virtual Machine)和Java 应用编程接口(Application Programming Interface、简称API)构成。Java 应用编程接口为Java应用提供了一个独立于操作系统的标准接口,可分为基本部分和扩展部分。在硬件或操作系统平台上安装一个Java平台之后,Java应用程序就可运行。现在Java平台已经嵌入了几乎所有的操作系统。这样Java程序可以只编译一次,就可以在各种系统中运行。
Java分为三个体系JavaSE,JavaEE,JavaME。
SQL全称是“结构化查询语言(Structured Query Language)”,最早的是
IBM的圣约瑟研究实验室为其关系数据库管理系统SYSTEM R开发的一种查询语言,它的前身是SQUARE语言。SQL语言结构简洁,功能强大,简单易学,所以自从IBM公司1981年推出以来,SQL语言,得到了广泛的应用。如今无论是像
Oracle ,
Sybase,Informix,SQL server这些大型的数据库管理系统,还是像Visual Foxporo,PowerBuilder这些微机上常用的数据库开发系统,都支持SQL语言作为查询语言。
SQL是高级的非过程化编程语言,允许用户在高层数据结构上工作。他不要求用户指定对数据的存放方法,也不需要用户了解具体的数据存放方式,所以具有完全不同底层结构的不同数据库系统可以使用相同的SQL语言作为数据输入与管理的接口。它以记录集合作为操纵对象,所有SQL语句接受集合作为输入,返回集合作为输出,这种集合特性允许一条SQL语句的输出作为另一条SQL语句的输入,所以SQL语言可以嵌套,这使他具有极大的灵活性和强大的功能,在多数情况下,在其他语言中需要一大段程序实现的一个单独事件只需要一个SQL语句就可以达到目的,这也意味着用SQL语言可以写出非常复杂的语句。
SQL同时也是数据库文件格式的扩展名。
SQL语言包含4个部分:
数据查询语言(SELECT语句)
数据操纵语言(INSERT, UPDATE, DELETE语句)
数据定义语言(如CREATE, DROP等语句)
数据控制语言(如COMMIT, ROLLBACK等语句)
取自"
http://zh.wikipedia.org/wiki/SQL"
SQL(STructured Query Language)是一种资料库查询和程式设计语言,用於存取资料以及查询、更新和管理关联式资料库系统。美国国家标准局(ANSI)与国际标准化组织(ISO)已经制定了 SQL 标准。ANSI 是一个美国工业和商业集团组织,发展美国的商务和通讯标准。ANSI 同时也是 ISO 和 International Electrotechnical Commission(IEC)的成员之一。ANSI 发布与国际标准组织相应的美国标准。1992年,ISO 和 IEC 发布了 SQL 的国际标准,称为 SQL-92。ANSI 随之发布的相应标准是 ANSI SQL-92。ANSI SQL-92 有时被称为 ANSI SQL。尽管不同的关联式资料库使用的 SQL 版本有一些差异,但大多数都遵循 ANSI SQL 标准。SQL Server 使用 ANSI SQL-92 的扩展集,称为 T-SQL,其遵循 ANSI 制定的 SQL-92 标准。
SQL 语言包括两种主要程式设计语言类别的陈述式: 资料定义语言 (DDL)与资料操作语言 (DML)。下面我们将介绍这两类语言。
DDL
DDL 用於定义和管理物件,例如资料库、资料表以及检视表( 第18章 将会解释何谓检视表)。DDL 陈述式通常包括每个物件的CREATE、ALTER 以及 DROP 命令。举例来说,CREATE TABLE、ALTER TABLE 以及 DROP TABLE 这些陈述式便可以用来建立新资料表、修改其属性(如新增或删除资料行)、删除资料表等,下面我们会一一介绍。
CREATE TABLE 陈述式
使用 DDL 在 MyDB 资料库建立一个名为 Customer_Data 的范例资料表,本章后面的例子我们会使用到这个资料表。如前所述,CREATE TABLE 陈述式可以用来建立资料表。这个范例资料表被定义成四个资料行,如下所示:
Use MyDB
CREATE TABLE Customer_Data
(customer_id smallint,
first_name char(20),
last_name char(20),
phone char(10))
GO
这个陈述式能产生 Customer_Data 资料表,这个资料表会一直是空的直到资料被填入资料表内。
ALTER TABLE 陈述式
ALTER TABLE 陈述式用来变更资料表的定义与属性。在下面的例子中,我们利用 ALTER TABLE 在已经存在的 Customer_Data 资料表中新增 middle_initial 资料行。
ALTER TABLE Customer_Data
ADD middle_initial char(1)
GO
现在资料表的定义包括了五个资料行,而不是之前的四个资料行。关於使用ALTER TABLE 的更多细节,请参阅 第15章 。
DROP TABLE 陈述式
DROP TABLE 陈述式用来删除资料表定义以及所有的资料、索引、触发程序、条件约束以及资料表的权限。要删除我们的 Customer_Data 资料表,可利用下列命令:
DROP TABLE Customer_Data
GO
关於 DROP TABLE 陈述式的详细内容,请参阅 第15章 。
DML
DML 利用 INSERT、SELECT、UPDATE 及 DELETE 等陈述式来操作资料库物件所包含的资料。
INSERT 陈述式
INSERT 陈述式用来在资料表或检视表中插入一列资料。例如,如果要在Customer_Data 资料表中新增一个客户,可使用类似以下的 INSERT 陈述式:
INSERT INTO Customer_Data
(customer_id, first_name, last_name, phone)
VALUES (777, "Frankie", "Stein", "4895873900")
请注意 SQL 陈述式中第二行的资料行名称清单,清单上资料行名称的次序决定了资料数值将被放在哪个资料行。举例来说,第一个资料数值将被放在清单列出的第一个资料行 customer_id、第二个资料数值放在第二个资料行,依此类推。由于我们在建立资料表时,定义资料资料行填入数值的次序与现在相同,因此我们不必特意指定栏位名称。我们可以用以下的 INSERT 陈述式代替:
INSERT INTO Customer_Data
VALUES (777, "Frankie", "Stein", "4895873900")
注意
如果使用这种形式的 INSERT 陈述式,但被插入的数值次序上与建立资料表时不同,数值将被放入错误的资料行。如果资料的型别与定义不符,则会收到一个错误讯息。
--------------------------------------------------------------------------------
SELECT 陈述式
SELECT 陈述式用来检索资料表中的资料,而哪些资料被检索由列出的资料行与陈述式中的 WHERE 子句决定。例如,要从之前建立的 Customer_Data 资料表中检索 customer_id 以及 first_name 资料行的资料,并且只想取出每列中 first_name 资料行值为 Frankie 的资料,那麼可以利用以下的 SELECT 陈述式:
SELECT customer_id, first_name FROM Customer_Data
WHERE first_name = "Frankie"
如果有一列符合 SELECT 陈述式中的标准,则结果将显示如下:
customer_id first_name
------------- ------------
777 Frankie
UPDATE 陈述式
UPDATE 陈述式用来更新或改变一列或多列中的值。例如,一位名称为 Frankie Stein 的客户想要在记录中改变他的姓氏为 Franklin,可使用以下 UPDATE 陈述式:
UPDATE Customer_Data
SET first_name = "Franklin"
WHERE last_name = "Stein" and customer_id= 777
我们在 WHERE 子句中加入 customer_id 的项目来确定其他名称为 Stein 的客户不会被影响-只有customer_id为777的客户,姓氏会有所改变。
--------------------------------------------------------------------------------
说明
当您使用 UPDATE 陈述式时,要确定在 WHERE 子句提供充分的筛选条件,如此才不会不经意地改变了一些不该改变的资料。
--------------------------------------------------------------------------------
DELETE 陈述式
DELETE 陈述式用来删除资料表中一列或多列的资料,您也可以删除资料表中的所有资料列。要从 Customer_Data 资料表中删除所有的列,您可以利用下列陈述式:
DELETE FROM Customer_Data
或
DELETE Customer_Data
资料表名称前的 FROM 关键字在 DELETE 陈述式中是选择性的。除此之外,这两个陈述式完全相同。
要从 Customer_Data 资料表中删除 customer_id 资料行的值小於100的列,可利用下列陈述式:
DELETE FROM Customer_Data
WHERE customer_id < 100
现在我们已经快速浏览了 SQL 提供的 DDL 与 DML 陈述式,接著,下面将介绍 T-SQL。
SQL中的五种数据类型
简要描述一下SQL中的五种数据类型:字符型,文本型,数值型,逻辑型和日期型
字符型
VARCHAR VS CHAR
VARCHAR型和CHAR型数据的这个差别是细微的,但是非常重要。他们都是用来储存字符串长度小于255的字符。
假如你向一个长度为四十个字符的VARCHAR型字段中输入数据BIll GAtES。当你以后从这个字段中取出此数据时,你取出的数据其长度为十个字符——字符串Bill Gates的长度。 现在假如你把字符串输入一个长度为四十个字符的CHAR型字段中,那么当你取出数据时,所取出的数据长度将是四十个字符。字符串的后面会被附加多余的空格。
当你建立自己的站点时,你会发现使用VARCHAR型字段要比CHAR型字段方便的多。使用VARCHAR型字段时,你不需要为剪掉你数据中多余的空格而操心。
VARCHAR型字段的另一个突出的好处是它可以比CHAR型字段占用更少的内存和硬盘空间。当你的数据库很大时,这种内存和磁盘空间的节省会变得非常重要
文本型
TEXT
使用文本型数据,你可以存放超过二十亿个字符的字符串。当你需要存储大串的字符时,应该使用文本型数据。
注意文本型数据没有长度,而上一节中所讲的字符型数据是有长度的。一个文本型字段中的数据通常要么为空,要么很大。
当你从HTML fORM的多行文本编辑框(TEXTAREA)中收集数据时,你应该把收集的信息存储于文本型字段中。但是,无论何时,只要你能避免使用文本型字段,你就应该不适用它。文本型字段既大且慢,滥用文本型字段会使服务器速度变慢。文本型字段还会吃掉大量的磁盘空间。
一旦你向文本型字段中输入了任何数据(甚至是空值),就会有2K的空间被自动分配给该数据。除非删除该记录,否则你无法收回这部分存储空间。
数值型
SQL支持许多种不同的数值型数据。你可以存储整数 INT 、小数 NUMERIC、和钱数 MONEY。
INT VS SMALLINT VS TINYINT
他们的区别只是字符长度:
INT型数据的表数范围是从-2,147,483,647到2,147,483,647的整数
SMALLINT 型数据可以存储从-32768到32768的整数
TINYINT 型的字段只能存储从0到255的整数,不能用来储存负数
通常,为了节省空间,应该尽可能的使用最小的整型数据。一个TINYINT型数据只占用一个字节;一个INT型数据占用四个字节。这看起来似乎差别不大,但是在比较大的表中,字节数的增长是很快的。另一方面,一旦你已经创建了一个字段,要修改它是很困难的。因此,为安全起见,你应该预测以下,一个字段所需要存储的数值最大有可能是多大,然后选择适当的数据类型。
NUMERIC
为了能对字段所存放的数据有更多的控制,你可以使用NUMERIC型数据来同时表示一个数的整数部分和小数部分。NUMERIC型数据使你能表示非常大的数——比INT型数据要大得多。一个NUMERIC型字段可以存储从-1038到1038范围内的数。NUMERIC型数据还使你能表示有小数部分的数。例如,你可以在NUMERIC型字段中存储小数3.14。
当定义一个NUMERIC型字段时,你需要同时指定整数部分的大小和小数部分的大小。如:MUNERIC(23,0)
一个 NUMERIC型数据的整数部分最大只能有28位,小数部分的位数必须小于或等于整数部分的位数,小数部分可以是零。
MONEY VS SMALLMONEY
你可以使用 INT型或NUMERIC型数据来存储钱数。但是,专门有另外两种数据类型用于此目的。如果你希望你的网点能挣很多钱,你可以使用MONEY型数据。如果你的野心不大,你可以使用SMALLMONEY型数据。MONEY型数据可以存储从-922,337,203,685,477.5808到922,337,203,685,477.5807的钱数。如果你需要存储比这还大的金额,你可以使用NUMERIC型数据。
SMALLMONEY型数据只能存储从-214,748.3648到214,748.3647 的钱数。同样,如果可以的话,你应该用SMALLMONEY型来代替MONEY型数据,以节省空间。
逻辑型
BIT
如果你使用复选框( CHECKBOX)从网页中搜集信息,你可以把此信息存储在BIT型字段中。BIT型字段只能取两个值:0或1。
当心,在你创建好一个表之后,你不能向表中添加 BIT型字段。如果你打算在一个表中包含BIT型字段,你必须在创建表时完成。
日期型
DATETIME VS SMALLDATETIME
一个 DATETIME型的字段可以存储的日期范围是从1753年1月1日第一毫秒到9999年12月31日最后一毫秒。
如果你不需要覆盖这么大范围的日期和时间,你可以使用SMALLDATETIME型数据。它与DATETIME型数据同样使用,只不过它能表示的日期和时间范围比DATETIME型数据小,而且不如DATETIME型数据精确。一个SMALLDATETIME型的字段能够存储从1900年1月1日到2079年6月6日的日期,它只能精确到秒。
DATETIME型字段在你输入日期和时间之前并不包含实际的数据,认识这一点是重要的。
SQL全称是“结构化查询语言(Structured Query Language)”,最早的是
IBM的圣约瑟研究实验室为其关系数据库管理系统SYSTEM R开发的一种查询语言,它的前身是SQUARE语言。SQL语言结构简洁,功能强大,简单易学,所以自从IBM公司1981年推出以来,SQL语言,得到了广泛的应用。如今无论是像
Oracle ,
Sybase,Informix,SQL server这些大型的数据库管理系统,还是像Visual Foxporo,PowerBuilder这些微机上常用的数据库开发系统,都支持SQL语言作为查询语言。
SQL是高级的非过程化编程语言,允许用户在高层数据结构上工作。他不要求用户指定对数据的存放方法,也不需要用户了解具体的数据存放方式,所以具有完全不同底层结构的不同数据库系统可以使用相同的SQL语言作为数据输入与管理的接口。它以记录集合作为操纵对象,所有SQL语句接受集合作为输入,返回集合作为输出,这种集合特性允许一条SQL语句的输出作为另一条SQL语句的输入,所以SQL语言可以嵌套,这使他具有极大的灵活性和强大的功能,在多数情况下,在其他语言中需要一大段程序实现的一个单独事件只需要一个SQL语句就可以达到目的,这也意味着用SQL语言可以写出非常复杂的语句。
SQL同时也是数据库文件格式的扩展名。
SQL语言包含4个部分:
数据查询语言(SELECT语句)
数据操纵语言(INSERT, UPDATE, DELETE语句)
数据定义语言(如CREATE, DROP等语句)
数据控制语言(如COMMIT, ROLLBACK等语句)
取自"
http://zh.wikipedia.org/wiki/SQL"
SQL(STructured Query Language)是一种资料库查询和程式设计语言,用於存取资料以及查询、更新和管理关联式资料库系统。美国国家标准局(ANSI)与国际标准化组织(ISO)已经制定了 SQL 标准。ANSI 是一个美国工业和商业集团组织,发展美国的商务和通讯标准。ANSI 同时也是 ISO 和 International Electrotechnical Commission(IEC)的成员之一。ANSI 发布与国际标准组织相应的美国标准。1992年,ISO 和 IEC 发布了 SQL 的国际标准,称为 SQL-92。ANSI 随之发布的相应标准是 ANSI SQL-92。ANSI SQL-92 有时被称为 ANSI SQL。尽管不同的关联式资料库使用的 SQL 版本有一些差异,但大多数都遵循 ANSI SQL 标准。SQL Server 使用 ANSI SQL-92 的扩展集,称为 T-SQL,其遵循 ANSI 制定的 SQL-92 标准。
SQL 语言包括两种主要程式设计语言类别的陈述式: 资料定义语言 (DDL)与资料操作语言 (DML)。下面我们将介绍这两类语言。
DDL
DDL 用於定义和管理物件,例如资料库、资料表以及检视表( 第18章 将会解释何谓检视表)。DDL 陈述式通常包括每个物件的CREATE、ALTER 以及 DROP 命令。举例来说,CREATE TABLE、ALTER TABLE 以及 DROP TABLE 这些陈述式便可以用来建立新资料表、修改其属性(如新增或删除资料行)、删除资料表等,下面我们会一一介绍。
CREATE TABLE 陈述式
使用 DDL 在 MyDB 资料库建立一个名为 Customer_Data 的范例资料表,本章后面的例子我们会使用到这个资料表。如前所述,CREATE TABLE 陈述式可以用来建立资料表。这个范例资料表被定义成四个资料行,如下所示:
Use MyDB
CREATE TABLE Customer_Data
(customer_id smallint,
first_name char(20),
last_name char(20),
phone char(10))
GO
这个陈述式能产生 Customer_Data 资料表,这个资料表会一直是空的直到资料被填入资料表内。
ALTER TABLE 陈述式
ALTER TABLE 陈述式用来变更资料表的定义与属性。在下面的例子中,我们利用 ALTER TABLE 在已经存在的 Customer_Data 资料表中新增 middle_initial 资料行。
ALTER TABLE Customer_Data
ADD middle_initial char(1)
GO
现在资料表的定义包括了五个资料行,而不是之前的四个资料行。关於使用ALTER TABLE 的更多细节,请参阅 第15章 。
DROP TABLE 陈述式
DROP TABLE 陈述式用来删除资料表定义以及所有的资料、索引、触发程序、条件约束以及资料表的权限。要删除我们的 Customer_Data 资料表,可利用下列命令:
DROP TABLE Customer_Data
GO
关於 DROP TABLE 陈述式的详细内容,请参阅 第15章 。
DML
DML 利用 INSERT、SELECT、UPDATE 及 DELETE 等陈述式来操作资料库物件所包含的资料。
INSERT 陈述式
INSERT 陈述式用来在资料表或检视表中插入一列资料。例如,如果要在Customer_Data 资料表中新增一个客户,可使用类似以下的 INSERT 陈述式:
INSERT INTO Customer_Data
(customer_id, first_name, last_name, phone)
VALUES (777, "Frankie", "Stein", "4895873900")
请注意 SQL 陈述式中第二行的资料行名称清单,清单上资料行名称的次序决定了资料数值将被放在哪个资料行。举例来说,第一个资料数值将被放在清单列出的第一个资料行 customer_id、第二个资料数值放在第二个资料行,依此类推。由于我们在建立资料表时,定义资料资料行填入数值的次序与现在相同,因此我们不必特意指定栏位名称。我们可以用以下的 INSERT 陈述式代替:
INSERT INTO Customer_Data
VALUES (777, "Frankie", "Stein", "4895873900")
注意
如果使用这种形式的 INSERT 陈述式,但被插入的数值次序上与建立资料表时不同,数值将被放入错误的资料行。如果资料的型别与定义不符,则会收到一个错误讯息。
--------------------------------------------------------------------------------
SELECT 陈述式
SELECT 陈述式用来检索资料表中的资料,而哪些资料被检索由列出的资料行与陈述式中的 WHERE 子句决定。例如,要从之前建立的 Customer_Data 资料表中检索 customer_id 以及 first_name 资料行的资料,并且只想取出每列中 first_name 资料行值为 Frankie 的资料,那麼可以利用以下的 SELECT 陈述式:
SELECT customer_id, first_name FROM Customer_Data
WHERE first_name = "Frankie"
如果有一列符合 SELECT 陈述式中的标准,则结果将显示如下:
customer_id first_name
------------- ------------
777 Frankie
UPDATE 陈述式
UPDATE 陈述式用来更新或改变一列或多列中的值。例如,一位名称为 Frankie Stein 的客户想要在记录中改变他的姓氏为 Franklin,可使用以下 UPDATE 陈述式:
UPDATE Customer_Data
SET first_name = "Franklin"
WHERE last_name = "Stein" and customer_id= 777
我们在 WHERE 子句中加入 customer_id 的项目来确定其他名称为 Stein 的客户不会被影响-只有customer_id为777的客户,姓氏会有所改变。
--------------------------------------------------------------------------------
说明
当您使用 UPDATE 陈述式时,要确定在 WHERE 子句提供充分的筛选条件,如此才不会不经意地改变了一些不该改变的资料。
--------------------------------------------------------------------------------
DELETE 陈述式
DELETE 陈述式用来删除资料表中一列或多列的资料,您也可以删除资料表中的所有资料列。要从 Customer_Data 资料表中删除所有的列,您可以利用下列陈述式:
DELETE FROM Customer_Data
或
DELETE Customer_Data
资料表名称前的 FROM 关键字在 DELETE 陈述式中是选择性的。除此之外,这两个陈述式完全相同。
要从 Customer_Data 资料表中删除 customer_id 资料行的值小於100的列,可利用下列陈述式:
DELETE FROM Customer_Data
WHERE customer_id < 100
现在我们已经快速浏览了 SQL 提供的 DDL 与 DML 陈述式,接著,下面将介绍 T-SQL。
SQL中的五种数据类型
简要描述一下SQL中的五种数据类型:字符型,文本型,数值型,逻辑型和日期型
字符型
VARCHAR VS CHAR
VARCHAR型和CHAR型数据的这个差别是细微的,但是非常重要。他们都是用来储存字符串长度小于255的字符。
假如你向一个长度为四十个字符的VARCHAR型字段中输入数据BIll GAtES。当你以后从这个字段中取出此数据时,你取出的数据其长度为十个字符——字符串Bill Gates的长度。 现在假如你把字符串输入一个长度为四十个字符的CHAR型字段中,那么当你取出数据时,所取出的数据长度将是四十个字符。字符串的后面会被附加多余的空格。
当你建立自己的站点时,你会发现使用VARCHAR型字段要比CHAR型字段方便的多。使用VARCHAR型字段时,你不需要为剪掉你数据中多余的空格而操心。
VARCHAR型字段的另一个突出的好处是它可以比CHAR型字段占用更少的内存和硬盘空间。当你的数据库很大时,这种内存和磁盘空间的节省会变得非常重要
文本型
TEXT
使用文本型数据,你可以存放超过二十亿个字符的字符串。当你需要存储大串的字符时,应该使用文本型数据。
注意文本型数据没有长度,而上一节中所讲的字符型数据是有长度的。一个文本型字段中的数据通常要么为空,要么很大。
当你从HTML fORM的多行文本编辑框(TEXTAREA)中收集数据时,你应该把收集的信息存储于文本型字段中。但是,无论何时,只要你能避免使用文本型字段,你就应该不适用它。文本型字段既大且慢,滥用文本型字段会使服务器速度变慢。文本型字段还会吃掉大量的磁盘空间。
一旦你向文本型字段中输入了任何数据(甚至是空值),就会有2K的空间被自动分配给该数据。除非删除该记录,否则你无法收回这部分存储空间。
数值型
SQL支持许多种不同的数值型数据。你可以存储整数 INT 、小数 NUMERIC、和钱数 MONEY。
INT VS SMALLINT VS TINYINT
他们的区别只是字符长度:
INT型数据的表数范围是从-2,147,483,647到2,147,483,647的整数
SMALLINT 型数据可以存储从-32768到32768的整数
TINYINT 型的字段只能存储从0到255的整数,不能用来储存负数
通常,为了节省空间,应该尽可能的使用最小的整型数据。一个TINYINT型数据只占用一个字节;一个INT型数据占用四个字节。这看起来似乎差别不大,但是在比较大的表中,字节数的增长是很快的。另一方面,一旦你已经创建了一个字段,要修改它是很困难的。因此,为安全起见,你应该预测以下,一个字段所需要存储的数值最大有可能是多大,然后选择适当的数据类型。
NUMERIC
为了能对字段所存放的数据有更多的控制,你可以使用NUMERIC型数据来同时表示一个数的整数部分和小数部分。NUMERIC型数据使你能表示非常大的数——比INT型数据要大得多。一个NUMERIC型字段可以存储从-1038到1038范围内的数。NUMERIC型数据还使你能表示有小数部分的数。例如,你可以在NUMERIC型字段中存储小数3.14。
当定义一个NUMERIC型字段时,你需要同时指定整数部分的大小和小数部分的大小。如:MUNERIC(23,0)
一个 NUMERIC型数据的整数部分最大只能有28位,小数部分的位数必须小于或等于整数部分的位数,小数部分可以是零。
MONEY VS SMALLMONEY
你可以使用 INT型或NUMERIC型数据来存储钱数。但是,专门有另外两种数据类型用于此目的。如果你希望你的网点能挣很多钱,你可以使用MONEY型数据。如果你的野心不大,你可以使用SMALLMONEY型数据。MONEY型数据可以存储从-922,337,203,685,477.5808到922,337,203,685,477.5807的钱数。如果你需要存储比这还大的金额,你可以使用NUMERIC型数据。
SMALLMONEY型数据只能存储从-214,748.3648到214,748.3647 的钱数。同样,如果可以的话,你应该用SMALLMONEY型来代替MONEY型数据,以节省空间。
逻辑型
BIT
如果你使用复选框( CHECKBOX)从网页中搜集信息,你可以把此信息存储在BIT型字段中。BIT型字段只能取两个值:0或1。
当心,在你创建好一个表之后,你不能向表中添加 BIT型字段。如果你打算在一个表中包含BIT型字段,你必须在创建表时完成。
日期型
DATETIME VS SMALLDATETIME
一个 DATETIME型的字段可以存储的日期范围是从1753年1月1日第一毫秒到9999年12月31日最后一毫秒。
如果你不需要覆盖这么大范围的日期和时间,你可以使用SMALLDATETIME型数据。它与DATETIME型数据同样使用,只不过它能表示的日期和时间范围比DATETIME型数据小,而且不如DATETIME型数据精确。一个SMALLDATETIME型的字段能够存储从1900年1月1日到2079年6月6日的日期,它只能精确到秒。
DATETIME型字段在你输入日期和时间之前并不包含实际的数据,认识这一点是重要的。
刚开始用SQL Server的时候,我没有用显示执行计划来对查询进行分析。我曾经一直认为我递交的SQL查询都是最优的,而忽略了查询性能究竟如何,从而对“执行计划”重视不够。在我职业初期,我只要能获取数据就很开心,而不去考虑数据是如何返回的,“执行计划”对我的查询作了什么工作。我以为SQL Server会自己去处理查询的性能问题的。作为一个刚进入IT行业或者刚学到新技术的软件工程师,在编写代码前不太可能有时间去学习其实必须掌握的知识。也许这是因为IT行业竞争太激烈的缘故。
随着时间的流逝,数据库容量慢慢变大了。终于某天,客户对应用系统的查询性能感到不满意了。他面带怒容来找我,抱怨由于查询太慢,使得他需要花更多的时间来处理公务。最初,我建议客户升级其系统资源,例如作为临时解决方案,增加硬盘容量。虽然硬盘价格现在很便宜了,但是客户还是要求我提供一个永久性的解决方案,检查和好好调试查询语句,来替代那种无休止地升级资源的临时方案。因为客户的满意度对IT行业来说是十分重要的,因此我不得不考虑他的个人建议。我答应他一定会检查和调整我的代码。
在刚进入IT行业时,我知道SQL Server的基础只是。说实话,向客户承诺检查系统的时候,我还没有一点入手的头绪。不过我相信我可以通过GOOGL和BOL来获取相应的信息。
我阅读了一些关于SQL Server的书籍,BOL,以及在网上搜索的信息。于是我知道了“显示执行计划”的概念。可以在查询管理器中将该选项的开关设置为ON。“显示执行计划”是一个图形化工具,可以帮助开发者和DBA分析,优化查询,从而改善性能。
“显示执行计划”中不同的任务具有不同的图标。本文中我主要对“Table Scan”、“Index Scan”、“Index Seek”、“Cluster Index Scan”以及“Clustered Index Seek”感兴趣。也许在以后,可以对别的任务进行另外介绍。
时间以F1方程式的速度开始流逝,我觉得该是我全面理解“Table Scan”、“Index Scan”、“Index Seek”、“Clustered Index Scan”、和“Clustered Index Seek”如何工作的时候了。
我准备开始分析并优化我的查询。在分析之前,我想到了一些问题。
-
MS-SQL Server什么时候使用"Table Scan"?
-
MS-SQL Server什么时候使用"Index Scan"?
-
MS-SQL Server什么时候使用"Index Seek"?
-
MS-SQL Server什么时候使用"Clustered Index Scan"?
-
MS-SQL Server什么时候使用"Clustered Index Seek"?
我主要关注SQL Server是根据什么来使用“执行计划”分析查询的。在经过一段时间学习后,我了解了一些相关知识。这些知识应该对开发和DBA新手有帮助。于是我决定写这篇文章,共享我的知识以帮助别人来理解“执行计划”。
如果你喜欢,可以慢慢读完,也可以在SQL Server上,模拟我下面做的实验。
为了解释“显示执行计划”中的“Table Scan”、“Index Scan”、“Index Seek”、“Clustered Index Scan”和“Clustered Index Seek”,先创建新表,并添加一些示例数据进去。下面是创建新表的脚本:
Create Table PerformanceIssue ( PRID UniqueIdentifier NOT NULL, PRCode Int NOT NULL, PRDesc Varchar (100) NOT NULL ) ON [PRIMARY]
|
表创建后需要添加一些数据。使用下面的脚本添加100,000条记录进去。脚本执行时间可能比较长,请耐心等待其执行完毕。
Declare @Loop Int Declare @PRID UniqueIdentifier Declare @ PRDesc Varchar (100)
Set @Loop = 1 Set @ PRDesc = ''
WHILE @Loop <= 100000 BEGIN Set @PRID = NewID() Set @PRDesc = ' PerformanceIssue - ' + Convert( Varchar(10),@Loop ) Insert Into PerformanceIssue Values (@PRID, @Loop, @PRDesc) Set @Loop = @Loop + 1 END
|
脚本成功执行后,数据就添加进去了。
用下面语句来看一下表的内容:
Select PRID, PRCode, PRDesc From PerformanceIssue GO
|
由于记录较长,因此这里就不列出查询结果了。
正如我前面讲到,我想解释何时会有“Table Scan”、“Index Scan”、“Index Seek”、“Clustered Index Scan”和“Clustered Index Seek”。上述哪个会改善性能呢?
当SQL Server返回数据时,我们想知道SQL Server采取何种扫描机制来协助获取数据。首先看一下“Table Scan”。我们想了解什么时候“Table Scan”会产生。
选择“显示执行计划”或者使用热键“Alt + Q”来激活“显示执行计划”,当然也可以用快捷键“Ctrl+K”。
看一下执行下面查询后的“执行计划”结果。
Select PRID, PRCode, PRDesc From PerformanceIssue GO
|
上面的“执行计划”中,SQL Server用到了“Table Scan”。我问自己为什么会有“Table Scan”,SQL Server是根据什么来使用该方法的。难道是因为我想获取所有100,000条记录吗?于是我换了一个角度进行思考,如果来避免查询中出现“Table Scan”呢?此时我对SQL Server的扫描机制还不是很清楚,那么该如何优化查询呢?下面的SELECT查询中仅选择两列:[PRID, PRCode]。
Select PRID, PRCode From PerformanceIssue GO
|
查询执行后,执行计划和第一个查询一样。于是将查询改变为只检索一个字段 [PRID]。
Select PRID From PerformanceIssue
GO
|
查询执行后,执行计划仍然和第一个查询的相同。对“Estimated row size”属性不需要太大关注。意思我立刻决定只获取一条记录,看看执行计划会如何。查询语句如下:
Select PRID, PRCode, PRDesc From PerformanceIssue Where PRID = 'D386C151-5F74-4C2A-B527-86FEF9712955' -- PRID GUID value might be differ in your machine
GO
|
执行完成后,执行计划显示:
查询仍然使用了“Table Scan”方法来显示数据。
那么,我需要想其它办法来避免“Table Scan”。首先我想到应该给表加上索引。于是我在PRID字段上创建非聚集索引。添加了索引后是否就能避免“Table Scan”?下面我们开始讨论关于“Index Scan”和“Index Seek”的主题。
首先在PRID字段上创建非聚集索引。
CREATE UNIQUE NONCLUSTERED INDEX UNC_PRID ON PerformanceIssue (PRID) GO
|
本文假定读者已经知道非聚集索引如何工作的知识。了解非聚集索引更详细的信息,请阅读BOL相关主题,也可参看 http://www.sql-server-performance.com/gv_index_data_structures.asp。下面我们详细讲述“Index Scan”是如何工作的。
执行下面语句并查看执行计划的结果。
Select PRID, PRCode, PRDesc From PerformanceIssue GO
|
奇怪了,“Table Scan”仍然用到了。为什么SQL Server没有用到那个非聚集索引?于是继续优化查询语句,选择检索两个字段 [PRID, PRCode] 。
Select PRID, PRCode From PerformanceIssue GO
|
执行结果是和上一个查询结果一摸一样。于是修改查询为只检索一个字段 [PRID] 。
Select PRID From PerformanceIssue GO
|
执行计划结果如下:
“Index Scan”在查询中被用到了,这很好。很自然,接下来的问题就是“Index Scan”什么时候会被用到。字段PRID上有一个索引,查询语句中选中的字段为PRID。执行查询的时候,SQL Server扫描索引页,因此用到了“Index Scan”方法。前面的查询中选择了有索引的和没有索引的字段,SQL Server无法使用“Index Scan”。当查询中只选择有索引的字段时,SQL Server就使用了“Index Scan”。我不清楚SQL Server底层到底是如何判断的,不过通过这些试验,我认为当查询中只选择有索引的字段时,SQL Server就使用“Index Scan”方法。
下面看“Index Seek”方法何时产生。当我看到“Seek”这个词时,第一反应就是条件查询这个主意。
我尝试三种不同的带WHERE语法的查询语句,以找出那种会用“Index Seek”。第一种语句如下:
Select PRID, PRCode, PRDesc From PerformanceIssue Where PRCode = 8 GO
|
结果显示,执行计划使用了“Table Scan”。
第二种语句如下:
Select PRID, PRCode, PRDesc From PerformanceIssue Where PRDesc = ' PerformanceIssue - 8' GO
|
执行计划仍然使用“Table Scan”方法。
第三种查询语句如下:
Select PRID, PRCode, PRDesc From PerformanceIssue Where PRID = 'D386C151-5F74-4C2A-B527-86FEF9712955'
-- PRID GUID value might be differ in your machine GO
|
查询用到了“Index Seek”和“Bookmark Lookup”方法。用到“Index Seek”是因为WHERE后面使用带索引的字段PRID来进行过滤。“Bookmark Lookup”方法被用到是因为查询中选择了没有索引的字段。如果去掉这两个没有索引的字段,那么“Bookmark Lookup”方法就可以去掉。当然如果只返回PRID字段,那么该查询就没什么意义了,因为WHERE语句后面已经给出PRID具体取值了。
我认为“Index Seek”在性能改善上比“Index Scan”和“Table Scan”要好,这主要表现在下面几个方面:
- “Index Seek”不需要对表和索引页进行扫描;而“Table Scan”和“Index Scan”需要。
- “Index Seek”利用“WHERE”来过滤获取的数据,这样比用“Index Scan”和“Table Scan”快很多。
当我完成这些测试后,我同事问我一个很有意思的问题:SQL Server什么时候使用“Clustered Index Scan”和“Clustered Index Seek”?下面对“Clustered Index Scan”和“Clustered Index Seek”进行实验。
我决定在PRCode上建一个聚集索引来测试“Clustered Index Scan”和“Clustered Index Seek”。
Clustered Index Scan & Clustered Index Seek
下面的脚本删除PRID字段上的索引,并在PRCode字段上创建聚集索引。
Drop Index PerformanceIssue.UNC_PRID GO CREATE UNIQUE CLUSTERED INDEX UC_PRCode ON PerformanceIssue( PRCode) GO ------------- Clustered index has been created successfully. Index has been created.
|
关于聚集索引的基础知识请查阅联机帮助的相关主题或者 http://www.sql-server-performance.com/gv_index_data_structures.asp。下面我们将重点放在“Clustered Index Scan”和“Clustered Index Seek”如何被使用上。
执行下面查询语句:
Select PRID, PRCode, PRDesc From PerformanceIssue GO
|
查询执行后,可以看到执行计划中用到了“Clustered Index Scan”。
下面用三种不同的WHERE方式来试验何时SQL Server会用到“Clustered Index Seek”。第一种形式如下:
Select PRID, PRCode, PRDesc From PerformanceIssue Where PRDesc = ' PerformanceIssue - 8' GO
|
查询执行后,可以看到执行计划中用到了“Clustered Index Scan”。
第二种形式如下:
Select PRID, PRCode, PRDesc From PerformanceIssue Where PRID = 'D386C151-5F74-4C2A-B527-86FEF9712955'
-- PRID GUID value might be differ in your machine GO
|
查询执行后,发现执行计划中用到的仍然是“Clustered Index Scan”。
第三种形式:
Select PRID, PRCode, PRDesc From PerformanceIssue Where PRCode = 8 GO
|
这次执行计划用到了“Clustered Index Seek”。
当在WHERE后用到PRCode字段的时候,“Clustered Index Seek”被用到。执行计划对聚集索引表检索的时候,因为在选取的字段中,包括没有索引的字段,所以不用用到“Bookmark Lookup”方法。
我个人认为,从改善性能角度考虑,“Clustered Index Seek”比“Clustered Index Scan”和“Index Seek”要好。
- “Clustered Index Seek”不需要扫描整个聚集索引页。
- 和“Index Scan”相比,对于检索选择的字段包含那些没有索引的字段时,“Clustered Index Seek”不会有“Bookmark Lookup”方法出现。
通过这些试验,我对执行计划的应用积累了实际经验。我知道哪种扫描机制可以提高性能,从而是的客户满意。
怎样查看sql的执行计划
如何启用AutoTrace 查看SQL执行计划
通过以下方法可以把Autotrace的权限授予Everyone,
如果你需要限制Autotrace权限,可以把对public的授权改为对特定user的授权。
D:\oracle\ora92>sqlplus /nolog
SQL*Plus: Release 9.2.0.1.0 - Production on 星期二 6月 3 15:16:03 2003
Copyright (c) 1982, 2002, Oracle Corporation. All rights reserved.
SQL> connect sys as sysdba
请输入口令:
已连接。
SQL> [b]@?\rdbms\admin\utlxplan[/b]
表已创建。
SQL> create public synonym plan_table for plan_table;
同义词已创建。
SQL> grant all on plan_table to public ;
授权成功。
SQL>[b] @?\sqlplus\admin\plustrce[/b]
SQL>
SQL> drop role plustrace;
drop role plustrace
*
ERROR 位于第 1 行:
ORA-01919: 角色'PLUSTRACE'不存在
SQL> create role plustrace;
角色已创建
SQL>
SQL> grant select on v_$sesstat to plustrace;
授权成功。
SQL> grant select on v_$statname to plustrace;
授权成功。
SQL> grant select on v_$session to plustrace;
授权成功。
SQL> grant plustrace to dba with admin option;
授权成功。
SQL>
SQL> set echo off
DBA用户首先被授予了plustrace角色,然后我们可以把plustrace授予public
这样所有用户都将拥有plustrace角色的权限.
SQL> [b]grant plustrace to public ;[/b]
授权成功。
然后我们就可以使用AutoTrace的功能了.
SQL> connect eqsp/eqsp
已连接。
SQL> set autotrace on
SQL> set timing on
SQL>
关于Autotrace几个常用选项的说明:
SET AUTOTRACE OFF ---------------- 不生成AUTOTRACE 报告,这是缺省模式
SET AUTOTRACE ON EXPLAIN ------ AUTOTRACE只显示优化器执行路径报告
SET AUTOTRACE ON STATISTICS -- 只显示执行统计信息
SET AUTOTRACE ON ----------------- 包含执行计划和统计信息
SET AUTOTRACE TRACEONLY ------ 同set autotrace on,但是不显示查询输出
SQL> set autotrace traceonly
SQL> select table_name from user_tables;
已选择98行。
已用时间: 00: 00: 00.04
Execution Plan
----------------------------------------------------------
0 SELECT STATEMENT Optimizer=CHOOSE
1 0 NESTED LOOPS
2 1 NESTED LOOPS (OUTER)
3 2 NESTED LOOPS (OUTER)
4 3 NESTED LOOPS (OUTER)
5 4 NESTED LOOPS (OUTER)
6 5 NESTED LOOPS
7 6 TABLE ACCESS (BY INDEX ROWID) OF 'OBJ$'
8 7 INDEX (RANGE SCAN) OF 'I_OBJ2' (UNIQUE)
9 6 TABLE ACCESS (CLUSTER) OF 'TAB$'
10 9 INDEX (UNIQUE SCAN) OF 'I_OBJ#' (NON-UNIQUE)
11 5 TABLE ACCESS (BY INDEX ROWID) OF 'OBJ$'
12 11 INDEX (UNIQUE SCAN) OF 'I_OBJ1' (UNIQUE)
13 4 INDEX (UNIQUE SCAN) OF 'I_OBJ1' (UNIQUE)
14 3 TABLE ACCESS (CLUSTER) OF 'USER$'
15 14 INDEX (UNIQUE SCAN) OF 'I_USER#' (NON-UNIQUE)
16 2 TABLE ACCESS (CLUSTER) OF 'SEG$'
17 16 INDEX (UNIQUE SCAN) OF 'I_FILE#_BLOCK#' (NON-UNIQUE)
18 1 TABLE ACCESS (CLUSTER) OF 'TS$'
19 18 INDEX (UNIQUE SCAN) OF 'I_TS#' (NON-UNIQUE)
Statistics
----------------------------------------------------------
0 recursive calls
0 db block gets
1389 consistent gets
0 physical reads
0 redo size
2528 bytes sent via SQL*Net to client
569 bytes received via SQL*Net from client
8 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
98 rows processed
SQL>
怎样查看sql的执行计划
如何启用AutoTrace 查看SQL执行计划
通过以下方法可以把Autotrace的权限授予Everyone,
如果你需要限制Autotrace权限,可以把对public的授权改为对特定user的授权。
D:\oracle\ora92>sqlplus /nolog
SQL*Plus: Release 9.2.0.1.0 - Production on 星期二 6月 3 15:16:03 2003
Copyright (c) 1982, 2002, Oracle Corporation. All rights reserved.
SQL> connect sys as sysdba
请输入口令:
已连接。
SQL> [b]@?\rdbms\admin\utlxplan[/b]
表已创建。
SQL> create public synonym plan_table for plan_table;
同义词已创建。
SQL> grant all on plan_table to public ;
授权成功。
SQL>[b] @?\sqlplus\admin\plustrce[/b]
SQL>
SQL> drop role plustrace;
drop role plustrace
*
ERROR 位于第 1 行:
ORA-01919: 角色'PLUSTRACE'不存在
SQL> create role plustrace;
角色已创建
SQL>
SQL> grant select on v_$sesstat to plustrace;
授权成功。
SQL> grant select on v_$statname to plustrace;
授权成功。
SQL> grant select on v_$session to plustrace;
授权成功。
SQL> grant plustrace to dba with admin option;
授权成功。
SQL>
SQL> set echo off
DBA用户首先被授予了plustrace角色,然后我们可以把plustrace授予public
这样所有用户都将拥有plustrace角色的权限.
SQL> [b]grant plustrace to public ;[/b]
授权成功。
然后我们就可以使用AutoTrace的功能了.
SQL> connect eqsp/eqsp
已连接。
SQL> set autotrace on
SQL> set timing on
SQL>
关于Autotrace几个常用选项的说明:
SET AUTOTRACE OFF ---------------- 不生成AUTOTRACE 报告,这是缺省模式
SET AUTOTRACE ON EXPLAIN ------ AUTOTRACE只显示优化器执行路径报告
SET AUTOTRACE ON STATISTICS -- 只显示执行统计信息
SET AUTOTRACE ON ----------------- 包含执行计划和统计信息
SET AUTOTRACE TRACEONLY ------ 同set autotrace on,但是不显示查询输出
SQL> set autotrace traceonly
SQL> select table_name from user_tables;
已选择98行。
已用时间: 00: 00: 00.04
Execution Plan
----------------------------------------------------------
0 SELECT STATEMENT Optimizer=CHOOSE
1 0 NESTED LOOPS
2 1 NESTED LOOPS (OUTER)
3 2 NESTED LOOPS (OUTER)
4 3 NESTED LOOPS (OUTER)
5 4 NESTED LOOPS (OUTER)
6 5 NESTED LOOPS
7 6 TABLE ACCESS (BY INDEX ROWID) OF 'OBJ$'
8 7 INDEX (RANGE SCAN) OF 'I_OBJ2' (UNIQUE)
9 6 TABLE ACCESS (CLUSTER) OF 'TAB$'
10 9 INDEX (UNIQUE SCAN) OF 'I_OBJ#' (NON-UNIQUE)
11 5 TABLE ACCESS (BY INDEX ROWID) OF 'OBJ$'
12 11 INDEX (UNIQUE SCAN) OF 'I_OBJ1' (UNIQUE)
13 4 INDEX (UNIQUE SCAN) OF 'I_OBJ1' (UNIQUE)
14 3 TABLE ACCESS (CLUSTER) OF 'USER$'
15 14 INDEX (UNIQUE SCAN) OF 'I_USER#' (NON-UNIQUE)
16 2 TABLE ACCESS (CLUSTER) OF 'SEG$'
17 16 INDEX (UNIQUE SCAN) OF 'I_FILE#_BLOCK#' (NON-UNIQUE)
18 1 TABLE ACCESS (CLUSTER) OF 'TS$'
19 18 INDEX (UNIQUE SCAN) OF 'I_TS#' (NON-UNIQUE)
Statistics
----------------------------------------------------------
0 recursive calls
0 db block gets
1389 consistent gets
0 physical reads
0 redo size
2528 bytes sent via SQL*Net to client
569 bytes received via SQL*Net from client
8 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
98 rows processed
SQL>
对于drop procedure 时hang住的问题
问题:在drop procedure的时候发现一直没反应,查询原因 SQL> conn sys/pwd@sid as sysdba 已连接。 SQL> oradebug username ORA-00070: 命令gdyf无效 SQL> oradebug setmypid 已处理的语句 SQL> oradebug hanganalyze 3 Hang Analysis in d:\oracle\admin\oracle\udump\oracle_ora_3200.trc 内容如下: Dump file d:\oracle\admin\oracle\udump\oracle_ora_3200.trc Tue Mar 18 15:39:01 2008 ORACLE V9.2.0.5.0 - Production vsnsta=0 vsnsql=12 vsnxtr=3 Windows 2000 Version 5.0 Service Pack 4, CPU type 586 Oracle9i Enterprise Edition Release 9.2.0.5.0 - Production With the Partitioning, OLAP and Oracle Data Mining options JServer Release 9.2.0.5.0 - Production Windows 2000 Version 5.0 Service Pack 4, CPU type 586 Instance name: oracle Redo thread mounted by this instance: 1 Oracle process number: 82 Windows thread id: 3200, image: ORACLE.EXE *** SESSION ID:(26.2234) 2008-03-18 15:39:01.390 *** 2008-03-18 15:39:01.390 ============== HANG ANALYSIS: ============== Open chains found: Chain 1 : <cnode/sid/sess_srno/proc_ptr/ospid/wait_event> : <0/48/20150/0x45a2b2e8/3336/No Wait> -- <0/40/11993/0x45a29c68/3284/library cache lock> Other chains found: Chain 2 : <cnode/sid/sess_srno/proc_ptr/ospid/wait_event> : <0/8/1/0x45a1ca68/2796/wakeup time manager> Chain 3 : <cnode/sid/sess_srno/proc_ptr/ospid/wait_event> : <0/26/2234/0x45a2dc28/3200/No Wait> Chain 4 : <cnode/sid/sess_srno/proc_ptr/ospid/wait_event> : <0/29/2338/0x45a25528/672/db file sequential read> Chain 5 : <cnode/sid/sess_srno/proc_ptr/ospid/wait_event> : <0/30/23502/0x45a23728/3224/db file sequential read> Chain 6 : <cnode/sid/sess_srno/proc_ptr/ospid/wait_event> : <0/64/22233/0x45a1f3a8/1892/No Wait> Chain 7 : <cnode/sid/sess_srno/proc_ptr/ospid/wait_event> : <0/69/1878/0x45a1dd28/2084/No Wait> Extra information that will be dumped at higher levels: [level 4] : 1 node dumps -- [REMOTE_WT] [LEAF] [LEAF_NW] [level 5] : 6 node dumps -- [SINGLE_NODE] [SINGLE_NODE_NW] [IGN_DMP] [level 6] : 1 node dumps -- [NLEAF] [level 10] : 73 node dumps -- [IGN] State of nodes ([nodenum]/cnode/sid/sess_srno/session/ospid/state/start/finish/[adjlist]/predecessor): [0]/0/1/1/0x4520da08/3160/IGN/1/2//none [1]/0/2/1/0x45a652ac/2828/IGN/3/4//none [2]/0/3/1/0x4520e378/1924/IGN/5/6//none [3]/0/4/1/0x45a65c1c/3308/IGN/7/8//none [4]/0/5/1/0x4520ece8/156/IGN/9/10//none [5]/0/6/1/0x45a6658c/1884/IGN/11/12//none [6]/0/7/1/0x4520f658/3064/IGN/13/14//none [7]/0/8/1/0x45a66efc/2796/SINGLE_NODE/15/16//none [8]/0/9/18325/0x4520ffc8/2496/IGN/17/18//none [12]/0/13/17667/0x452112a8/1928/IGN/19/20//none [13]/0/14/18771/0x45a68b4c/816/IGN/21/22//none [14]/0/15/9177/0x45211c18/2816/IGN/23/24//none [15]/0/16/16965/0x45a694bc/3108/IGN/25/26//none [16]/0/17/19671/0x45212588/2724/IGN/27/28//none [17]/0/18/25029/0x45a69e2c/3272/IGN/29/30//none [18]/0/19/11291/0x45212ef8/3080/IGN/31/32//none [19]/0/20/25825/0x45a6a79c/3164/IGN/33/34//none [20]/0/21/26486/0x45213868/448/IGN/35/36//none [21]/0/22/21584/0x45a6b10c/2316/IGN/37/38//none [22]/0/23/37646/0x452141d8/3340/IGN/39/40//none [23]/0/24/5364/0x45a6ba7c/1468/IGN/41/42//none [24]/0/25/33844/0x45214b48/2920/IGN/43/44//none [25]/0/26/2234/0x45a6c3ec/3200/SINGLE_NODE_NW/45/46//none [26]/0/27/28532/0x452154b8/2848/IGN/47/48//none [28]/0/29/2338/0x45215e28/672/SINGLE_NODE/49/50//none [29]/0/30/23502/0x45a6d6cc/3224/SINGLE_NODE/51/52//none [31]/0/32/17993/0x45a6e03c/2580/IGN/53/54//none [32]/0/33/21925/0x45217108/2584/IGN/55/56//none [33]/0/34/20841/0x45a6e9ac/1316/IGN/57/58//none [34]/0/35/19307/0x45217a78/3076/IGN/59/60//none [35]/0/36/19269/0x45a6f31c/3092/IGN/61/62//none [36]/0/37/11711/0x452183e8/2908/IGN/63/64//none [37]/0/38/29651/0x45a6fc8c/2156/IGN/65/66//none [38]/0/39/13933/0x45218d58/3332/IGN/67/68//none [39]/0/40/11993/0x45a705fc/3284/NLEAF/69/72/[47]/none [40]/0/41/23604/0x452196c8/3280/IGN/73/74//none [41]/0/42/30238/0x45a70f6c/3312/IGN/75/76//none [43]/0/44/15405/0x45a718dc/2528/IGN/77/78//none [45]/0/46/33109/0x45a7224c/1920/IGN/79/80//none [47]/0/48/20150/0x45a72bbc/3336/LEAF_NW/70/71//39 [48]/0/49/30884/0x4521bc88/2436/IGN/81/82//none [49]/0/50/17150/0x45a7352c/2620/IGN/83/84//none [50]/0/51/24541/0x4521c5f8/2376/IGN/85/86//none [51]/0/52/20825/0x45a73e9c/2924/IGN/87/88//none [52]/0/53/8516/0x4521cf68/764/IGN/89/90//none [53]/0/54/16868/0x45a7480c/3320/IGN/91/92//none [55]/0/56/14359/0x45a7517c/3356/IGN/93/94//none [56]/0/57/32976/0x4521e248/2624/IGN/95/96//none [57]/0/58/30428/0x45a75aec/3212/IGN/97/98//none [58]/0/59/12175/0x4521ebb8/3268/IGN/99/100//none [59]/0/60/15084/0x45a7645c/3032/IGN/101/102//none [60]/0/61/31222/0x4521f528/1912/IGN/103/104//none [61]/0/62/20108/0x45a76dcc/2564/IGN/105/106//none [62]/0/63/32235/0x4521fe98/3376/IGN/107/108//none [63]/0/64/22233/0x45a7773c/1892/SINGLE_NODE_NW/109/110//none [64]/0/65/27250/0x45220808/1948/IGN/111/112//none [65]/0/66/33424/0x45a780ac/3252/IGN/113/114//none [66]/0/67/41625/0x45221178/3360/IGN/115/116//none [67]/0/68/33495/0x45a78a1c/2420/IGN/117/118//none [68]/0/69/1878/0x45221ae8/2084/SINGLE_NODE_NW/119/120//none [70]/0/71/7937/0x45222458/3380/IGN/121/122//none [71]/0/72/18116/0x45a79cfc/1448/IGN/123/124//none [72]/0/73/37603/0x45222dc8/2936/IGN/125/126//none [73]/0/74/23965/0x45a7a66c/2480/IGN/127/128//none [74]/0/75/7067/0x45223738/3300/IGN/129/130//none [75]/0/76/8541/0x45a7afdc/1068/IGN/131/132//none [76]/0/77/9178/0x452240a8/2360/IGN/133/134//none [77]/0/78/25889/0x45a7b94c/2864/IGN/135/136//none [78]/0/79/11006/0x45224a18/2996/IGN/137/138//none [79]/0/80/19934/0x45a7c2bc/3384/IGN/139/140//none [80]/0/81/24305/0x45225388/3136/IGN/141/142//none [81]/0/82/27089/0x45a7cc2c/2744/IGN/143/144//none [82]/0/83/15792/0x45225cf8/3236/IGN/145/146//none [83]/0/84/19887/0x45a7d59c/2788/IGN/147/148//none [86]/0/87/20152/0x45226fd8/2284/IGN/149/150//none [87]/0/88/7617/0x45a7e87c/2776/IGN/151/152//none [88]/0/89/33192/0x45227948/3248/IGN/153/154//none [89]/0/90/22038/0x45a7f1ec/2652/IGN/155/156//none [90]/0/91/31249/0x452282b8/2852/IGN/157/158//none [91]/0/92/15647/0x45a7fb5c/3088/IGN/159/160//none [92]/0/93/3053/0x45228c28/3100/IGN/161/162//none ==================== END OF HANG ANALYSIS ====================
发现是如下出现问题: Chain 1 : <cnode/sid/sess_srno/proc_ptr/ospid/wait_event> : <0/48/20150/0x45a2b2e8/3336/No Wait> -- <0/40/11993/0x45a29c68/3284/library cache lock>
当前drop的session为40,然后查询48的session,居然是前面做重编译时候未成功退出的一个SESSION 然后orakill 这个session后正常drop完成
|
C、语句级别
这些需要用到Hint,比如:
SQL> SELECT /*+ RULE */ a.userid,
2 b.name,
3 b.depart_name
4 FROM tf_f_yhda a,
5 tf_f_depart b
6 WHERE a.userid=b.userid;
4、为什么有时一个表的某个字段明明有索引,当观察一些语的执行计划确不走索引呢?如何解决呢 ?
A、不走索引大体有以下几个原因
♀你在Instance级别所用的是all_rows的方式
♀你的表的统计信息(最可能的原因)
♀你的表很小,上文提到过的,Oracle的优化器认为不值得走索引。
B、解决方法
♀可以修改init<SID>.ora中的OPTIMIZER_MODE这个参数,把它改为Rule或Choose,重起数据库。也可以使用4中所提的Hint.
♀删除统计信息
SQL>analyze table table_name delete statistics;
♀表小不走索引是对的,不用调的。
5、其它相关
A、如何看一个表或索引是否是统计信息
SQL>SELECT * FROM user_tables
2 WHERE table_name=<table_name>
3 AND num_rows is not null;
SQL>SELECT * FROM user_indexes
2 WHERE table_name=<table_name>
3 AND num_rows is not null;
b、如果我们先用CBO的方式,我们应及时去更新表和索引的统计信息,以免生形不切合实的执行计划。
SQL> ANALYZE TABLE table_name COMPUTE STATISTICS;
SQL> ANALYZE INDEX index_name ESTIMATE STATISTICS;
具体的ANALYZE语句请参照Oracle8i/9i 的refrence文档。
<================end of file“Oracle的优化器(Optimizer)”=====================>
下面的是我的关于一点执行计划的理解:
1。首先要启动trace的选项:
set autotrace trace eXPlain
如果出现下面的错误:
SQL> set autotrace trace explain
SP2-0613: Unable to verify PLAN_TABLE format or existence
SP2-0611: Error enabling EXPLAIN report
那么要先运行下面的语句:
@?/rdbms/admin/utlxplan.sql;
2。分析下面的执行计划:
SQL> select ename,dname from emp, dept where emp.deptno=dept.deptno and dept.dname in ('ACCOUNTING','RESEARCH','SALES','OPERATIONS');
Execution Plan
----------------------------------------------------------
0 SELECT STATEMENT Optimizer=CHOOSE
1 0 NESTED LOOPS
2 1 TABLE Access (FULL) OF 'EMP'
3 1 TABLE ACCESS (BY INDEX ROWID) OF 'DEPT'
4 3 INDEX (UNIQUE SCAN) OF 'PK_DEPT' (UNIQUE)
关于前面的两个数字,第一个是状态ID,第二个是父ID。
就是如下所示:0-->1-->2
-->3-->4
在上图里,0的执行依靠1,1的执行又依赖2和3,2是没有子ID的,所以2最先执行,然后是4,在然后是3;然后2和3的结果传回1。
在这个里面0行有个字“Optimizer=CHOOSE”,这个就是上文说的那个oracle的优化器了。
还有,看这个“ INDEX (UNIQUE SCAN) OF 'PK_DEPT' (UNIQUE)”,就知道这个语句运行的时候是走INDEX的。
培训的第一天,如果JAVAC 和 JAVA 的版本不一致,将导致有时编译成功,运行时却出现错误提示。
当天发现的原因是,本机安装了ORACLE ,且在path中的变量排序中,oracle 和oracle\bin排在jdk之前,这将导致提前在运行的过程中,即java命令调用的是oracle\bin程序内的java程序。而非jdk中的。这将很容易导致两者(javac .java)两文件版本不一致而使高版本编译,却低版本(jre)运行。
第一天,主要是对学生的介绍,期待明天的课程。