我有一些复杂的存储过程,可能会返回成千上万行数据,并且需要很长时间才能完成。
在查询执行和获取数据之前,有没有办法找出将返回多少行?
这是使用 Visual Studio 2005、Winforms 应用程序和 SQL Server 2005。
我有一些复杂的存储过程,可能会返回成千上万行数据,并且需要很长时间才能完成。
在查询执行和获取数据之前,有没有办法找出将返回多少行?
这是使用 Visual Studio 2005、Winforms 应用程序和 SQL Server 2005。
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;
SELECT TOP 1000 * FROM tblWHATEVER
在SQL Server中,或者
SELECT * FROM tblWHATEVER WHERE ROWNUM <= 1000
在Oracle中。或者实现分页解决方案,使得每次调用的结果集是可以接受的小。
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
这应该返回一个表格,或者多个表格,让您获取查询的预估行数。
您需要分析返回的数据集,确定适合返回结果集的逻辑(有意义的)主键。通常情况下,这比完整的过程要快得多,因为服务器不是从每个表的每行的所有列中的数据构造结果集,而只是计算行数... 一般来说,它甚至可能不需要从磁盘读取实际的表行,只需要计算索引节点...
然后编写另一个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
除非您的应用程序业务逻辑中有某些方面可以进行计算,否则不行。数据库将不得不执行所有where和join逻辑来确定如何排列行,这是存储过程中花费绝大部分时间的原因。
在执行存储过程之前,无法获取其行数。
您可以创建一个不同的存储过程,接受相同的参数,目的是告诉您其他存储过程应该返回多少行。然而,这个存储过程所需的步骤通常与主要存储过程非常相似,因此它需要的时间几乎和执行主要存储过程一样长。
不是一般性的。
通过对存储过程操作的了解,您可能能够获得估计或准确的计数(例如,如果查询的“核心”或“基础”表能够快速计算,但复杂的连接和/或汇总会增加时间)。
但您必须先调用计数SP,然后再调用数据SP,或者您可以考虑使用多结果集SP。
获取行数可能需要与获取实际数据一样长的时间,因此在大多数情况下,我不建议执行计数。
一些可能性:
1)SQL Server是否以某种方式公开其查询优化器的结果?即,您是否可以解析查询,然后获得行数的估计值?(我不了解SQL Server)。
2)也许基于用户提供的条件,您可以进行自己的估算。例如,如果用户在客户姓氏字段中输入“S%”以查询订单,则您可以确定该字段匹配7%(假设)的客户记录,并推断出查询可能返回约7%的订单记录。