如何对mssql_execute()进行分页或批量调用?

时间:2014-07-19 00:09:46

标签: php sql sql-server stored-procedures

当我使用ad-hoc SQL(例如,"SELECT foo FROM tablename")调用MSSQL数据库时,我可以为该调用提供批量大小。当我期望返回大量数据时,这非常有用。

在我的情况下,我有一个超过2亿行的表,而且我得到了所有这些。是的,我有理由成为像这样的大型奶牛。

我的数据库人员说,“嘿,停止使用临时SQL,在这里,使用这个漂亮的SP。它做同样的事情。”

所以我在mssql_execute()函数调用中使用它,但在执行此操作时没有办法指定批量大小,因为mssql_query()

我不仅要做ini_set('memory_limit', '64G');为了完成这项工作,我也不得不出汗,因为SP呼叫需要花费半小时才能运行。一旦它运行,我可以在mssql_fetch_row()上循环,没问题,但是这个初始调用是一个钉子![/ p>

一旦我完成了,我有一个占用57G内存的进程(在一个96G的盒子上),然后在80%的CPU上花费整整一个小时来放松和垃圾收集。是的,我可以杀死这个过程,但那是一个黑客攻击。

必须有更好的方法!

使用ad-hoc SQL,我调用批量大小为10,000行的mssql_query()并处理它们,然后返回更多。然后,我可以做一些回音“是的,确实,我现在正在排$i ......”并且让我的偏执狂让一切顺利。

那么......如果我被迫使用我的数据库人员希望我使用的SP,那么这样做的恰当方法是什么?

1 个答案:

答案 0 :(得分:0)

假设表有一个主键,我建议你让DB伙伴给存储过程添加2个参数,一个用于返回的行数,另一个用于起始键值。为初始批处理传递NULL,为每个后续批处理返回最后一个键值。这将提供有效的前向分页。例如:

CREATE PROCEDURE dbo.usp_select_tablename
      @NumRows int
    , @StartKey int = NULL
AS 
IF @StartKey IS NULL
BEGIN
    SELECT TOP(@NumRows) foo
    FROM tableName
    ORDER BY StartKey;
END
ELSE
BEGIN
    SELECT TOP(@NumRows) foo
    FROM tableName
    WHERE Key > @StartKey
    ORDER BY StartKey;
END;