﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>BlogJava-金家寶-随笔分类-MS-SQL</title><link>http://www.blogjava.net/jiabao/category/30685.html</link><description>機會只會給垂青有准備的人，運氣不是每個人都有的.</description><language>zh-cn</language><lastBuildDate>Sat, 12 Apr 2008 00:29:34 GMT</lastBuildDate><pubDate>Sat, 12 Apr 2008 00:29:34 GMT</pubDate><ttl>60</ttl><item><title>关于JAVA的分页查询操作技术</title><link>http://www.blogjava.net/jiabao/archive/2008/04/11/192222.html</link><dc:creator>金家寶</dc:creator><author>金家寶</author><pubDate>Fri, 11 Apr 2008 08:47:00 GMT</pubDate><guid>http://www.blogjava.net/jiabao/archive/2008/04/11/192222.html</guid><wfw:comment>http://www.blogjava.net/jiabao/comments/192222.html</wfw:comment><comments>http://www.blogjava.net/jiabao/archive/2008/04/11/192222.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jiabao/comments/commentRss/192222.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jiabao/services/trackbacks/192222.html</trackback:ping><description><![CDATA[
		<h1>　　Servlet版性能测试</h1>
		<div id="memo">
				<p>　　主要考虑的Servlet版运行方式有：</p>
				<p>　　一：Servlet在Web容器中的运行机制</p>
				<p>　　1． 单独一个无状态的Servlet实例运行</p>
				<p>　　即Web容器里的多个线程调用一个Servlet实例的运行方式</p>
				<p>　　2． 多个Servlet实例</p>
				<p>　　在Web容器中有多个Servlet实例的对象池，并有多个Web容器线程来分别调用执行</p>
				<p>　　二：Servlet 连接数据库的方式</p>
				<p>　　1． 一对一</p>
				<p>　　即可每个Servlet实例都有直接的数据库连接。</p>
				<p>　　具体方式有：</p>
				<p>　　1&gt; 在Servlet实例的每个处理方法中每次都调用数据库连接，然后用此连接进行数据库的查询等操作，最后关闭并释放此连接。</p>
				<p>　　2&gt; 在Servlet实例的初始化操作时就连接一个“长”的数据库连接，直到Servlet实例在destroy时关闭并释放此数据库连接。</p>
				<p>　　因为现在的数据库操作主要是查询，没有对数据库的增加、修改等操作，多用户业务查询、Web容器多线程同时对一个Servlet的同一个数据库连接进行操作应该会没有数据操作同步等问题。</p>
				<p>　　2． 使用Web容器的数据源</p>
				<p>　　这里主要是使用Web容器的数据源－数据库连接池。</p>
				<p>　　在理论上这种方式能提供最佳的性能。这是也是测试各种Web容器产品在数据库连接池上实现的性能情况。</p>
				<p>　　这里主要看Web容器的在各种应用情况下的最优化配置。</p>
				<p>　　Servlet与数据源连接的实现方式：</p>
				<p>　　Servlet直接从Web容器配置中取得数据源及其连接对象，然后通过此连接对象来操作数据库。对于数据库连接对象的管理由Web容器来管理。</p>
				<p>　　三：要考虑的问题：</p>
				<p>　　1． 大数据量传输问题</p>
				<p>　　大数据量通过Servlet实例从数据库中取得并整理后，如何有效的传输到客户端IE，并且Servlet实例如何有效在Web容器中处理这些大数据量。</p>
				<p>　　2． 对各种JDBC版本的测试</p>
				<p>　　即不同的数据库使用其自己专用的JDBC来连接，在性能上应该要好一些。</p>
				<p>　　这里也可比较Weblogic Server中实现JDBC与各种数据库（MSSQL、Oracle）专用的差别，从测试的结果看出Weblogic Server的技术实例以及是否真正做到了数据库连接等处理的优化了吗。</p>
				<p>　　3． Weblogic Server的优化配置</p>
				<p>　　3．1 对象池配置</p>
				<p>　　包括应用逻辑处理对象的对象池化以及使用数据源时的数据库连接对象池在各种具体应用环境下的优化配置。</p>
				<p>　　3．2 线程池配置</p>
				<p>　　以上两个方面涉及到对象池化和串行化处理的策略。</p>
				<p>　　3．3 Weblogic Server 的配置的各种参数的相应情况下的配置</p>
				<p>　　1&gt; JAVA VM (JAVA 虚拟机)参数在各种应用情况下的配置。</p>
				<p>　　2&gt; Weblogic Server 本身的各种参数配置。</p>
				<p>　　鉴于以上的考虑对Servlet版的测试规划为以下几种测试用例：</p>
				<p>　　序号 部署包名(*.JAR *.WAR *.EAR 等) 数据源配置 Weblogic Server</p>
				<p>　　的配置 预期结果 说明 可能出现的问题和现象</p>
				<p>　　1 ServletQueryForPerConn.war 在每此业务处理时创建数据库连接，操作完毕后关闭并释放。</p>
				<p>　　通过Web.xml配置文件来配置JDBC的驱动类型和连接。 直接部署ServletQueryForPerConn.jar部署包。</p>
				<p>　　Web容器中只有一个Serverlet实例。</p>
				<p>　　建议配置较多的线程数量。</p>
				<p>　　性能差。</p>
				<p>　　在每此业务处理时创建数据库连接，操作完毕后关闭并释放。</p>
				<p>　　此包中没有设计到线程同步的有关代码。 数据库很忙（因为数据库要接收频繁的数据库连接）。</p>
				<p>　　可能瓶颈在数据库对频繁的连接处理。</p>
				<p>　　数据库事务方面：由于是在每次处理时就调用数据库连接并查询，因此数据库的事务处理应该是单独在一个独立的处理过程中，与并行的其他线程的处理没有关系。</p>
				<p>　　2 ServletQueryForOnceConn.war Servlet对象只是的初始化时连接与数据库的一个连接，在以后的操作中式中使用这个连接。</p>
				<p>　　通过Web.xml配置文件来配置JDBC的驱动类型和连接。 直接部署ServletQueryForOnceConn.jar包；</p>
				<p>　　Web容器只有一个Servlet实例。</p>
				<p>　　建议配置较多的线程数量。</p>
				<p>　　性能较差。</p>
				<p>　　Servlet对象只是的初始化时连接与数据库的一个连接，在以后的操作中式中使用这个连接。</p>
				<p>　　此包中没有设计到线程同步的有关代码。 数据库连接只有一个。</p>
				<p>　　可能瓶颈在Web容器的多个线程对同一个数据库连接对象的同步等处理（这些同步处理是Web容器自己管理的）。</p>
				<p>　　可能出现查询的数据在多个客户请求中打乱（因为同时使用同一个数据库通信通道）；</p>
				<p>　　并且多个线程（单独的处理单元）可能会在同一个处理事务中，可能各个处理单元会串行操作数据库（这要看数据库的具体实现了）。</p>
				<p>　　3 ServletQueryForConnPool.war 直接使用Web容器的数据源和数据库连接池。 配置数据源及数据库连接池。</p>
				<p>　　建议根据实际情况优化配置数据源和连接池。如可建立多个连接池等配置。 性能好。 Servlet实例不管数据库连接，而是直接从Web容器中取得数据库连接。数据库的连接对象有Web容器全权管理。</p>
				<p>　　此包中没有设计到线程同步的有关代码。 对Web容器的数据库连接池的配置可能要根据具体情况进行有效的调整（如数据库连接对象个数和Web容器配额的线程个数的关系等）。如果配置不佳可能是性能瓶颈在Web容器或者在数据库方。</p>
				<p>　　4 ServletQueryForConnPool.war</p>
				<p>　　（同测试3） 同测试3 Web容器的数据源重新配置为数据库产品专用的JDBC驱动器。 性能好。 测试目的是比较各种不同的JDBC数据连接驱动器的性能，以便得出根据不同的数据库产品选择最佳的JDBC驱动器。</p>
				<p>　　只测试数据库产品提供的专用JDBC驱动器。</p>
				<p>　　（说明：因为测试3在理论上性能是最好，因此选用测试3。测试方法和测试3一样，这样才有可比性。） 同测试3。</p>
				<p>　　5 servletQueryDS_Cache.war 同测试3 同测试3 性能一般</p>
				<p>　　使用一变量来缓存查询的数据，用户以后的分页查询查询操作是直接从此缓存中取得的。</p>
				<p>　　这种方式对Web容器的内存要求高，效果不是很好，对数据量查询小的效果可能会好些。 优点：</p>
				<p>　　减少的了对数据库访问的次数。</p>
				<p>　　缺点：</p>
				<p>　　需要较大的内存。对Weblogic容器的内存要求高，对于有大量用户的查询操作，并且查询的结果集较大时，可能对整个系统的性能是个很大的瓶颈。</p>
				<p>　　</p>
				<p>　　对大量数据的分页处理</p>
				<p>　　问题描述：</p>
				<p>　　背景1：一客户通过IE请求Web服务器查询数据，而查询结果是上千条甚至是上万条记录，要求查询结果传送到IE客户端并分页显示。</p>
				<p>　　背景2：一客户通过IE或者其他方式请求Web服务器查询数据，而查询结果是上千条甚至是上万条记录，并要求查询结果把包传送到客户的E-mail中。</p>
				<p>　　问：对于这样的有大量数据的结果集，在Web服务器端如何有效的处理？</p>
				<p>　　可能涉及到的问题：</p>
				<p>　　1． 内存占用</p>
				<p>　　大量数据的结果集，可能要</p>
				<p>　　2． 传输速度及策略</p>
				<p>　　具体的分页处理技术</p>
				<p>　　</p>
				<p>　　序号 名称 处理方法 针对的数据库 例子说明 备注</p>
				<p>　　1 游标查询 直接使用ResultSet来处理。ResultSet是直接在数据库上建立游标，然后通过ResultSet的行位置定位接口来获得指定行位置的记录。</p>
				<p>　　当用户第一请求数据查询时，就执行SQL语句查询，获得的ResultSet对象及其要使用的连接对象都保存到其对应的会话对象中。</p>
				<p>　　以后的分页查询都通过第一次执行SQL获得的ResultSet对象定位取得指定行位置的记录。</p>
				<p>　　最后在用户不再进行分页查询时或会话关闭时，释放数据库连接和ResultSet对象等数据库访问资源。</p>
				<p>　　说明：在用例分页查询的整个会话期间，一个用户的分页查询就要占用一个数据库连接对象和结果集的游标，这种方式对数据库的访问资源占用比较大，并且其利用率不是很高。 所有的数据库产品。 优点：</p>
				<p>　　减少了数据库连接对象的多次分配获取，减少了对数据库的SQL查询执行。</p>
				<p>　　缺点：</p>
				<p>　　占用数据库访问资源－数据库连接对象，并占用了数据库上的资源－游标。而这些资源都是十分宝贵的有限制的。</p>
				<p>　　结论：</p>
				<p>　　这种的数据库查询分页处理方式不是最佳的。一般不适用这种方式。</p>
				<p>　　2 定位行集SQL查询 主要是直接使用数据库产品的提供的对查询的结果集可定位行范围的SQL接口技术。</p>
				<p>　　在用户的分页面查询请求中，每次可取得查询请求的行范围的参数，然后使用这些参数生产取得指定行范围的的SQL查询语句，然后每次请求获得一个数据库连接对象并执行SQL查询，把查询的结果返回给用户，最后释放说有的数据库访问资源。</p>
				<p>　　说明：这种方式需要每次请求时都要执行数据库的SQL查询语句；对数据库的访问资源是使用完就立即释放，不白白占用数据库访问资源。 对特定（提供了对查询结果集可定位功能的）的数据库产品。</p>
				<p>　　如：Oracle,DB2, PostgreSQL,mySQL等。(MS SQL Server 没有提供此技术。) 如:</p>
				<p>　　1． Oracle数据库使用关键字：rowid或rownum </p>
				<p>　　2． DB2:</p>
				<p>　　rowid或rownum ()</p>
				<p>　　3． PostgreSQL 使用LIMIT 和 OFFSET</p>
				<p>　　4． MySQL 使用Limit 优点：</p>
				<p>　　这种技术是直接使用数据库产品自己提供的可对查询结果集定位行范围过滤的功能，因此直接利用了数据库的性能对此分页查询的优化功能。</p>
				<p>　　对数据库的访问资源（数据库连接对象，数据库游标等）没有浪费，这些资源的充分重复的利用。</p>
				<p>　　对查询的结果对Web容器没有什么特别要求。</p>
				<p>　　缺点：</p>
				<p>　　要执行多次数据库SQL查询操作。对每次的分页面操作请求都要指定相应范围的结果集来执行SQL语句的数据库查询操作，这对数据库有一定的影响。</p>
				<p>　　对每次分页面查询请求要频繁的从Web容器中获得数据库访问资源（数据库连接对象和数据库游标）。</p>
				<p>　　要依赖于具体的数据库产品。因为对没有实现没有提供此技术的数据库产品不能使用此方式。</p>
				<p>　　结论：</p>
				<p>　　由于每次对数据库的SQL查询操作相对而言耗用的数据资源比较少，并且在实际用户的操作中，有可能用户对查询的所有结果集只是需要查看其中的部分页面。</p>
				<p>　　因此这种方式是最佳的。</p>
				<p>　　3 特别处理的定位行集SQL查询 这种方式是在方式2的基础上针对不提供对查询结果集行范围定位的数据库产品。</p>
				<p>　　其在Web容器端的操作逻辑大致和方式2相同。</p>
				<p>　　只是先要对要查询的数据库表要有一字段的数据能区别每条不同的数据记录。第一次查询时，获得用来可唯一标识不同记录的字段的所有结果集，并缓存起来以备后面的分页面查询指定要查询的结果集的行范围。 主要是针对不同对查询行集可定位范围获得的数据库产品，如MS SQL Server等。 假设从A，B，C三个表中选取数据。且A有字段ID用来可唯一区别不同的记录。</p>
				<p>　　那么第一次查询的时候，会查询两次1. select A.id from A,B,C where condition.</p>
				<p>　　2. 把A的ID缓存到SESSION中?3.从Session中。现可按照次序来取得相应页面范围的ID来，并构造下一个查询语句：select A.name, B.add from A,B,C where condition &amp;&amp; ( </p>
				<p>　　A.ID in 本页面范围的 ID )</p>
				<p>　　以后每次翻页的时候，依次获得对应页的ID只要表中唯一的就可以了。无所谓大小，顺序?这样，SESSSION缓存的就只是一列而不是所有列了。当然，对于列数不多的，效果并不好。</p>
				<p>　　也可使用存储过程实现，可参照：<a href="http://expert.csdn.net/Expert/topic" taggedby="hylanda">http://expert.csdn.net/Expert/topic</a></p>
				<p>　　/2365/2365596.xml?temp=.7529261</p>
				<p>　　优点：</p>
				<p>　　同方式2</p>
				<p>　　缺点：</p>
				<p>　　同方式2；</p>
				<p>　　还要在要查询的数据库表中建立一个相应的ID,用来唯一区别每条记录。</p>
				<p>　　结论：</p>
				<p>　　同方式2。</p>
				<p>　　4 缓存一次SQL查询的结果集 优点：</p>
				<p>　　缺点：</p>
				<p>　　既然我们要缓存结果，那么用户就可能会看到过期的数据</p>
				<p>　　</p>
				<p>　　说明：对于实际情况的应用来说，一般结合实际情况，结合使用方式2（或方式3）和方式4。如：一个应用场景：对公司的产品的查询是经常的，但是产品的种类不是很多，这时可使用缓存方式；但是对有些查询结果集较大，数据库和Web容器之间的网络访问由可能是远程的，这时候可考虑使方式2（或者方式3）。</p>
				<p>　　测试用例代码实现说明</p>
				<p>　　一：测试用例3－ServletQueryForConnPool 版本</p>
				<p>　　1．结构图</p>
				<p>　　</p>
				<p>　　2．代码实现结构</p>
				<p>　　3．运行时序图</p>
				<p>　　4．测试运行情况说明</p>
				<p>　　4．1 数据库连接和数据库游标占用可能比较大</p>
				<p>　　由于数据库的查询及其分页处理是直接使用JDBC的，并在分页中是使用RseultSet的查询结果集－游标形式实现的，并且每个客户对应一个会话，每个会话对应一个数据库连接和一个结果集（游标），数据库连接和游标是在会话终止时才释放的。因此在多个客户的请求过程中，可能对数据库的访问资源（数据库连接和用于数据操作的游标）占用比较大。</p>
				<p>　　因此数据库访问及其数据库的处理可能是个瓶颈。</p>
				<p>　　4．2 资源没有释放的问题</p>
				<p>　　会话对应的数据库连接和游标可能在会话终止时没有释放。</p>
				<p>　　为了更好的体现出使用Web容器数据库连接池的优点，应该合理的设置连接池中连接对象的“非活动超时时间”，建议次值和Servlet对象的会话超时时间长度一直。</p>
				<p>　　5．此测试用例操作说明</p>
				<p>　　5．1 部署的包的位置：</p>
				<p>　　ServletQueryForConnPool.war</p>
				<p>　　5．2 部署</p>
				<p>　　1．通过Weblogic 的控制台工具部署此包</p>
				<p>　　2．相关的参数请看ServletQueryForConnPool.war包中的配置文件web.xml中相应的servlet配置参数 </p>
				<p>　　5．3 测试URL</p>
				<p>　　http://Server：port/WebAppName</p>
				<p>　　即：</p>
				<p>　　http://Web服务器名：端口/Servlet部署的应用程序名</p>
				<p>　　二：测试用例4 ServletQueryForConnPool_cache 版本</p>
				<p>　　1．结构图</p>
				<p>　　和“一：测试用例3”相同</p>
				<p>　　2．代码实现结构</p>
				<p>　　3．运行时序</p>
				<p>　　说明：使用第四种“缓存一次SQL查询的结果集”的分页面查询技术，即一次SQL查询，把从数据库查询出来的结果保存到会话中，以后的客户分页查询操作都从此缓存中取得。</p>
				<p>　　4．测试运行情况说明</p>
				<p>　　由于使用的是缓存结果集的方式，对Web容器服务器的内存要求比较高，可能在测试过程中，Web容器服务器因内存问题而影响整个系统的响应性能。</p>
				<p>　　5．此测试用例操作说明</p>
				<p>　　5．1 部署的包的位置：</p>
				<p>　　ServletQueryForConnPool_cache.war</p>
		</div>
		<!--新闻内容//-->
		<!--评论发布-->
<img src ="http://www.blogjava.net/jiabao/aggbug/192222.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jiabao/" target="_blank">金家寶</a> 2008-04-11 16:47 <a href="http://www.blogjava.net/jiabao/archive/2008/04/11/192222.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>SQL基础常识</title><link>http://www.blogjava.net/jiabao/archive/2008/04/09/191612.html</link><dc:creator>金家寶</dc:creator><author>金家寶</author><pubDate>Tue, 08 Apr 2008 17:08:00 GMT</pubDate><guid>http://www.blogjava.net/jiabao/archive/2008/04/09/191612.html</guid><wfw:comment>http://www.blogjava.net/jiabao/comments/191612.html</wfw:comment><comments>http://www.blogjava.net/jiabao/archive/2008/04/09/191612.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jiabao/comments/commentRss/191612.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jiabao/services/trackbacks/191612.html</trackback:ping><description><![CDATA[SQL全称是“结构化查询语言(Structured Query Language)”，最早的是<a href="http://baike.baidu.com/view/1937.htm" target="_blank">IBM</a>的圣约瑟研究实验室为其关系数据库管理系统SYSTEM R开发的一种查询语言，它的前身是SQUARE语言。SQL语言结构简洁，功能强大，简单易学，所以自从IBM公司1981年推出以来，SQL语言，得到了广泛的应用。如今无论是像<a href="http://baike.baidu.com/view/15020.htm" target="_blank">Oracle</a> ,<a href="http://baike.baidu.com/view/118488.htm" target="_blank">Sybase</a>,Informix,SQL server这些大型的数据库管理系统，还是像Visual Foxporo,PowerBuilder这些微机上常用的数据库开发系统，都支持SQL语言作为查询语言。<br /><br />SQL是高级的非过程化编程语言，允许用户在高层数据结构上工作。他不要求用户指定对数据的存放方法，也不需要用户了解具体的数据存放方式，所以具有完全不同底层结构的不同数据库系统可以使用相同的SQL语言作为数据输入与管理的接口。它以记录集合作为操纵对象，所有SQL语句接受集合作为输入，返回集合作为输出，这种集合特性允许一条SQL语句的输出作为另一条SQL语句的输入，所以SQL语言可以嵌套，这使他具有极大的灵活性和强大的功能，在多数情况下，在其他语言中需要一大段程序实现的一个单独事件只需要一个SQL语句就可以达到目的，这也意味着用SQL语言可以写出非常复杂的语句。 <br /><br />SQL同时也是数据库文件格式的扩展名。 <br /><br />SQL语言包含4个部分： <br /><br />数据查询语言（SELECT语句） <br /><br />数据操纵语言（INSERT, UPDATE, DELETE语句） <br /><br />数据定义语言（如CREATE, DROP等语句） <br /><br />数据控制语言（如COMMIT, ROLLBACK等语句） <br /><br />取自"<a href="http://zh.wikipedia.org/wiki/SQL" target="_blank">http://zh.wikipedia.org/wiki/SQL</a>"<br />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 标准。<br /><br />      SQL 语言包括两种主要程式设计语言类别的陈述式： 资料定义语言 （DDL）与资料操作语言 （DML）。下面我们将介绍这两类语言。<br /><br />DDL<br />　<br /><br />      DDL 用於定义和管理物件，例如资料库、资料表以及检视表（ 第18章 将会解释何谓检视表）。DDL 陈述式通常包括每个物件的CREATE、ALTER 以及 DROP 命令。举例来说，CREATE TABLE、ALTER TABLE 以及 DROP TABLE 这些陈述式便可以用来建立新资料表、修改其属性（如新增或删除资料行）、删除资料表等，下面我们会一一介绍。<br /><br />CREATE TABLE 陈述式<br />　<br /><br />使用 DDL 在 MyDB 资料库建立一个名为 Customer_Data 的范例资料表，本章后面的例子我们会使用到这个资料表。如前所述，CREATE TABLE 陈述式可以用来建立资料表。这个范例资料表被定义成四个资料行，如下所示：<br /><br />Use MyDB<br />CREATE TABLE Customer_Data<br />(customer_id smallint,<br />first_name char(20),<br />last_name char(20),<br />phone char(10))<br />GO<br />这个陈述式能产生 Customer_Data 资料表，这个资料表会一直是空的直到资料被填入资料表内。<br /><br />ALTER TABLE 陈述式<br />　<br /><br />ALTER TABLE 陈述式用来变更资料表的定义与属性。在下面的例子中，我们利用 ALTER TABLE 在已经存在的 Customer_Data 资料表中新增 middle_initial 资料行。<br /><br />ALTER TABLE Customer_Data<br />ADD middle_initial char(1)<br />GO<br />现在资料表的定义包括了五个资料行，而不是之前的四个资料行。关於使用ALTER TABLE 的更多细节，请参阅 第15章 。<br /><br />DROP TABLE 陈述式<br />　<br /><br />DROP TABLE 陈述式用来删除资料表定义以及所有的资料、索引、触发程序、条件约束以及资料表的权限。要删除我们的 Customer_Data 资料表，可利用下列命令：<br /><br />DROP TABLE Customer_Data<br />GO<br />关於 DROP TABLE 陈述式的详细内容，请参阅 第15章 。<br /><br />DML<br />　<br /><br />DML 利用 INSERT、SELECT、UPDATE 及 DELETE 等陈述式来操作资料库物件所包含的资料。<br /><br />INSERT 陈述式<br />　<br /><br />INSERT 陈述式用来在资料表或检视表中插入一列资料。例如，如果要在Customer_Data 资料表中新增一个客户，可使用类似以下的 INSERT 陈述式：<br /><br />INSERT INTO Customer_Data<br />(customer_id, first_name, last_name, phone)<br />VALUES (777, "Frankie", "Stein", "4895873900")<br />请注意 SQL 陈述式中第二行的资料行名称清单，清单上资料行名称的次序决定了资料数值将被放在哪个资料行。举例来说，第一个资料数值将被放在清单列出的第一个资料行 customer_id、第二个资料数值放在第二个资料行，依此类推。由于我们在建立资料表时，定义资料资料行填入数值的次序与现在相同，因此我们不必特意指定栏位名称。我们可以用以下的 INSERT 陈述式代替：<br /><br />INSERT INTO Customer_Data<br />VALUES (777, "Frankie", "Stein", "4895873900")<br /><br />注意 <br /><br />如果使用这种形式的 INSERT 陈述式，但被插入的数值次序上与建立资料表时不同，数值将被放入错误的资料行。如果资料的型别与定义不符，则会收到一个错误讯息。<br /><br /><br />--------------------------------------------------------------------------------<br /><br />SELECT 陈述式<br />　<br /><br />SELECT 陈述式用来检索资料表中的资料，而哪些资料被检索由列出的资料行与陈述式中的 WHERE 子句决定。例如，要从之前建立的 Customer_Data 资料表中检索 customer_id 以及 first_name 资料行的资料，并且只想取出每列中 first_name 资料行值为 Frankie 的资料，那麼可以利用以下的 SELECT 陈述式：<br /><br />SELECT customer_id, first_name FROM Customer_Data<br />WHERE first_name = "Frankie"<br />如果有一列符合 SELECT 陈述式中的标准，则结果将显示如下：<br /><br />customer_id     first_name<br />-------------    ------------<br />777              Frankie<br />UPDATE 陈述式<br />　<br /><br />UPDATE 陈述式用来更新或改变一列或多列中的值。例如，一位名称为 Frankie Stein 的客户想要在记录中改变他的姓氏为 Franklin，可使用以下 UPDATE 陈述式：<br /><br />UPDATE Customer_Data<br />SET first_name = "Franklin"<br />WHERE last_name = "Stein" and customer_id= 777<br />我们在 WHERE 子句中加入 customer_id 的项目来确定其他名称为 Stein 的客户不会被影响－只有customer_id为777的客户，姓氏会有所改变。<br /><br />--------------------------------------------------------------------------------<br /><br />说明 <br /><br />当您使用 UPDATE 陈述式时，要确定在 WHERE 子句提供充分的筛选条件，如此才不会不经意地改变了一些不该改变的资料。<br /><br /><br />--------------------------------------------------------------------------------<br /><br />DELETE 陈述式<br />　<br /><br />DELETE 陈述式用来删除资料表中一列或多列的资料，您也可以删除资料表中的所有资料列。要从 Customer_Data 资料表中删除所有的列，您可以利用下列陈述式：<br /><br />DELETE FROM Customer_Data<br />或<br />DELETE Customer_Data<br />资料表名称前的 FROM 关键字在 DELETE 陈述式中是选择性的。除此之外，这两个陈述式完全相同。<br /><br />要从 Customer_Data 资料表中删除 customer_id 资料行的值小於100的列，可利用下列陈述式：<br /><br />DELETE FROM Customer_Data<br />WHERE customer_id &amp;lt; 100<br />现在我们已经快速浏览了 SQL 提供的 DDL 与 DML 陈述式，接著，下面将介绍 T-SQL。<br /><br />SQL中的五种数据类型  <br /><br />简要描述一下SQL中的五种数据类型:字符型，文本型，数值型，逻辑型和日期型<br /><br />字符型<br /><br />VARCHAR VS CHAR<br /><br />VARCHAR型和CHAR型数据的这个差别是细微的，但是非常重要。他们都是用来储存字符串长度小于255的字符。<br /><br />假如你向一个长度为四十个字符的VARCHAR型字段中输入数据BIll GAtES。当你以后从这个字段中取出此数据时，你取出的数据其长度为十个字符——字符串Bill Gates的长度。 现在假如你把字符串输入一个长度为四十个字符的CHAR型字段中，那么当你取出数据时，所取出的数据长度将是四十个字符。字符串的后面会被附加多余的空格。<br /><br />当你建立自己的站点时，你会发现使用VARCHAR型字段要比CHAR型字段方便的多。使用VARCHAR型字段时，你不需要为剪掉你数据中多余的空格而操心。<br /><br />VARCHAR型字段的另一个突出的好处是它可以比CHAR型字段占用更少的内存和硬盘空间。当你的数据库很大时，这种内存和磁盘空间的节省会变得非常重要<br /><br />文本型<br /><br />TEXT<br /><br />使用文本型数据，你可以存放超过二十亿个字符的字符串。当你需要存储大串的字符时，应该使用文本型数据。<br /><br />注意文本型数据没有长度，而上一节中所讲的字符型数据是有长度的。一个文本型字段中的数据通常要么为空，要么很大。<br /><br />当你从HTML fORM的多行文本编辑框(TEXTAREA)中收集数据时，你应该把收集的信息存储于文本型字段中。但是，无论何时，只要你能避免使用文本型字段，你就应该不适用它。文本型字段既大且慢，滥用文本型字段会使服务器速度变慢。文本型字段还会吃掉大量的磁盘空间。<br /><br />一旦你向文本型字段中输入了任何数据(甚至是空值)，就会有2K的空间被自动分配给该数据。除非删除该记录，否则你无法收回这部分存储空间。<br /><br />数值型<br /><br />SQL支持许多种不同的数值型数据。你可以存储整数 INT 、小数 NUMERIC、和钱数 MONEY。<br /><br />INT VS SMALLINT VS TINYINT<br /><br />他们的区别只是字符长度:<br /><br />INT型数据的表数范围是从-2，147，483，647到2，147，483，647的整数<br /><br />SMALLINT 型数据可以存储从-32768到32768的整数<br /><br />TINYINT 型的字段只能存储从0到255的整数,不能用来储存负数<br /><br />通常，为了节省空间，应该尽可能的使用最小的整型数据。一个TINYINT型数据只占用一个字节;一个INT型数据占用四个字节。这看起来似乎差别不大，但是在比较大的表中，字节数的增长是很快的。另一方面，一旦你已经创建了一个字段，要修改它是很困难的。因此，为安全起见，你应该预测以下，一个字段所需要存储的数值最大有可能是多大，然后选择适当的数据类型。<br /><br />NUMERIC<br /><br />为了能对字段所存放的数据有更多的控制，你可以使用NUMERIC型数据来同时表示一个数的整数部分和小数部分。NUMERIC型数据使你能表示非常大的数——比INT型数据要大得多。一个NUMERIC型字段可以存储从-1038到1038范围内的数。NUMERIC型数据还使你能表示有小数部分的数。例如，你可以在NUMERIC型字段中存储小数3.14。<br /><br />当定义一个NUMERIC型字段时，你需要同时指定整数部分的大小和小数部分的大小。如:MUNERIC(23,0)<br /><br />一个 NUMERIC型数据的整数部分最大只能有28位，小数部分的位数必须小于或等于整数部分的位数，小数部分可以是零。<br /><br />MONEY VS SMALLMONEY<br /><br />你可以使用 INT型或NUMERIC型数据来存储钱数。但是，专门有另外两种数据类型用于此目的。如果你希望你的网点能挣很多钱，你可以使用MONEY型数据。如果你的野心不大，你可以使用SMALLMONEY型数据。MONEY型数据可以存储从-922，337，203，685，477.5808到922，337，203，685，477.5807的钱数。如果你需要存储比这还大的金额，你可以使用NUMERIC型数据。<br /><br />SMALLMONEY型数据只能存储从-214，748.3648到214，748.3647 的钱数。同样，如果可以的话，你应该用SMALLMONEY型来代替MONEY型数据，以节省空间。<br /><br />逻辑型<br /><br />BIT<br /><br />如果你使用复选框( CHECKBOX)从网页中搜集信息，你可以把此信息存储在BIT型字段中。BIT型字段只能取两个值:0或1。<br /><br />当心，在你创建好一个表之后，你不能向表中添加 BIT型字段。如果你打算在一个表中包含BIT型字段，你必须在创建表时完成。<br /><br />日期型<br /><br />DATETIME VS SMALLDATETIME<br /><br />一个 DATETIME型的字段可以存储的日期范围是从1753年1月1日第一毫秒到9999年12月31日最后一毫秒。<br /><br />如果你不需要覆盖这么大范围的日期和时间，你可以使用SMALLDATETIME型数据。它与DATETIME型数据同样使用，只不过它能表示的日期和时间范围比DATETIME型数据小，而且不如DATETIME型数据精确。一个SMALLDATETIME型的字段能够存储从1900年1月1日到2079年6月6日的日期，它只能精确到秒。<br /><br />DATETIME型字段在你输入日期和时间之前并不包含实际的数据，认识这一点是重要的。<img src ="http://www.blogjava.net/jiabao/aggbug/191612.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jiabao/" target="_blank">金家寶</a> 2008-04-09 01:08 <a href="http://www.blogjava.net/jiabao/archive/2008/04/09/191612.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>SQL基础常识</title><link>http://www.blogjava.net/jiabao/archive/2008/04/09/191613.html</link><dc:creator>金家寶</dc:creator><author>金家寶</author><pubDate>Tue, 08 Apr 2008 17:08:00 GMT</pubDate><guid>http://www.blogjava.net/jiabao/archive/2008/04/09/191613.html</guid><wfw:comment>http://www.blogjava.net/jiabao/comments/191613.html</wfw:comment><comments>http://www.blogjava.net/jiabao/archive/2008/04/09/191613.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jiabao/comments/commentRss/191613.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jiabao/services/trackbacks/191613.html</trackback:ping><description><![CDATA[SQL全称是“结构化查询语言(Structured Query Language)”，最早的是<a href="http://baike.baidu.com/view/1937.htm" target="_blank">IBM</a>的圣约瑟研究实验室为其关系数据库管理系统SYSTEM R开发的一种查询语言，它的前身是SQUARE语言。SQL语言结构简洁，功能强大，简单易学，所以自从IBM公司1981年推出以来，SQL语言，得到了广泛的应用。如今无论是像<a href="http://baike.baidu.com/view/15020.htm" target="_blank">Oracle</a> ,<a href="http://baike.baidu.com/view/118488.htm" target="_blank">Sybase</a>,Informix,SQL server这些大型的数据库管理系统，还是像Visual Foxporo,PowerBuilder这些微机上常用的数据库开发系统，都支持SQL语言作为查询语言。<br /><br />SQL是高级的非过程化编程语言，允许用户在高层数据结构上工作。他不要求用户指定对数据的存放方法，也不需要用户了解具体的数据存放方式，所以具有完全不同底层结构的不同数据库系统可以使用相同的SQL语言作为数据输入与管理的接口。它以记录集合作为操纵对象，所有SQL语句接受集合作为输入，返回集合作为输出，这种集合特性允许一条SQL语句的输出作为另一条SQL语句的输入，所以SQL语言可以嵌套，这使他具有极大的灵活性和强大的功能，在多数情况下，在其他语言中需要一大段程序实现的一个单独事件只需要一个SQL语句就可以达到目的，这也意味着用SQL语言可以写出非常复杂的语句。 <br /><br />SQL同时也是数据库文件格式的扩展名。 <br /><br />SQL语言包含4个部分： <br /><br />数据查询语言（SELECT语句） <br /><br />数据操纵语言（INSERT, UPDATE, DELETE语句） <br /><br />数据定义语言（如CREATE, DROP等语句） <br /><br />数据控制语言（如COMMIT, ROLLBACK等语句） <br /><br />取自"<a href="http://zh.wikipedia.org/wiki/SQL" target="_blank">http://zh.wikipedia.org/wiki/SQL</a>"<br />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 标准。<br /><br />      SQL 语言包括两种主要程式设计语言类别的陈述式： 资料定义语言 （DDL）与资料操作语言 （DML）。下面我们将介绍这两类语言。<br /><br />DDL<br />　<br /><br />      DDL 用於定义和管理物件，例如资料库、资料表以及检视表（ 第18章 将会解释何谓检视表）。DDL 陈述式通常包括每个物件的CREATE、ALTER 以及 DROP 命令。举例来说，CREATE TABLE、ALTER TABLE 以及 DROP TABLE 这些陈述式便可以用来建立新资料表、修改其属性（如新增或删除资料行）、删除资料表等，下面我们会一一介绍。<br /><br />CREATE TABLE 陈述式<br />　<br /><br />使用 DDL 在 MyDB 资料库建立一个名为 Customer_Data 的范例资料表，本章后面的例子我们会使用到这个资料表。如前所述，CREATE TABLE 陈述式可以用来建立资料表。这个范例资料表被定义成四个资料行，如下所示：<br /><br />Use MyDB<br />CREATE TABLE Customer_Data<br />(customer_id smallint,<br />first_name char(20),<br />last_name char(20),<br />phone char(10))<br />GO<br />这个陈述式能产生 Customer_Data 资料表，这个资料表会一直是空的直到资料被填入资料表内。<br /><br />ALTER TABLE 陈述式<br />　<br /><br />ALTER TABLE 陈述式用来变更资料表的定义与属性。在下面的例子中，我们利用 ALTER TABLE 在已经存在的 Customer_Data 资料表中新增 middle_initial 资料行。<br /><br />ALTER TABLE Customer_Data<br />ADD middle_initial char(1)<br />GO<br />现在资料表的定义包括了五个资料行，而不是之前的四个资料行。关於使用ALTER TABLE 的更多细节，请参阅 第15章 。<br /><br />DROP TABLE 陈述式<br />　<br /><br />DROP TABLE 陈述式用来删除资料表定义以及所有的资料、索引、触发程序、条件约束以及资料表的权限。要删除我们的 Customer_Data 资料表，可利用下列命令：<br /><br />DROP TABLE Customer_Data<br />GO<br />关於 DROP TABLE 陈述式的详细内容，请参阅 第15章 。<br /><br />DML<br />　<br /><br />DML 利用 INSERT、SELECT、UPDATE 及 DELETE 等陈述式来操作资料库物件所包含的资料。<br /><br />INSERT 陈述式<br />　<br /><br />INSERT 陈述式用来在资料表或检视表中插入一列资料。例如，如果要在Customer_Data 资料表中新增一个客户，可使用类似以下的 INSERT 陈述式：<br /><br />INSERT INTO Customer_Data<br />(customer_id, first_name, last_name, phone)<br />VALUES (777, "Frankie", "Stein", "4895873900")<br />请注意 SQL 陈述式中第二行的资料行名称清单，清单上资料行名称的次序决定了资料数值将被放在哪个资料行。举例来说，第一个资料数值将被放在清单列出的第一个资料行 customer_id、第二个资料数值放在第二个资料行，依此类推。由于我们在建立资料表时，定义资料资料行填入数值的次序与现在相同，因此我们不必特意指定栏位名称。我们可以用以下的 INSERT 陈述式代替：<br /><br />INSERT INTO Customer_Data<br />VALUES (777, "Frankie", "Stein", "4895873900")<br /><br />注意 <br /><br />如果使用这种形式的 INSERT 陈述式，但被插入的数值次序上与建立资料表时不同，数值将被放入错误的资料行。如果资料的型别与定义不符，则会收到一个错误讯息。<br /><br /><br />--------------------------------------------------------------------------------<br /><br />SELECT 陈述式<br />　<br /><br />SELECT 陈述式用来检索资料表中的资料，而哪些资料被检索由列出的资料行与陈述式中的 WHERE 子句决定。例如，要从之前建立的 Customer_Data 资料表中检索 customer_id 以及 first_name 资料行的资料，并且只想取出每列中 first_name 资料行值为 Frankie 的资料，那麼可以利用以下的 SELECT 陈述式：<br /><br />SELECT customer_id, first_name FROM Customer_Data<br />WHERE first_name = "Frankie"<br />如果有一列符合 SELECT 陈述式中的标准，则结果将显示如下：<br /><br />customer_id     first_name<br />-------------    ------------<br />777              Frankie<br />UPDATE 陈述式<br />　<br /><br />UPDATE 陈述式用来更新或改变一列或多列中的值。例如，一位名称为 Frankie Stein 的客户想要在记录中改变他的姓氏为 Franklin，可使用以下 UPDATE 陈述式：<br /><br />UPDATE Customer_Data<br />SET first_name = "Franklin"<br />WHERE last_name = "Stein" and customer_id= 777<br />我们在 WHERE 子句中加入 customer_id 的项目来确定其他名称为 Stein 的客户不会被影响－只有customer_id为777的客户，姓氏会有所改变。<br /><br />--------------------------------------------------------------------------------<br /><br />说明 <br /><br />当您使用 UPDATE 陈述式时，要确定在 WHERE 子句提供充分的筛选条件，如此才不会不经意地改变了一些不该改变的资料。<br /><br /><br />--------------------------------------------------------------------------------<br /><br />DELETE 陈述式<br />　<br /><br />DELETE 陈述式用来删除资料表中一列或多列的资料，您也可以删除资料表中的所有资料列。要从 Customer_Data 资料表中删除所有的列，您可以利用下列陈述式：<br /><br />DELETE FROM Customer_Data<br />或<br />DELETE Customer_Data<br />资料表名称前的 FROM 关键字在 DELETE 陈述式中是选择性的。除此之外，这两个陈述式完全相同。<br /><br />要从 Customer_Data 资料表中删除 customer_id 资料行的值小於100的列，可利用下列陈述式：<br /><br />DELETE FROM Customer_Data<br />WHERE customer_id &amp;lt; 100<br />现在我们已经快速浏览了 SQL 提供的 DDL 与 DML 陈述式，接著，下面将介绍 T-SQL。<br /><br />SQL中的五种数据类型  <br /><br />简要描述一下SQL中的五种数据类型:字符型，文本型，数值型，逻辑型和日期型<br /><br />字符型<br /><br />VARCHAR VS CHAR<br /><br />VARCHAR型和CHAR型数据的这个差别是细微的，但是非常重要。他们都是用来储存字符串长度小于255的字符。<br /><br />假如你向一个长度为四十个字符的VARCHAR型字段中输入数据BIll GAtES。当你以后从这个字段中取出此数据时，你取出的数据其长度为十个字符——字符串Bill Gates的长度。 现在假如你把字符串输入一个长度为四十个字符的CHAR型字段中，那么当你取出数据时，所取出的数据长度将是四十个字符。字符串的后面会被附加多余的空格。<br /><br />当你建立自己的站点时，你会发现使用VARCHAR型字段要比CHAR型字段方便的多。使用VARCHAR型字段时，你不需要为剪掉你数据中多余的空格而操心。<br /><br />VARCHAR型字段的另一个突出的好处是它可以比CHAR型字段占用更少的内存和硬盘空间。当你的数据库很大时，这种内存和磁盘空间的节省会变得非常重要<br /><br />文本型<br /><br />TEXT<br /><br />使用文本型数据，你可以存放超过二十亿个字符的字符串。当你需要存储大串的字符时，应该使用文本型数据。<br /><br />注意文本型数据没有长度，而上一节中所讲的字符型数据是有长度的。一个文本型字段中的数据通常要么为空，要么很大。<br /><br />当你从HTML fORM的多行文本编辑框(TEXTAREA)中收集数据时，你应该把收集的信息存储于文本型字段中。但是，无论何时，只要你能避免使用文本型字段，你就应该不适用它。文本型字段既大且慢，滥用文本型字段会使服务器速度变慢。文本型字段还会吃掉大量的磁盘空间。<br /><br />一旦你向文本型字段中输入了任何数据(甚至是空值)，就会有2K的空间被自动分配给该数据。除非删除该记录，否则你无法收回这部分存储空间。<br /><br />数值型<br /><br />SQL支持许多种不同的数值型数据。你可以存储整数 INT 、小数 NUMERIC、和钱数 MONEY。<br /><br />INT VS SMALLINT VS TINYINT<br /><br />他们的区别只是字符长度:<br /><br />INT型数据的表数范围是从-2，147，483，647到2，147，483，647的整数<br /><br />SMALLINT 型数据可以存储从-32768到32768的整数<br /><br />TINYINT 型的字段只能存储从0到255的整数,不能用来储存负数<br /><br />通常，为了节省空间，应该尽可能的使用最小的整型数据。一个TINYINT型数据只占用一个字节;一个INT型数据占用四个字节。这看起来似乎差别不大，但是在比较大的表中，字节数的增长是很快的。另一方面，一旦你已经创建了一个字段，要修改它是很困难的。因此，为安全起见，你应该预测以下，一个字段所需要存储的数值最大有可能是多大，然后选择适当的数据类型。<br /><br />NUMERIC<br /><br />为了能对字段所存放的数据有更多的控制，你可以使用NUMERIC型数据来同时表示一个数的整数部分和小数部分。NUMERIC型数据使你能表示非常大的数——比INT型数据要大得多。一个NUMERIC型字段可以存储从-1038到1038范围内的数。NUMERIC型数据还使你能表示有小数部分的数。例如，你可以在NUMERIC型字段中存储小数3.14。<br /><br />当定义一个NUMERIC型字段时，你需要同时指定整数部分的大小和小数部分的大小。如:MUNERIC(23,0)<br /><br />一个 NUMERIC型数据的整数部分最大只能有28位，小数部分的位数必须小于或等于整数部分的位数，小数部分可以是零。<br /><br />MONEY VS SMALLMONEY<br /><br />你可以使用 INT型或NUMERIC型数据来存储钱数。但是，专门有另外两种数据类型用于此目的。如果你希望你的网点能挣很多钱，你可以使用MONEY型数据。如果你的野心不大，你可以使用SMALLMONEY型数据。MONEY型数据可以存储从-922，337，203，685，477.5808到922，337，203，685，477.5807的钱数。如果你需要存储比这还大的金额，你可以使用NUMERIC型数据。<br /><br />SMALLMONEY型数据只能存储从-214，748.3648到214，748.3647 的钱数。同样，如果可以的话，你应该用SMALLMONEY型来代替MONEY型数据，以节省空间。<br /><br />逻辑型<br /><br />BIT<br /><br />如果你使用复选框( CHECKBOX)从网页中搜集信息，你可以把此信息存储在BIT型字段中。BIT型字段只能取两个值:0或1。<br /><br />当心，在你创建好一个表之后，你不能向表中添加 BIT型字段。如果你打算在一个表中包含BIT型字段，你必须在创建表时完成。<br /><br />日期型<br /><br />DATETIME VS SMALLDATETIME<br /><br />一个 DATETIME型的字段可以存储的日期范围是从1753年1月1日第一毫秒到9999年12月31日最后一毫秒。<br /><br />如果你不需要覆盖这么大范围的日期和时间，你可以使用SMALLDATETIME型数据。它与DATETIME型数据同样使用，只不过它能表示的日期和时间范围比DATETIME型数据小，而且不如DATETIME型数据精确。一个SMALLDATETIME型的字段能够存储从1900年1月1日到2079年6月6日的日期，它只能精确到秒。<br /><br />DATETIME型字段在你输入日期和时间之前并不包含实际的数据，认识这一点是重要的。<img src ="http://www.blogjava.net/jiabao/aggbug/191613.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jiabao/" target="_blank">金家寶</a> 2008-04-09 01:08 <a href="http://www.blogjava.net/jiabao/archive/2008/04/09/191613.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>关于sql的执行计划（推荐详细）</title><link>http://www.blogjava.net/jiabao/archive/2008/04/08/191595.html</link><dc:creator>金家寶</dc:creator><author>金家寶</author><pubDate>Tue, 08 Apr 2008 15:38:00 GMT</pubDate><guid>http://www.blogjava.net/jiabao/archive/2008/04/08/191595.html</guid><wfw:comment>http://www.blogjava.net/jiabao/comments/191595.html</wfw:comment><comments>http://www.blogjava.net/jiabao/archive/2008/04/08/191595.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jiabao/comments/commentRss/191595.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jiabao/services/trackbacks/191595.html</trackback:ping><description><![CDATA[
		<div style="FONT-SIZE: 14px; FONT-FAMILY: Verdana">
				<p>刚开始用SQL Server的时候，我没有用<strong>显示执行计划</strong>来对查询进行分析。我曾经一直认为我递交的SQL查询都是最优的，而忽略了查询性能究竟如何，从而对“执行计划”重视不够。在我职业初期，我只要能获取数据就很开心，而不去考虑数据是如何返回的，“执行计划”对我的查询作了什么工作。我以为SQL Server会自己去处理查询的性能问题的。作为一个刚进入IT行业或者刚学到新技术的软件工程师，在编写代码前不太可能有时间去学习其实必须掌握的知识。也许这是因为IT行业竞争太激烈的缘故。 </p>
				<p>随着时间的流逝，数据库容量慢慢变大了。终于某天，客户对应用系统的查询性能感到不满意了。他面带怒容来找我，抱怨由于查询太慢，使得他需要花更多的时间来处理公务。最初，我建议客户升级其系统资源，例如作为临时解决方案，增加硬盘容量。虽然硬盘价格现在很便宜了，但是客户还是要求我提供一个永久性的解决方案，检查和好好调试查询语句，来替代那种无休止地升级资源的临时方案。因为客户的满意度对IT行业来说是十分重要的，因此我不得不考虑他的个人建议。我答应他一定会检查和调整我的代码。 </p>
		</div>
		<br />
		<div style="FONT-WEIGHT: bold; FONT-SIZE: 16px; COLOR: #446996; FONT-FAMILY: bookman old style">
				<p>如何入手呢?</p>
		</div>
		<div style="FONT-SIZE: 14px; FONT-FAMILY: Verdana">
				<p>在刚进入IT行业时，我知道SQL Server的基础只是。说实话，向客户承诺检查系统的时候，我还没有一点入手的头绪。不过我相信我可以通过GOOGL和BOL来获取相应的信息。 </p>
				<p>我阅读了一些关于SQL Server的书籍，BOL，以及在网上搜索的信息。于是我知道了“显示执行计划”的概念。可以在查询管理器中将该选项的开关设置为ON。“显示执行计划”是一个图形化工具，可以帮助开发者和DBA分析，优化查询，从而改善性能。 </p>
				<p>“显示执行计划”中不同的任务具有不同的图标。本文中我主要对“Table Scan”、“Index Scan”、“Index Seek”、“Cluster Index Scan”以及“Clustered Index Seek”感兴趣。也许在以后，可以对别的任务进行另外介绍。 </p>
				<p>时间以F1方程式的速度开始流逝，我觉得该是我全面理解“Table Scan”、“Index Scan”、“Index Seek”、“Clustered Index Scan”、和“Clustered Index Seek”如何工作的时候了。 </p>
				<p>我准备开始分析并优化我的查询。在分析之前，我想到了一些问题。 </p>
				<p>
						<strong>
						</strong>
				</p>
				<ul>
						<li>
								<strong>MS-SQL Server什么时候使用"Table Scan"? </strong>
						</li>
						<li>
								<strong>MS-SQL Server什么时候使用"Index Scan"? </strong>
						</li>
						<li>
								<strong>MS-SQL Server什么时候使用"Index Seek"? </strong>
						</li>
						<li>
								<strong>MS-SQL Server什么时候使用"Clustered Index Scan"? </strong>
						</li>
						<li>
								<strong>MS-SQL Server什么时候使用"Clustered Index Seek"? </strong>
						</li>
				</ul>
				<p> </p>
				<p>我主要关注SQL Server是根据什么来使用“执行计划”分析查询的。在经过一段时间学习后，我了解了一些相关知识。这些知识应该对开发和DBA新手有帮助。于是我决定写这篇文章，共享我的知识以帮助别人来理解“执行计划”。 </p>
				<p>如果你喜欢，可以慢慢读完，也可以在SQL Server上，模拟我下面做的实验。 </p>
		</div>
		<br />
		<div style="FONT-WEIGHT: bold; FONT-SIZE: 16px; COLOR: #446996; FONT-FAMILY: bookman old style">
				<p>开始入手</p>
		</div>
		<div style="FONT-SIZE: 14px; FONT-FAMILY: Verdana">
				<p>为了解释“显示执行计划”中的“Table Scan”、“Index Scan”、“Index Seek”、“Clustered Index Scan”和“Clustered Index Seek”，先创建新表，并添加一些示例数据进去。下面是创建新表的脚本： </p>
				<p> </p>
				<table style="TABLE-LAYOUT: fixed; BACKGROUND-COLOR: #f9f9f9" cellspacing="5" width="90%">
						<tbody>
								<tr>
										<td>
												<p style="FONT-SIZE: 14px; FONT-FAMILY: Verdana">Create Table PerformanceIssue<br />(<br />    PRID UniqueIdentifier NOT NULL,<br />    PRCode Int NOT NULL,<br />    PRDesc Varchar (100) NOT NULL<br />)<br />ON [PRIMARY]<br /></p>
										</td>
								</tr>
						</tbody>
				</table>
				<p> </p>
				<p>表创建后需要添加一些数据。使用下面的脚本添加100,000条记录进去。脚本执行时间可能比较长，请耐心等待其执行完毕。 </p>
				<p> </p>
				<table style="TABLE-LAYOUT: fixed; BACKGROUND-COLOR: #f9f9f9" cellspacing="5" width="90%">
						<tbody>
								<tr>
										<td>
												<p style="FONT-SIZE: 14px; FONT-FAMILY: Verdana">Declare @Loop Int<br />Declare @PRID UniqueIdentifier<br />Declare @ PRDesc Varchar (100)<br /><br />Set @Loop = 1<br />Set @ PRDesc = ''<br /><br />WHILE @Loop &lt;= 100000<br />BEGIN<br />   Set @PRID = NewID()<br />   Set @PRDesc = ' PerformanceIssue - ' + Convert( Varchar(10),@Loop )<br />   Insert Into PerformanceIssue Values (@PRID, @Loop, @PRDesc)<br />   Set @Loop = @Loop + 1<br />END<br /></p>
										</td>
								</tr>
						</tbody>
				</table>
				<p> </p>
				<p>脚本成功执行后，数据就添加进去了。 </p>
				<p>用下面语句来看一下表的内容： </p>
				<p> </p>
				<table style="TABLE-LAYOUT: fixed; BACKGROUND-COLOR: #f9f9f9" cellspacing="5" width="90%">
						<tbody>
								<tr>
										<td>
												<p style="FONT-SIZE: 14px; FONT-FAMILY: Verdana">Select PRID, PRCode, PRDesc<br />From PerformanceIssue<br />GO<br /></p>
										</td>
								</tr>
						</tbody>
				</table>
				<p> </p>
				<p>由于记录较长，因此这里就不列出查询结果了。 </p>
				<p>正如我前面讲到，我想解释何时会有“Table Scan”、“Index Scan”、“Index Seek”、“Clustered Index Scan”和“Clustered Index Seek”。上述哪个会改善性能呢？ </p>
				<p>当SQL Server返回数据时，我们想知道SQL Server采取何种扫描机制来协助获取数据。首先看一下“Table Scan”。我们想了解什么时候“Table Scan”会产生。 </p>
				<p>选择“显示执行计划”或者使用热键“Alt + Q”来激活“显示执行计划”，当然也可以用快捷键“Ctrl+K”。 </p>
				<p>看一下执行下面查询后的“执行计划”结果。 </p>
				<p> </p>
				<table style="TABLE-LAYOUT: fixed; BACKGROUND-COLOR: #f9f9f9" cellspacing="5" width="90%">
						<tbody>
								<tr>
										<td>
												<p style="FONT-SIZE: 14px; FONT-FAMILY: Verdana">Select PRID, PRCode, PRDesc <br />From PerformanceIssue<br />GO<br /></p>
										</td>
								</tr>
						</tbody>
				</table>
				<p>
						<img alt="" src="http://storage.msn.com/x1pKouN4nZmbX1GXt4PK3fT0r--wpY720dGZZbuMFWxNVrcS7Azc5Z2Ma0GIGoBAgH_VqKpZloe1E5kAOwpXw2b0xPrUxY9q5TbxrPEWtnJhs5rWpDwZYvAxDnEvC9HFuPFPyPvggmk8vp_5r-tOn27YQ" />
						<br />
				</p>
				<p>上面的“执行计划”中，SQL Server用到了“Table Scan”。我问自己为什么会有“Table Scan”，SQL Server是根据什么来使用该方法的。难道是因为我想获取所有100,000条记录吗？于是我换了一个角度进行思考，如果来避免查询中出现“Table Scan”呢？此时我对SQL Server的扫描机制还不是很清楚，那么该如何优化查询呢？下面的SELECT查询中仅选择两列：[PRID, PRCode]。 </p>
				<p> </p>
				<table style="TABLE-LAYOUT: fixed; BACKGROUND-COLOR: #f9f9f9" cellspacing="5" width="90%">
						<tbody>
								<tr>
										<td>
												<p style="FONT-SIZE: 14px; FONT-FAMILY: Verdana">Select PRID, PRCode<br />From PerformanceIssue<br />GO<br /></p>
										</td>
								</tr>
						</tbody>
				</table>
				<p>
						<img alt="" src="http://storage.msn.com/x1pCFuELfk4HG5HGNGsDSLDPMiFz7i0uCmiijlNOrj8gIv1Jn5k1ECnTvpigni4OUlBNAWuBUFCPZAB6cBi4xpqHixRnmu0RxT_OdKiVZ94_BTbfEcTcf0Cj_xvcLIPtdPa" />
						<br />
				</p>
				<p>查询执行后，执行计划和第一个查询一样。于是将查询改变为只检索一个字段 [PRID]。 </p>
				<p> </p>
				<table style="TABLE-LAYOUT: fixed; BACKGROUND-COLOR: #f9f9f9" cellspacing="5" width="90%">
						<tbody>
								<tr>
										<td>
												<p style="FONT-SIZE: 14px; FONT-FAMILY: Verdana">Select PRID <br />From PerformanceIssue<br /><br />GO<br /></p>
										</td>
								</tr>
						</tbody>
				</table>
				<p>
						<img alt="" src="http://storage.msn.com/x1pCFuELfk4HG5HGNGsDSLDPLG-5aH8sL29Nxtz7K-3BABZY54v5W9CkiCQDzg-pkTI_dM6OYrV6xnsm8upiR4nCXrEi4k0GdoIMap0KlqDqxeU2tKhRtBpEabPojERmq23t2qSZ3oi2Z4" />
						<br />
				</p>
				<p>查询执行后，执行计划仍然和第一个查询的相同。对“Estimated row size”属性不需要太大关注。意思我立刻决定只获取一条记录，看看执行计划会如何。查询语句如下： </p>
				<p> </p>
				<table style="TABLE-LAYOUT: fixed; BACKGROUND-COLOR: #f9f9f9" cellspacing="5" width="90%">
						<tbody>
								<tr>
										<td>
												<p style="FONT-SIZE: 14px; FONT-FAMILY: Verdana">Select PRID, PRCode, PRDesc <br />From PerformanceIssue<br />Where PRID = 'D386C151-5F74-4C2A-B527-86FEF9712955'<br />-- PRID GUID value might be differ in your machine<br /><br />GO<br /></p>
										</td>
								</tr>
						</tbody>
				</table>
				<p> </p>
				<p>执行完成后，执行计划显示： <img alt="" src="http://storage.msn.com/x1pCFuELfk4HG5HGNGsDSLDPOfXsUydrD1C1FSVJ6aeQ2FeoSCMyxjjeZ2ibnviincCMjPr41clDfQ3X8TkLgbHRl1-c7F8wV37bVHAyi28g0Yl5b8rPOqqWNPsaJY5_D7gYsHQ04xSOsI" /><br /></p>
				<p>查询仍然使用了“Table Scan”方法来显示数据。 </p>
				<p>那么，我需要想其它办法来避免“Table Scan”。首先我想到应该给表加上索引。于是我在PRID字段上创建非聚集索引。添加了索引后是否就能避免“Table Scan”？下面我们开始讨论关于“Index Scan”和“Index Seek”的主题。 </p>
		</div>
		<br />
		<div style="FONT-WEIGHT: bold; FONT-SIZE: 16px; COLOR: #446996; FONT-FAMILY: bookman old style">
				<p>Index Scan 和 Index Seek</p>
		</div>
		<div style="FONT-SIZE: 14px; FONT-FAMILY: Verdana">
				<p>首先在PRID字段上创建非聚集索引。 </p>
				<p> </p>
				<table style="TABLE-LAYOUT: fixed; BACKGROUND-COLOR: #f9f9f9" cellspacing="5" width="90%">
						<tbody>
								<tr>
										<td>
												<p style="FONT-SIZE: 14px; FONT-FAMILY: Verdana">CREATE UNIQUE NONCLUSTERED INDEX UNC_PRID<br />ON PerformanceIssue (PRID)<br />GO<br /></p>
										</td>
								</tr>
						</tbody>
				</table>
				<p> </p>
				<p>本文假定读者已经知道非聚集索引如何工作的知识。了解非聚集索引更详细的信息，请阅读BOL相关主题，也可参看 <a style="COLOR: #3366bb; TEXT-DECORATION: underline" href="http://www.sql-server-performance.com/gv_index_data_structures.asp">http://www.sql-server-performance.com/gv_index_data_structures.asp</a>。下面我们详细讲述“Index Scan”是如何工作的。 </p>
				<p>执行下面语句并查看执行计划的结果。 </p>
				<p> </p>
				<table style="TABLE-LAYOUT: fixed; BACKGROUND-COLOR: #f9f9f9" cellspacing="5" width="90%">
						<tbody>
								<tr>
										<td>
												<p style="FONT-SIZE: 14px; FONT-FAMILY: Verdana">Select PRID, PRCode, PRDesc <br />From PerformanceIssue<br />GO<br /></p>
										</td>
								</tr>
						</tbody>
				</table>
				<p>
						<img alt="" src="http://storage.msn.com/x1pCFuELfk4HG5HGNGsDSLDPCoCUSPrQg4fD3JME0db5bK42R_-O_qPCDpxa9F_Wx8V7AzVqxecLV4rvW3JYtIJnhaGuxeRJgWEGQ4BWf6mfeGstgsBiVi8ZZWwGQlj1VSWBYXSfW3AfD4" />
						<br />
				</p>
				<p>奇怪了，“Table Scan”仍然用到了。为什么SQL Server没有用到那个非聚集索引？于是继续优化查询语句，选择检索两个字段 [PRID, PRCode] 。 </p>
				<p> </p>
				<table style="TABLE-LAYOUT: fixed; BACKGROUND-COLOR: #f9f9f9" cellspacing="5" width="90%">
						<tbody>
								<tr>
										<td>
												<p style="FONT-SIZE: 14px; FONT-FAMILY: Verdana">Select PRID, PRCode From PerformanceIssue<br />GO<br /></p>
										</td>
								</tr>
						</tbody>
				</table>
				<p>
						<img alt="" src="http://storage.msn.com/x1pCFuELfk4HG5HGNGsDSLDPEgaLvZUGAukYKLci89vCemcX0tv_nMs9zfHFziEHW5c4Pe_mlIGnL4I4QK4DwYBtdxup-gCVclZrjdOk8UOJOolFxuASIqi5WNj215kc3gk_bQdGCxi5os" />
						<br />
				</p>
				<p>执行结果是和上一个查询结果一摸一样。于是修改查询为只检索一个字段 [PRID] 。 </p>
				<p> </p>
				<table style="TABLE-LAYOUT: fixed; BACKGROUND-COLOR: #f9f9f9" cellspacing="5" width="90%">
						<tbody>
								<tr>
										<td>
												<p style="FONT-SIZE: 14px; FONT-FAMILY: Verdana">Select PRID <br />From PerformanceIssue<br />GO<br /></p>
										</td>
								</tr>
						</tbody>
				</table>
				<p> </p>
				<p>执行计划结果如下： <img alt="" src="http://storage.msn.com/x1pCFuELfk4HG5HGNGsDSLDPECpnrZ_vTjwQLkWlcxZPRjQ_pkWpHfwKytCF6eyAt8idnUVN8T9fSi-XWb8trmi_anBAWbVGuFLzQ7UB1h9zymdvaWrMM1_BMsmE7IamGEn" /><br /></p>
				<p>“Index Scan”在查询中被用到了，这很好。很自然，接下来的问题就是“Index Scan”什么时候会被用到。字段PRID上有一个索引，查询语句中选中的字段为PRID。执行查询的时候，SQL Server扫描索引页，因此用到了“Index Scan”方法。前面的查询中选择了有索引的和没有索引的字段，SQL Server无法使用“Index Scan”。当查询中只选择有索引的字段时，SQL Server就使用了“Index Scan”。我不清楚SQL Server底层到底是如何判断的，不过通过这些试验，我认为<strong>当查询中只选择有索引的字段时，SQL Server就使用“Index Scan”方法</strong>。 </p>
				<p>下面看“Index Seek”方法何时产生。当我看到“Seek”这个词时，第一反应就是条件查询这个主意。 </p>
				<p>我尝试三种不同的带WHERE语法的查询语句，以找出那种会用“Index Seek”。第一种语句如下： </p>
				<p> </p>
				<table style="TABLE-LAYOUT: fixed; BACKGROUND-COLOR: #f9f9f9" cellspacing="5" width="90%">
						<tbody>
								<tr>
										<td>
												<p style="FONT-SIZE: 14px; FONT-FAMILY: Verdana">Select PRID, PRCode, PRDesc <br />From PerformanceIssue<br />Where PRCode = 8<br />GO<br /></p>
										</td>
								</tr>
						</tbody>
				</table>
				<p> </p>
				<p>结果显示，执行计划使用了“Table Scan”。 <img alt="" src="http://storage.msn.com/x1pCFuELfk4HG5HGNGsDSLDPO7xKCivdj-jOyVcx2aDCGldX24PlZGmjJwz2GE-4i0s4O7zu-YfhsWheDF56FahtCW0eUtJYMU95V4Q90B1pb12nBygJRHdZDlpoqvg4v-4yJeINu58bSE" /><br /></p>
				<p>第二种语句如下： </p>
				<p> </p>
				<table style="TABLE-LAYOUT: fixed; BACKGROUND-COLOR: #f9f9f9" cellspacing="5" width="90%">
						<tbody>
								<tr>
										<td>
												<p style="FONT-SIZE: 14px; FONT-FAMILY: Verdana">Select PRID, PRCode, PRDesc<br />From PerformanceIssue<br />Where PRDesc = ' PerformanceIssue - 8'<br />GO<br /></p>
										</td>
								</tr>
						</tbody>
				</table>
				<p> </p>
				<p>执行计划仍然使用“Table Scan”方法。 <img alt="" src="http://storage.msn.com/x1pCFuELfk4HG5HGNGsDSLDPAzaPv7d-XVFQyIwu1Xcw77VlXeFlCcHdrfA-HIArHnVYfktaE2dvhFwRWD1DJwQypJCzjWQ_3VpH0shc6AaSDoHBAvRd2xDgxpkieOsp5lLj04NctGY_pk" /><br /></p>
				<p>第三种查询语句如下： </p>
				<p> </p>
				<table style="TABLE-LAYOUT: fixed; BACKGROUND-COLOR: #f9f9f9" cellspacing="5" width="90%">
						<tbody>
								<tr>
										<td>
												<p style="FONT-SIZE: 14px; FONT-FAMILY: Verdana">Select PRID, PRCode, PRDesc<br />From PerformanceIssue <br />Where PRID = 'D386C151-5F74-4C2A-B527-86FEF9712955'<br /><br />-- PRID GUID value might be differ in your machine<br />GO<br /></p>
										</td>
								</tr>
						</tbody>
				</table>
				<p>
						<img alt="" src="http://storage.msn.com/x1pKouN4nZmbX1GXt4PK3fT0r--wpY720dGZZbuMFWxNVqxYdUionwLHWHD8vUHVSjWgvg7oO9T287kDJqT9O9n_zoynukEc0ECt2JJrnqCr-kzV-Msh0LL4SOsoOKRsJipLJO6h42nAPAcmAntW8MY8A" />
						<br />
						<img alt="" src="http://storage.msn.com/x1pKouN4nZmbX1GXt4PK3fT0r--wpY720dGZZbuMFWxNVrrQxklltiGyTf5BxTGBESvgNvahm7UNkT3lojLP4dwT0XnA3SJY9gcTjUnYAXjZiJGmV4aq4yKlqA6oC7kvp9OaJt2-m4yW7Xl8C6bclil3g" />
						<br />
				</p>
				<p>查询用到了“Index Seek”和“Bookmark Lookup”方法。用到“Index Seek”是因为WHERE后面使用带索引的字段PRID来进行过滤。“Bookmark Lookup”方法被用到是因为查询中选择了没有索引的字段。如果去掉这两个没有索引的字段，那么“Bookmark Lookup”方法就可以去掉。当然如果只返回PRID字段，那么该查询就没什么意义了，因为WHERE语句后面已经给出PRID具体取值了。 </p>
				<p>我认为“Index Seek”在性能改善上比“Index Scan”和“Table Scan”要好，这主要表现在下面几个方面： </p>
				<p> </p>
				<ol>
						<li>“Index Seek”不需要对表和索引页进行扫描；而“Table Scan”和“Index Scan”需要。 
</li>
						<li>“Index Seek”利用“WHERE”来过滤获取的数据，这样比用“Index Scan”和“Table Scan”快很多。 </li>
				</ol>
				<p> </p>
				<p>当我完成这些测试后，我同事问我一个很有意思的问题：SQL Server什么时候使用“Clustered Index Scan”和“Clustered Index Seek”？下面对“Clustered Index Scan”和“Clustered Index Seek”进行实验。 </p>
				<p>我决定在PRCode上建一个聚集索引来测试“Clustered Index Scan”和“Clustered Index Seek”。 </p>
		</div>
		<br />
		<div style="FONT-WEIGHT: bold; FONT-SIZE: 16px; COLOR: #446996; FONT-FAMILY: bookman old style">
				<p>Clustered Index Scan &amp; Clustered Index Seek</p>
		</div>
		<div style="FONT-SIZE: 14px; FONT-FAMILY: Verdana">
				<p>下面的脚本删除PRID字段上的索引，并在PRCode字段上创建聚集索引。 </p>
				<p> </p>
				<table style="TABLE-LAYOUT: fixed; BACKGROUND-COLOR: #f9f9f9" cellspacing="5" width="90%">
						<tbody>
								<tr>
										<td>
												<p style="FONT-SIZE: 14px; FONT-FAMILY: Verdana">Drop Index PerformanceIssue.UNC_PRID<br />GO<br />CREATE UNIQUE CLUSTERED INDEX UC_PRCode<br />ON PerformanceIssue( PRCode)<br />GO<br />-------------<br />Clustered index has been created successfully. <br />Index has been created. <br /></p>
										</td>
								</tr>
						</tbody>
				</table>
				<p> </p>
				<p>关于聚集索引的基础知识请查阅联机帮助的相关主题或者 <a style="COLOR: #3366bb; TEXT-DECORATION: underline" href="http://www.sql-server-performance.com/gv_index_data_structures.asp">http://www.sql-server-performance.com/gv_index_data_structures.asp</a>。下面我们将重点放在“Clustered Index Scan”和“Clustered Index Seek”如何被使用上。 </p>
				<p>执行下面查询语句： </p>
				<p> </p>
				<table style="TABLE-LAYOUT: fixed; BACKGROUND-COLOR: #f9f9f9" cellspacing="5" width="90%">
						<tbody>
								<tr>
										<td>
												<p style="FONT-SIZE: 14px; FONT-FAMILY: Verdana">Select PRID, PRCode, PRDesc <br />From PerformanceIssue<br />GO<br /></p>
										</td>
								</tr>
						</tbody>
				</table>
				<p> </p>
				<p>查询执行后，可以看到执行计划中用到了“Clustered Index Scan”。 <img alt="" src="http://storage.msn.com/x1pKouN4nZmbX1GXt4PK3fT0r--wpY720dGZZbuMFWxNVo8iwWBhKv4u5Sw1FAP_nQFRvmIeGcndLdC-ra--h7xXWPh8A5OG9q4AG_d-4pfEAy-9r2u4zjDBRcqIcfW9GeNn-S6YGgTgEA2Hv5k2KjSlw" /><br /></p>
				<p>下面用三种不同的WHERE方式来试验何时SQL Server会用到“Clustered Index Seek”。第一种形式如下： </p>
				<p> </p>
				<table style="TABLE-LAYOUT: fixed; BACKGROUND-COLOR: #f9f9f9" cellspacing="5" width="90%">
						<tbody>
								<tr>
										<td>
												<p style="FONT-SIZE: 14px; FONT-FAMILY: Verdana">Select PRID, PRCode, PRDesc <br />From PerformanceIssue<br />Where PRDesc = ' PerformanceIssue - 8'<br />GO<br /></p>
										</td>
								</tr>
						</tbody>
				</table>
				<p> </p>
				<p>查询执行后，可以看到执行计划中用到了“Clustered Index Scan”。 <img alt="" src="http://storage.msn.com/x1pKouN4nZmbX1GXt4PK3fT0r--wpY720dGZZbuMFWxNVovLmEmg5zIv3glKD8cPzNVSM8-OpJnfYtBniwcDxQ22y9huT4t8lQIqUDmbcV8AWAUXcaHRjPQ2mwBSrYYAt-sAHtumbjAXVPp46hrH6UMAg" /><br /></p>
				<p>第二种形式如下： </p>
				<p> </p>
				<table style="TABLE-LAYOUT: fixed; BACKGROUND-COLOR: #f9f9f9" cellspacing="5" width="90%">
						<tbody>
								<tr>
										<td>
												<p style="FONT-SIZE: 14px; FONT-FAMILY: Verdana">Select PRID, PRCode, PRDesc <br />From PerformanceIssue<br />Where PRID = 'D386C151-5F74-4C2A-B527-86FEF9712955'<br /><br />-- PRID GUID value might be differ in your machine<br />GO<br /></p>
										</td>
								</tr>
						</tbody>
				</table>
				<p> </p>
				<p>查询执行后，发现执行计划中用到的仍然是“Clustered Index Scan”。 <img alt="" src="http://storage.msn.com/x1pCFuELfk4HG5HGNGsDSLDPP60MRclO6irF7ZHVVGC0exOPjcE6CsADIh4AfOA7Z5XgryTWLkLYmQWO0njMvGzvQOftUkf2Z76W5YHo4bCnkoF9rHU9SG5YYnNlvBI77-e" /><br /></p>
				<p>第三种形式： </p>
				<p> </p>
				<table style="TABLE-LAYOUT: fixed; BACKGROUND-COLOR: #f9f9f9" cellspacing="5" width="90%">
						<tbody>
								<tr>
										<td>
												<p style="FONT-SIZE: 14px; FONT-FAMILY: Verdana">Select PRID, PRCode, PRDesc <br />From PerformanceIssue<br />Where PRCode = 8<br />GO<br /></p>
										</td>
								</tr>
						</tbody>
				</table>
				<p> </p>
				<p>这次执行计划用到了“Clustered Index Seek”。 <img alt="" src="http://storage.msn.com/x1pCFuELfk4HG5HGNGsDSLDPMFx5_Sy-R7OUDGT7WugYZScvUGO7EaJjirFPcXZSIrUHP-cJjwj8Vpk9z2A956NMIr5RBpIkXgUCpniZoAXdOMvxe6-o_Ymp9pr02gkthJMaRtjjpg6Fqk" /><br /></p>
				<p>当在WHERE后用到PRCode字段的时候，“Clustered Index Seek”被用到。执行计划对聚集索引表检索的时候，因为在选取的字段中，包括没有索引的字段，所以不用用到“Bookmark Lookup”方法。 </p>
				<p>我个人认为，从改善性能角度考虑，“Clustered Index Seek”比“Clustered Index Scan”和“Index Seek”要好。 </p>
				<p> </p>
				<ol>
						<li>“Clustered Index Seek”不需要扫描整个聚集索引页。 
</li>
						<li>和“Index Scan”相比，对于检索选择的字段包含那些没有索引的字段时，“Clustered Index Seek”不会有“Bookmark Lookup”方法出现。 </li>
				</ol>
				<p> </p>
				<p>通过这些试验，我对执行计划的应用积累了实际经验。我知道哪种扫描机制可以提高性能，从而是的客户满意。</p>
				<p> </p>
		</div>
<img src ="http://www.blogjava.net/jiabao/aggbug/191595.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jiabao/" target="_blank">金家寶</a> 2008-04-08 23:38 <a href="http://www.blogjava.net/jiabao/archive/2008/04/08/191595.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>