SQL Server sproc查询优化

时间:2010-02-11 16:49:25

标签: sql-server stored-procedures sql-optimization

我有一个应用程序可以为报告生成数据:

                    age < 30   | age >=30  |   asian   | hispanic
-----------------------------------------------------------------
clients in prog A              |          |           |
-----------------------------------------------------------------
clients in prog B              |          |           |
-----------------------------------------------------------------
number clients                 |          |           |
-----------------------------------------------------------------
number children                |          |           |

查询有时非常长,我想优化它们。

我没有在服务器上运行查询分析器的权限(我读到它通常更好使用它的建议)。最长的sprocs需要大约35秒才能执行。

阅读,高度查询优化要避免的事情是:

  • 选择*
  • 存在
  • 不同
  • 游标
  • 具有

我对手头的任务有几个疑问:

  • 通过将Select *更改为Select colA,colB ...,我看到了多少差异?这真的值得吗?
  • 如果存在(...)我该如何优化? if(选择计数(查询)&gt; 0)是否是一个很好的优化?
  • 如果我真的要在表格中返回所有列,是否可以使用Select *?

我不想发布这些查询,因为它们太长而且非常糟糕,但您可以提供哪些其他建议?我试图尽可能使用可重复使用的功能和临时表来缓解我的大脑和服务器上的压力。

5 个答案:

答案 0 :(得分:1)

您可以发布查询

这里只是一些指示,因为你没有显示任何代码

一般存在比count(*)更快,因为exists返回它找到匹配的那一刻,其中count()将继续,直到它到达结果集的末尾

选择col1,col2优于select *,因为如果列在非聚簇索引中,则甚至不会触及基表/聚簇索引,现在您已经在索引中包含了列,这更是如此。如果只返回所需的列

,您也将使用更少的带宽
  

如果我真的要返回表中的所有列,是否可以使用Select *?

如果有人稍后在表中添加4列会怎么样?现在,您将返回这4列

答案 1 :(得分:1)

1)通过将Select *更改为Select colA,colB ...,我看到了多少差异?这真的值得吗?
这可以产生很大的不同 - 一般来说,指定所需的字段并且仅指定那些字段总是好的做法。也就是说,如果你只需要其中的2个就执行SELECT *返回50个字段,并且这2个字段包含在合适的索引中,那么所有数据都可以从索引中提供,而无需查找其余的数据。数据页面。所以这要好得多。

2)如果存在(...)我该如何优化? if(选择计数(查询)&gt; 0)是否是一个很好的优化?
不... SELECT COUNT()更糟糕。 EXISTS 执行此类操作的最佳方式,因为它经过优化,可在找到第一个匹配记录后立即停止检查。而COUNT()将继续前进,而发现它们都是不必要的。我不会在游戏中用游标对“EXISTS”进行分类。

3)如果我真的要返回表中的所有列,是否可以使用Select *?
好吧,如果你真的想要它们,那么它并不重要。假设您希望将来添加更多列,那么您还希望返回这些列,如果它突然发生变化,可能会破坏现有代码。

答案 2 :(得分:1)

  

我正在尝试尽可能使用可重复使用的功能和临时表来缓解我的大脑和服务器上的压力

假设您的意思是用户定义的功能,它们并不总是对性能有益。寻求缓解大脑的压力可能会增加服务器的压力。纯粹标量的那些(即它们取值,操纵它并返回另一个值)应该没问题,但扫描表的那些通常可以在它们的逻辑直接用于存储过程时更快地运行。例如,一个扫描表X中出现值Y并返回计数的函数将比包含可以一次完成每个值计数的连接的SQL语句运行得慢(因为重复调用它)。

您还应该检查相关源表上是否有索引以及是否正在使用它们。

答案 3 :(得分:0)

从Select *更改为Select column1,column2,您将无法获得更多好处。但是,您应该这样做,因为它是良好的编码。如果有人在将来更改了列顺序或列数,则可能会导致报告中断,具体取决于它们的构建方式。

另一种方法怎么样?如果您能够在表上添加非聚集索引,我建议您进行调查。具体来说,查看您现有的子查询,看看Where部分中的列是否有索引。如果它们没有,那么每次exists返回false时你都会进行表扫描,并且你每次都可以进行表扫描,即使它返回true(它取决于值的位置)。非聚集索引将允许子查询快速查找表中的任何结果。有时您必须使用低效的查询,但如果您可以通过索引优化表结构,那么它对您的速度的影响就会小得多。

此外,对于您的存在子查询,您最多会得到1个结果?如果是这样,那么您可能想尝试对表进行左连接。如果你在连接的左边和右边的两个列集上没有索引,这可能没有用,但如果你这样做应该非常有用,因为你基本上扫描你的右手表1次而不是每行一次

答案 4 :(得分:0)

对于计数,最有效的形式是SELECT Count(1)FROM table。 (或0或123或任何简单的常数值)。

您也应该更改为SELECT field1,field2,..以便管理。 SELECT *较慢,稍后当代码,视图或表(或更多)更改时,您可能会遇到问题。