while with cursor和dynamic SQL不会终止

时间:2017-08-07 16:03:40

标签: sql sybase-ase

我喜欢编写一个返回每个表名称的过程,该过程具有一个具有特定id的行。换句话说,这些表的列'id'是varchar类型,包含一个uuid。在做了一些研究之后,我选择了以下方法(简化,重点关注我无法解决/理解的问题):

-- get a cursor for all foo table names that have an id column
DECLARE table_name_cursor CURSOR FOR
SELECT a.name
FROM sysobjects a, syscolumns b 
WHERE a.id = b.id 
    AND a.name like 'Foo%'
    AND b.name = 'id'

GO

-- define some variables
DECLARE @current_table_name VARCHAR(100)
DECLARE @id_found VARCHAR(100)

OPEN table_name_cursor
FETCH table_name_cursor INTO @current_table_name
WHILE @@SQLSTATUS = 0
BEGIN
    EXEC ('SELECT @id_found = id from ' + @current_table_name + " where id = '@id_param'") -- @id_param will be passed with the procedure call
    select @current_table_name  
    FETCH table_name_cursor INTO @current_table_name
END

-- clean up resources
CLOSE table_name_cursor
DEALLOCATE table_name_cursor

当光标的大小相当低(在我的情况下约为20个表)时,它按预期工作,但如果光标大小增加,则该过程永远不会终止。

它闻起来像是一个资源问题,但我在Sybase-Fu中的白带并没有帮助找到答案。

问题:为什么它停止使用'太多'游标行,是否有办法让它使用这种方法?

是否有另一种(更好的)方法来解决实际问题(在所有表上运行查询)?这不是用于生产,它只是某种开发/维护脚本。

1 个答案:

答案 0 :(得分:1)

你的评论“它停止工作”可能会有所帮助,例如,proc是否意外返回,proc是否生成堆栈跟踪,是否真的“停止”或者“运行时间超出预期” ?

一些基本的监控应该有助于弄清楚发生了什么:

  • 是否sp_who将光标进程显示为被阻止(例如,对您正在查询的数据具有独占锁定的其他进程)
  • 定期查询master..monProcessWaits where SPID =<spid_of_cursor_process>显示任何具有大量等待时间的事件(例如,磁盘读取的等待时间较长;网络写入的等待时间较长)
  • 定期查询master..{monProcessStatement|monProcessObject} where SPID = <spid_of_cursor_process> show cpu / wait / logicalreads / physicalreads是否会增加?

我猜你的一些SELECT正在针对在id列上没有可用索引的较大表运行,最终结果是某些SELECT正在运行昂贵(和慢)的表和/或索引扫描,可能需要等待从磁盘中提取大量数据。

如果我的猜测是正确的,MDA表应该显示磁盘等待,逻辑/物理读取以及较小程度cpu的数量不断增加。

此外,如果您看到大量的逻辑/物理读取(指示表/索引扫描),则当前运行的SELECT的查询计划应确认使用表/索引扫描(因此无法查找/在当前表的id列上使用索引。

对于较小/较快的测试运行,我猜你要么是a)较小的表,其中表/索引扫描相对较快和/或b)表{/ 1}}列上有可用索引的表(和因此相对较快的索引查找)。

需要考虑的其他事项......您使用什么应用程序进行proc调用?

我已经忘记了用户遇到某些问题的次数......在访问ASE时,我会说'时髦'问题吗?通常会将问题跟踪回到前端/客户端应用程序的配置或编码问题。

在这些情况下,我建议用户通过id命令行工具运行他们的查询和/或过程,以查看他们是否获得了相同的“时髦”结果; isql命令行会话通常不会显示“时髦”行为,因此指出用户用于访问ASE的任何应用程序/工具的问题。

注意:通过isql命令行工具,我的意思是...... 命令行工具......不要与isql或{{1}混淆或者任何其他点击式GUI工具(其中许多会在某些情况下导致一些'时髦'行为)。

注意:即使这被证明是客户端问题(而不是ASE问题),MDA表通常可以精确定位,例如,monProcessWaits在等待输出时可能会显示大量等待时间(到客户)完成;在这种情况下,wisql还会显示状态为dbisql的spid(即,ASE正在等待客户端处理ASE发送给客户端的最后一个结果集)。