2017-08-07 107 views
0

我喜歡寫返回每個表的名稱的過程中,具有特定ID的行。換句話說,表中有一列'id',它是varchar類型的,並且包含一個uuid。之後做一些研究,我選擇了下面的方法(簡化,集中於我不能解決/明白的問題):while循環光標和動態SQL不會終止

-- 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福不幫助尋找答案。

問題:爲什麼它停止工作以「太多」遊標行,有沒有辦法把它用這種方式工作?

是否有其他(更好)的方式來解決實際問題(運行查詢的所有表)?這不是要用於生產,它只是某種開發/維護腳本。

回答

1

它可以幫助有大約您的評論的一些方面「停止工作」,例如,它的PROC回報意外,並在PROC生成一個堆棧跟蹤,是不是真的「停止」或者是「運行時間比預期長「?


一些基本的監控應該幫助找出發生了什麼事情:

  • 沒有sp_who顯示光標過程被阻塞(例如,通過對數據的排它鎖要查詢其他進程)
  • 做的master..monProcessWaits where SPID =<spid_of_cursor_process>定期查詢顯示有相當大數量的等待時間的任何事件(例如,高等待時間磁盤讀取;高等待時間網絡寫入)
  • 做定期查詢show cpu/wait/logicalreads/physicalreads增加?

我猜你的一些SELECT查詢的是針對稍大表與運行在id列沒有可用的指標,與最終的結果是,一些SELECT在運行昂貴的(和慢)表和/或索引掃描,可能不得不等待大量的數據從磁盤中取出。

如果我的猜測是正確的,MDA表應顯示曾經等待磁盤,邏輯/物理讀取,並在較小程度上的CPU越來越多。另外,如果您看到大量的邏輯/物理讀取(指示表/索引掃描),則當前運行的SELECT的查詢計劃應該確認使用表/索引掃描(並且因此不能查找/使用當前表的id列上的索引)。

對於你的更小/更快的測試運行,我猜你正碰到a)表/索引掃描相對較快的較小表和/或b)id列有可用索引的表(因此相對較快索引查找)。


還有其他的事情要考慮......您使用什麼應用程序來使您的proc調用?

我忘記了用戶遇到過一些問題的次數......我應該說'時髦'的問題......訪問ASE時,通常這個問題會跟蹤到前端/客戶端應用程序的配置或編碼問題。

在這些情況下,我建議用戶通過isql命令行工具運行他們的查詢和/或特效,看他們是否得到相同的'時髦'結果;通常isql命令行會話不會顯示'時髦'行爲,因此指出用戶所使用的任何應用程序/工具用於訪問ASE的問題。

注意:isql命令行工具,我的意思正是...的命令行工具 ...不要與wisqldbisql或任何其他點正單擊GUI工具(其中許多的混淆在某些情況下做會導致一些'時髦'的行爲)。

注意:即使事實證明這是客戶端問題(與ASE問題相反),MDA表通常可以指出這一點,例如,monProcessWaits可能在等待輸出時顯示大量等待時間(給客戶)完成;在這種情況下,sp_who也將顯示狀態爲send sleep的spid(即,ASE正在等待客戶端處理由ASE發送給客戶端的最後一個結果集)。

+0

感謝您的全面回答! 「那麼程序永遠不會終止」 - 希望解釋它:/它不會終止,我必須從數據庫斷開連接,停止它,沒有消息,沒有錯誤,沒有部分結果,什麼都沒有。 –

+0

這就像:有20個表格,它在幾毫秒內終止,21,它運行> 1分鐘(也許永遠)(不知道它是否恰好爲20 - 如果值很重要,我可以嘗試一些測試來獲得確切的邊界) –

+0

但是,通過「永不終止」,你的意思是幾分鐘後它沒有完成,或者它在6小時後沒有完成,或者它在2天后沒有完成?對於較大的表,較小的數據緩存,相對較慢的磁盤......一張表的表掃描很容易從10幾分鐘到幾個小時......將其乘以多個大表掃描......並且您的評論「永遠不會終止'太模糊了......你真的需要監視MDA表來看看發生了什麼(例如,花費很長時間執行一些大型表掃描)。 – markp