⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 44253.htm

📁 一本很基础的SQL讲解
💻 HTM
📖 第 1 页 / 共 2 页
字号:
<link href="./dzs_cs.css" rel="stylesheet" type="text/css" /><table width="96%" border="0" align="center" cellpadding="0" cellspacing="0">      <tr>        <td>&nbsp;</td>      </tr>      <tr>        <td height="24" align="center" valign="bottom" class="d_font3">理解SQL Server的SQL查询计划</td>      </tr>      <tr>        <td height="3" bgcolor="#E3E3E3"></td>      </tr>      <tr>        <td>&nbsp;</td>      </tr>      <tr>        <td class="d_font4"><P><STRONG>入门指南</STRONG></P>
<P>让我们以一个简单的例子帮助你理解如何阅读查询计划,可以通过发出SET SHOWPLAN_TEXT On命令,或者在SQL Query Analyzer 的配置属性中设置同样的选项等方式得到查询计划。 </P>
<P><STRONG>注意</STRONG>:这个例子使用了表pubs.big_sales,该表与pubs..sales表完全相同,除了多了80000行的记录,以当作简单explain plan例子的主要数据。</P>
<P>如下所示,这个最简单的查询将扫描整个聚集索引,如果该索引存在。注意聚集键值是物理次序,数据按该次序存放。所以,如果聚集键值存在,你将可能避免对整个表进行扫描。即使你所选的列不在聚集键值中,例如ord_date,这个查询引擎将用索引扫描并返回结果集。</P>
<P>
<TABLE cellSpacing=0 borderColorDark=#ffffff cellPadding=2 width=400 align=center borderColorLight=black border=1>
<TBODY>
<TR>
<TD class=code bgColor=#e6e6e6><PRE><P>&nbsp; SELECT *<BR>&nbsp; FROM big_sales</P><P>&nbsp; SELECT ord_date<BR>&nbsp; FROM big_sales</P><P>&nbsp; StmtText<BR>&nbsp;&nbsp; -------------------------------------------------------------------------<BR>&nbsp; |--ClusteredIndexScan(OBJECT:([pubs].[dbo].[big_sales].[UPKCL_big_sales]))</P></PRE></TD></TR></TBODY></TABLE></P>
<P>上面的查询展示返回的数据量非常不同,所以小结果集(ord_date)的查询比其它查询运行更快,这只是因为存在大量底层的I/O。然而,这两个查询计划实际上是一样的。你可以通过使用其它索引提高性能。例如,在title_id列上有一个非聚集索引存在:</P>
<P>
<TABLE cellSpacing=0 borderColorDark=#ffffff cellPadding=2 width=400 align=center borderColorLight=black border=1>
<TBODY>
<TR>
<TD class=code bgColor=#e6e6e6><PRE><P>&nbsp;SELECT title_id<BR>&nbsp;FROM big_sales</P><P>&nbsp;StmtText<BR>&nbsp; ------------------------------------------------------------------<BR>&nbsp; |--Index Scan(OBJECT:([pubs].[dbo].[big_sales].[ndx_sales_ttlID]))</P></PRE></TD></TR></TBODY></TABLE></P>
<P>上面的查询的执行时间与SELECT *查询相比非常小,这是因为可以从非聚集索引即可得到所有结果。该类查询被称为covering query(覆盖查询),因为全部结果集被一个非聚集索引所覆盖。</P>
<P><STRONG>SEEK与SCAN</STRONG></P>
<P>第一件事是你需要在查询计划中区别SEEK和SCAN操作的不同。 </P>
<P><STRONG>注意</STRONG>:一个简单但非常有用的规则是SEEK操作是有效率的,而SCAN操作即使不是非常差,其效率也不是很好。SEEK操作是直接的,或者至少是快速的,而SCAN操作需要对整个对象进行读取(表,聚集索引或非聚集索引)。因此,SCAN操作通常比SEEK要消耗更多的资源。如果你的查询计划仅是扫描操作,你就应该考虑调整你的查询了。 </P>
<P>where子句在查询性能中能产生巨大的差异,如下面展示的: </P>
<P>
<TABLE cellSpacing=0 borderColorDark=#ffffff cellPadding=2 width=400 align=center borderColorLight=black border=1>
<TBODY>
<TR>
<TD class=code bgColor=#e6e6e6><PRE><P>&nbsp; Select *<BR>&nbsp; From big_sales<BR>&nbsp; Where stor_id=’6380’</P><P>&nbsp; StmtText<BR>&nbsp; -----------------------------------------------------------------------------|--Clustered<BR>&nbsp; Index Seek(OBJECT: ([pubs].[dbo].[big_sales].[UPKCL_big_sales])),</P><P>    SEEK: ([big_sales].[stor_id]={@1} ORDERED FORWARD)</P></PRE></TD></TR></TBODY></TABLE></P>
<P>上面的查询是在聚集索引上执行SEEK而不是SCAN操作。这个SHOWPLAN确切的描述SEEK操作是基于stor_id并且结果是按照在索引中存储的顺序排序的。因为SQL Server支持索引的向前和向后滚动的性能是相同的,所以你可以在查询计划中看到ORDERED FORWARD 或ORDERED BACKWARD。这只是告诉你表或索引读取的方向。你甚至可以在ORDER BY子句中通过用ASC和DESC关键字操作这些行为。范围查询返回的查询计划,与前面的直接查询的查询计划很相似。下面两个范围查询可提供一些信息:</P>
<P>
<TABLE cellSpacing=0 borderColorDark=#ffffff cellPadding=2 width=400 align=center borderColorLight=black border=1>
<TBODY>
<TR>
<TD class=code bgColor=#e6e6e6><PRE><P>&nbsp; Select *<BR>&nbsp; From big_sales<BR>&nbsp; Where stor_id&gt;=’7131’</P><P>&nbsp; StmtText<BR>&nbsp; ------------------------------------------------------------------------------|-Clustered<BR>&nbsp; Index Seek(OBJECT: ([pubs].[dbo].[big_sales].[UPKCL_big_sales] ),</P><P>    SEEK: ([big_sales].[stor_id]&gt;=’7131’) ORDER FORWARD </P></PRE></TD></TR></TBODY></TABLE></P>
<P>上面的查询看起来很象以前的例子,除了SEEK谓词有点不同。</P>
<P>
<TABLE cellSpacing=0 borderColorDark=#ffffff cellPadding=2 width=400 align=center borderColorLight=black border=1>
<TBODY>
<TR>
<TD class=code bgColor=#e6e6e6><PRE><P>&nbsp; Select *<BR>&nbsp; From big_sales<BR>&nbsp; Where stor_id between ‘7066’ and ‘7131’</P><P>&nbsp; StmtText<BR>&nbsp;&nbsp; ------------------------------------------------------------------------------|-Clustered<BR>&nbsp;&nbsp; Index Seek(OBJECT: ([pubs].[dbo].[big_sales].[UPKCL_big_sales] ),</P><P>   SEEK:([big_sales].[stor_id]&gt;=’7066’ and ([big_sales].[stor_id]&lt;=’7131’) ORDER FORWARD)</P></PRE></TD></TR></TBODY></TABLE></P>
<P>这个看起来也一样。只是查找谓词改变了。因为查找是非常快的,所以这个查询是相当好的。</P>
<P>SEEK和SCAN也可包含Where谓词。在这种情况下,这个谓词告诉你Where子句从结果集中过滤出哪些记录。因为它是作为SEEK或SCAN的一个组件执行的, Where子句通常既不损害也不提高这个操作本身的性能。Where子句会帮助查询优化器找到可能有最佳性能的索引。</P>
<P>查询优化的一个重要部分是要确定是否在某个索引上执行SEEK操作,如果是这样,就找到了具有最佳性能的索引。大部分情况下,查询引擎能出色地查找到存在的索引。但是,目前有三种涉及到索引的常见问题: </P>
<P>◆数据库设计师,通常是应用开发者,在表中没有建立任何索引。 <BR>◆数据库设计师通常猜测不到常用的查询或事务类型,所以建立在表上的索引或主键往往效率不高。 <BR>◆当索引表被创建时,即使数据库设计师猜测较准,但事务负载随着时间将发生改变,使得这些索引效率变差。</P>
<P>如果你在你的查询计划中看到大量的SCAN而不是SEEK,你应该从新评估你的索引。例如,看看下面的查询: </P>
<P>
<TABLE cellSpacing=0 borderColorDark=#ffffff cellPadding=2 width=400 align=center borderColorLight=black border=1>
<TBODY>
<TR>
<TD class=code bgColor=#e6e6e6><PRE><P>&nbsp;Select ord_num<BR>&nbsp;From sales<BR>&nbsp;Where ord_date IS NOT NUL<BR>&nbsp;And ord_date&gt;’Jan 01,2002 12:00:00 AM’<BR>&nbsp; StemtText<BR>&nbsp; ----------------------------------------------------------------------------------|--<BR>&nbsp; Clustered Index Scan(OBJECT: ([pubs].[dbo].[sales].[UPKCL_sales] ),</P><P>    WHERE : ([sales].[ord_date]&gt;’Jan 1,2002 12:00:00 AM ’))</P></PRE></TD></TR></TBODY></TABLE></P>
<P>现在这个查询在我们刚创建的sales_ord_date索引上执行SEEK INDEX操作。</P>
<P>【文章相关内容】</P>
<P><STRONG>第一页</STRONG>:<A href="http://developer.51cto.com/art/200704/44253.htm"><FONT color=#0000ff>入门指南</FONT></A></P>
<P><STRONG>第二页</STRONG>:<A href="http://developer.51cto.com/art/200704/44253_1.htm"><FONT color=#0000ff>通过比较连接和子查询说明分支步骤</FONT></A>&nbsp;&nbsp; </P>
<P><STRONG>第三页</STRONG>:<A href="http://developer.51cto.com/art/200704/44253_2.htm"><FONT color=#0000ff>三种join(连接)策略</FONT></A></P>
<P>#p#</P>
<P><STRONG>通过比较连接和子查询说明分支步骤</STRONG></P>
<P>一条正确的老规则是:在结果集相同的情况下,连接比子查询具有更好的性能。 </P>
<P>
<TABLE cellSpacing=0 borderColorDark=#ffffff cellPadding=2 width=400 align=center borderColorLight=black border=1>
<TBODY>
<TR>

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -