0

我有一个应用程序可以为报告生成数据,如下所示:

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

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

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

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

  • 选择 *
  • 存在
  • 清楚的
  • 游标

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

  • 通过将 Select * 更改为 Select colA, colB ... ,我看到了多少差异?真的值得麻烦吗?
  • 如果存在(...),我该如何优化?if(Select Count(query) > 0) 是一个很好的优化吗?
  • 如果我真的要返回表中的所有列,可以使用 Select * 吗?

我不想发布这些查询,因为它们又长又可怕,但是您还能提供哪些其他建议?我正在尝试尽可能使用可重复使用的函数和临时表来减轻我的大脑和服务器上的压力。

4

5 回答 5

1

你可以发布查询

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

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

select col1, col2 比 select * 好,因为如果列在非聚集索引中,则基表/聚集索引甚至不会被触及,现在您已将列包含在索引中,这一点就更真实了。如果您只返回您需要的列,您还将使用更少的带宽

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

如果有人稍后在表格中添加 4 列怎么办?现在您还将返回这 4 列

于 2010-02-11T16:56:11.907 回答
1

1)通过将 Select * 更改为 Select colA, colB ... ,我看到了多少不同?真的值得麻烦吗?
这可能会产生很大的不同 - 通常指定您想要的字段并且仅指定这些字段始终是一种好习惯。即,如果您只需要 2 个字段时执行 SELECT * 以返回 50 个字段,并且这 2 个字段包含在合适的索引中,则可以从索引中提供所有数据,而无需查找其余数据数据页。所以这要好得多。

2)如果存在(...),我该如何优化?if(Select Count(query) > 0) 是一个很好的优化吗?
不... SELECT COUNT() 更糟。EXISTS执行此类操作的最高效方式,因为它经过优化,可以在找到第一个匹配记录后立即停止检查。而 COUNT() 将继续运行,直到找到它们都是不必要的。我根本不会用光标将“EXISTS”归类为坏营地。

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

于 2010-02-11T16:57:27.160 回答
1

我正在尝试尽可能使用可重复使用的函数和临时表来减轻我的大脑和服务器上的压力

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

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

于 2010-02-11T17:10:51.853 回答
0

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

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

此外,对于您的 Exists 子查询,您是否会得到最多 1 个结果?如果是这样,那么您可能想尝试对表进行左连接。如果您不在连接左侧和右侧的列集上都没有索引,那可能无济于事,但如果这样做应该会很有帮助,因为您基本上会扫描右手表 1 次而不是每行一次.

于 2010-02-11T17:04:43.303 回答
0

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

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

于 2010-02-11T17:11:07.770 回答