44042.htm
来自「一本很基础的SQL讲解」· HTM 代码 · 共 89 行 · 第 1/2 页
HTM
89 行
<link href="./dzs_cs.css" rel="stylesheet" type="text/css" /><table width="96%" border="0" align="center" cellpadding="0" cellspacing="0"> <tr> <td> </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> </td> </tr> <tr> <td class="d_font4"><P>在这部分里我们所有的例子都选择使用Microsoft SHOWPLAN_ALL输出,因为它更紧凑并且展示典型的信息。(Sybase的查询计划基本与此相同,可能包含其它一些信息)大部分的例子都是要么基于PUBS数据库,要么基于标准系统表的。我们在PUBS数据库中对用到的表进行了很大扩充,对很多表增加了好几万行。</P>
<P><STRONG>子查询优化</STRONG></P>
<P>一条好的值得称赞的规则是尽量用连接代替所有的子查询。优化器有时可以自动将子查询“扁平化”,并且用常规或外连接代替。但那样也不总是有效。明确的连接对选择表的顺序和找到最可能的计划给出了更多的选项。当你优化一个特殊查询时,了解一下是否去掉自查询可产生很大的差异。</P>
<P><STRONG>示例</STRONG></P>
<P>下面查询选择了pubs数据库中所有表的名字,以及每个表的聚集索引(如果存在)。如果没有聚集索引,表名仍然显示在列表中,在聚集索引列中显示为虚线。两个查询返回同样的结果集,但第一个使用了一个子查询,而第二个使用一个外连接时。比较Microsoft SQL Server产生的查询计划:</P>
<P><A href="/files/uploadimg/20070330/1740050.jpg" target=_blank><IMG height=253 alt="" src="/files/uploadimg/20070330/1740050.jpg" width=450 border=0></A> </P>
<P><A href="/files/uploadimg/20070330/1740051.jpg" target=_blank><IMG height=235 alt="" src="/files/uploadimg/20070330/1740051.jpg" width=450 border=0></A> </P>
<P>不必更深探索,我们可以看到在CPU和总的实耗时间方面连接更快,仅需要子查询方案逻辑读的一半。此外,这两种情况伴随着相同的结果集,虽然排序的顺序不同,这是因为连接查询(由于它的GROUP BY子句)有一个隐含的ORDER BY:</P>
<P><A href="/files/uploadimg/20070330/1740052.jpg" target=_blank><IMG height=476 alt="" src="/files/uploadimg/20070330/1740052.jpg" width=275 border=0></A> </P>
<P>查看这个子查询方法展示的查询计划:</P>
<P><A href="/files/uploadimg/20070330/1740053.jpg" target=_blank><IMG height=333 alt="" src="/files/uploadimg/20070330/1740053.jpg" width=431 border=0></A> </P>
<P>#p# </P>
<P>反之,求和查询操作我们可以得到:</P>
<P><A href="/files/uploadimg/20070330/1740054.jpg" target=_blank><IMG height=379 alt="" src="/files/uploadimg/20070330/1740054.jpg" width=399 border=0></A> </P>
<P>使用连接是更有效的方案。它不需要额外的流聚合(stream aggregate),即子查询所需在big_sales.qty列的求和。</P>
<P><STRONG>UNION vs UNION ALL</STRONG></P>
<P>无论何时尽可能用UNION ALL 代替UNION。其中的差异是因为UNION有排除重复行并且对结果进行排序的副作用,而UNION ALL不会做这些工作。选择无重复行的结果需要建立临时工作表,用它排序所有行并且在输出之前排序。(在一个select distinct 查询中显示查询计划将发现存在一个流聚合,消耗百分之三十多的资源处理查询)。当你确切知道你得需要时,可以使用UNION。但如果你估计在结果集中没有重复的行,就使用UNION ALL吧。它只是从一个表或一个连接中选择,然后从另一个表中选择,附加在第一条结果集的底部。UNION ALL不需要工作表和排序(除非其它条件引起的)。在大部分情况下UNION ALL更具效率。一个有潜在危险的问题是使用UNION会在数据库中产生巨大的泛滥的临时工作表。如果你期望从UNION查询中获得大量的结果集时,这就可能发生。</P>
<P><STRONG>示例</STRONG></P>
<P>下面的查询是选择pubs数据库中的表sales的所有商店的ID,也选择表big_sales中的所有商店的ID,这个表中我们加入了70,000多行数据。在这两个方案间不同之处仅仅是UNION 与UNION ALL的使用比较。但在这个计划中加入ALL关键字产生了三大不同。第一个方案中,在返回结果集给客户端之前需要流聚合并且排序结果。第二个查询更有效率,特别是对大表。在这个例子中两个查询返回同样的结果集,虽然顺序不同。在我们的测试中有两个临时表。你的结果可能会稍有差异。</P>
<P><A href="/files/uploadimg/20070330/1740055.jpg" target=_blank><IMG height=472 alt="" src="/files/uploadimg/20070330/1740055.jpg" width=450 border=0></A> </P>
<P><A href="/files/uploadimg/20070330/1740056.jpg" target=_blank><IMG height=202 alt="" src="/files/uploadimg/20070330/1740056.jpg" width=450 border=0></A> </P>
<P>虽然在这个例子的结果集是可互换的,你可以看到UNION ALL语句比UNION语句少消耗一半的资源。所以应当预料你的结果集并且确定已经没有重复时,使用UNION ALL子句。</P>
<P>#p# </P>
<P><STRONG>函数和表达式约束索引</STRONG></P>
<P>当你在索引列上使用内置的函数或表达式时,优化器不能使用这些列的索引。尽量重写这些条件,在表达式中不要包含索引列。</P>
<P><STRONG>示例</STRONG></P>
<P>你应该帮助SQL Server移除任何在索引数值列周围的表达式。下面的查询是从表jobs通过唯一的聚集索引的唯一键值选择出的一行。如果你在这个列上使用表达式,这个索引就不起作用了。但一旦你将条件’job_id-2=0’ 该成‘job_id=2’,优化器将在聚集索引上执行seek操作。</P>
<P><A href="/files/uploadimg/20070330/1740057.jpg" target=_blank><IMG height=260 alt="" src="/files/uploadimg/20070330/1740057.jpg" width=450 border=0></A> </P>
<P>下面表中列出了多种不同类型查询示例,其被禁止使用列索引,同时给出改写的方法,以获得更优的性能。</P>
<P><A href="/files/uploadimg/20070330/1740058.jpg" target=_blank><IMG height=458 alt="" src="/files/uploadimg/20070330/1740058.jpg" width=450 border=0></A></P>
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?