我能在执行存储过程之前获取行数吗?

5

我有一些复杂的存储过程,可能会返回成千上万行数据,并且需要很长时间才能完成。

在查询执行和获取数据之前,有没有办法找出将返回多少行?

这是使用 Visual Studio 2005、Winforms 应用程序和 SQL Server 2005。

11个回答

6
你提到存储过程需要很长时间才能完成。大部分时间是在从数据库中选择行还是将行返回给调用者的过程中花费的?
如果是后者,也许你可以创建一个镜像版本的存储过程,只获取计数而不是实际行。如果是前者,那么你不能做太多事情,因为找到合适的行是缓慢的过程。

0
你需要编写一个不同版本的存储过程来获取行数。这个版本可能会更快,因为你可以消除那些没有被筛选的表连接、删除排序等。例如,如果你的存储过程执行了以下 SQL:
select firstname, lastname, email, orderdate  from 
customer inner join productorder on customer.customerid=productorder.productorderid
where orderdate>@orderdate order by lastname, firstname;

您的计数版本将会类似于:

select count(*) from productorder where orderdate>@orderdate;

0
您的问题的解决方案可能是重新编写存储过程,以将结果集限制为某个数字,例如:
SELECT TOP 1000 * FROM tblWHATEVER

在SQL Server中,或者

SELECT * FROM tblWHATEVER WHERE ROWNUM <= 1000

在Oracle中。或者实现分页解决方案,使得每次调用的结果集是可以接受的小。


0
根据Tony Andrews在他的回答中所说的,你可以通过以下方式获取对查询调用的估计查询计划:
SET showplan_text OFF
GO
SET showplan_all on
GO
--Replace with call you your stored procedure
select * from MyTable
GO 
SET showplan_all ofF
GO

这应该返回一个表格,或者多个表格,让您获取查询的预估行数。


0

您需要分析返回的数据集,确定适合返回结果集的逻辑(有意义的)主键。通常情况下,这比完整的过程要快得多,因为服务器不是从每个表的每行的所有列中的数据构造结果集,而只是计算行数... 一般来说,它甚至可能不需要从磁盘读取实际的表行,只需要计算索引节点...

然后编写另一个SQL语句,仅包括生成这些关键列所需的表(希望这是主SQL查询中表的子集),以及相同的where子句和相同的过滤谓词值...

然后向存储过程添加另一个可选参数,称为@CountsOnly,默认为false(0),如下所示...

Alter Procedure <storedProcName>
@param1 Type, 
-- Other current params
@CountsOnly TinyInt = 0
As
Set NoCount On

   If @CountsOnly = 1
       Select Count(*) 
       From TableA A 
          Join TableB B On   etc. etc...
       Where < here put all Filtering predicates >

   Else
      <Here put old SQL That returns complete resultset with all data>

  Return 0

您可以使用@CountsOnly参数设置为1来调用相同的存储过程,以获取记录的计数。旧代码调用存储过程仍然像以前一样运行,因为如果未包含该参数,则参数值默认为false(0)。

0
创建一个存储过程来先计算行数。
SELECT COUNT(*) FROM table

即使仅仅是枚举数十亿行,这本身也可能非常昂贵。 - stephbu

0

除非您的应用程序业务逻辑中有某些方面可以进行计算,否则不行。数据库将不得不执行所有where和join逻辑来确定如何排列行,这是存储过程中花费绝大部分时间的原因。


0

在执行存储过程之前,无法获取其行数。

您可以创建一个不同的存储过程,接受相同的参数,目的是告诉您其他存储过程应该返回多少行。然而,这个存储过程所需的步骤通常与主要存储过程非常相似,因此它需要的时间几乎和执行主要存储过程一样长。


0

不是一般性的。

通过对存储过程操作的了解,您可能能够获得估计或准确的计数(例如,如果查询的“核心”或“基础”表能够快速计算,但复杂的连接和/或汇总会增加时间)。

但您必须先调用计数SP,然后再调用数据SP,或者您可以考虑使用多结果集SP。


0

获取行数可能需要与获取实际数据一样长的时间,因此在大多数情况下,我不建议执行计数。

一些可能性:

1)SQL Server是否以某种方式公开其查询优化器的结果?即,您是否可以解析查询,然后获得行数的估计值?(我不了解SQL Server)。

2)也许基于用户提供的条件,您可以进行自己的估算。例如,如果用户在客户姓氏字段中输入“S%”以查询订单,则您可以确定该字段匹配7%(假设)的客户记录,并推断出查询可能返回约7%的订单记录。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接