如何从SELECT语句输出进度消息?

时间:2008-09-24 19:48:01

标签: sql sqlanywhere

我有一个SQL脚本,我希望在运行时输出进度消息。让它在SQL语句之间输出消息很容易,但是我有一些很长时间运行的INSERT INTO SELECT。有没有办法让select语句输出消息,例如每1000行或每5秒后?

注意:这适用于SQL Anywhere,但任何SQL方言中的答案都可以。

12 个答案:

答案 0 :(得分:5)

无法检索单个查询的执行状态。没有主流数据库引擎提供此功能。
此外,任何进度实现都会产生可衡量的开销,因此如果查询已经花费了很长时间以至于您想要显示进度,那么通过显示所述进度可能不是设计目标而导致额外的减速。
您可能会发现此article on estimating SQL execution progress有用,但其实际意义有限。

答案 1 :(得分:3)

SQL本身没有提供此类内容。任何这样做的方法都是直接与数据库引擎交谈,而不是跨数据库的标准。

答案 2 :(得分:3)

实际上,基于集合的操作(这是关系数据库使用的)的进度的想法不会太有帮助,至少不会像进度条一样显示(完成百分比与总计)。当优化器弄清楚它需要做什么并真正理解操作的全部成本时,您已经完成了大部分操作。进度显示实际上是用于迭代操作而不是设置操作。

那是在谈论你的一般SELECT语句执行。对于作为单独语句的插入,通过监视语句的消耗率,可以通过提交者以各种方式执行此操作。如果它们是批量插入(选择,插入等),那么你真的遇到了我上面描述的相同问题。设置操作的批处理方式使得进度条类型的显示有点无意义。

答案 3 :(得分:3)

我在SQL Anywhere引擎开发团队中,目前无法做到这一点。我不能承诺任何事情,但我们正在考虑在未来版本中添加此类功能。

答案 4 :(得分:2)

当然没有SQL标准的解决方案。很抱歉让我感到痛苦,但我还没有看到任何可以在Oracle,SQL Server,Sybase或MySQL中做到这一点的事情,所以我对SQLAnywhere不会抱太大希望。

答案 5 :(得分:2)

我同意SQL无法直接执行此操作。一种方法可能是一次只插入TOP 1000,然后打印您的状态信息。然后根据需要继续重复(在某种循环中)。缺点是你需要一种方法来跟踪你的位置。

我应该注意,这种方法不如只做一个大的INSERT

那么高效

答案 6 :(得分:2)

这是我要做的(Sybase / SQL Server语法):

DECLARE @total_rows int

SELECT  @total_rows = count(*) 
FROM    Source_Table

WHILE   @total_rows > (SELECT count(*) FROM Target_Table) 
BEGIN
    SET rowcount 1000 

    print 'inserting 1000 rows' 

    INSERT  Target_Table         
    SELECT  * 
    FROM    Source_Table s
    WHERE   NOT EXISTS( SELECT 1 
                        FROM   Target_Table t
                        WHERE  t.id = s.id )
END

set rowcount 0
print 'done'

或者您可以根据ID(假设Id是数字)来执行此操作:

DECLARE @min_id   int, 
        @max_id   int, 
        @start_id int, 
        @end_id   int

SELECT  @min_id = min(id) , 
        @max_id = max(id) 
FROM    Source_Table

SELECT  @start_id = @min_id , 
        @end_id   = @min_id + 1000 

WHILE   @end_id <= @max_id 
BEGIN

    print 'inserting id range: ' + convert(varchar,@start_id) + ' to ' + convert(varchar,@end_id) 

    INSERT  Target_Table         
    SELECT  * 
    FROM    Source_Table s
    WHERE   id           BETWEEN @start_id AND @end_id

    SELECT  @start_id = @end_id + 1, 
            @end_id   = @end_id + 1000 
END

set rowcount 0
print 'done'

答案 7 :(得分:1)

一种想法可能是让另一个单独的进程计算表中正在进行插入的行数,以确定它们已经存在的百分比。这当然要求你最终知道总数。如果你不太担心服务器负载,这可能只会没问题。

答案 8 :(得分:0)

如果您正在使用Toad,则可以从表中生成一组INSERT语句,并将其配置为以用户输入频率提交。您可以稍微修改一下脚本,然后看看有多少新数据已经提交。

答案 9 :(得分:0)

您可以通过计算多次运行来模拟用户的效果,然后以平均记录/秒速率提前进度条。

唯一的其他方式是

1 - 请参阅数据库引擎的API,看看它是否为该

做了任何规定

2 - 将INSERT分解为许多较小的语句,并随时报告它们。但这将对性能产生重大负面影响。

答案 10 :(得分:0)

如果你需要它或者你死了,对于插入,更新,删除你可以使用一些触发器逻辑和db变量,并且你可以用sql来检索变量数据并向用户显示一些进度。

如果你不想使用它,我可以写一个例子并发送它。

答案 11 :(得分:0)

偶然发现这个老线程正在寻找其他东西。我不同意我们不想要进度信息的想法,因为它是一个固定的操作。如果用户知道多长时间,他们通常会忍受漫长的等待。

这是我的建议:

每次运行时,记录插入的行数和总时间,然后在该过程开始时添加一个步骤来查询该日志并计算估计的总时间。如果你根据最后一次运行估算,你应该能够对完成事情的等待时间提出一个可接受的好猜测。