2010-05-20 88 views
6

所以我們有一段軟件,它有一個寫得不好的SQL語句,導致表中的每一行都返回。表中有幾百萬行,所以這會導致嚴重的內存問題和客戶機上的崩潰。供應商正在爲這個問題創建一個補丁,但它仍然是幾個星期。與此同時,我們試圖找出一種限制在服務器端返回的結果數量的方法,只是將其作爲臨時修復。限制在服務器端返回的行數(強制限制)

我沒有真正希望有一個解決方案,我環顧四周,並沒有真正看到這樣做的任何方式,但我希望有人可能有一個想法。

預先感謝您。

編輯

我忘了一個重要信息,我們的源代碼不能訪問,所以我們不能在形成SQL語句中的客戶端進行更改。沒有真正的服務器端組件,客戶端只是直接訪問數據庫。任何解決方案基本上都需要一個過程,觸發器或某種SQL-Server 2008設置/命令。

+0

將是臨時的解決辦法然而中斷應用程序?你知道如何使用這些數據嗎? – Paddy 2010-05-20 13:37:32

+2

重命名錶並將其替換爲執行'SELECT TOP x * FROM new_name_of_the_table'的視圖。但是請注意,應用程序執行的數據操作(INSERT,UPDATE,DELETE)將會失敗。 – Heinzi 2010-05-20 13:41:03

+0

@Heinzi很遺憾,我們需要能夠插入,更新和刪除。 – tplaner 2010-05-20 13:43:27

回答

2

一個可能的解決方案可能是

  • 與原表名重命名違規表
  • 創建updatable view
  • 做一個SELECT TOP x * FROM OffendingTable作爲您的視圖定義

因此,客戶端在選擇數據時並不知道更改。


使用query governor

如果你不介意在所有的有問題的查詢沒有返回數據,查詢管理器允許你這樣做。

+0

非常好的建議,類似於Heinzi的評論,然而在應用程序中插入,更新和刪除語句不起作用。 – tplaner 2010-05-20 13:47:07

+0

@evolve,它變得更加困難,但你應該閱讀可更新的視圖。我不知道你的要求是否可能,但我相信。 – 2010-05-20 13:56:38

+0

這幾乎奏效,插入/更新/刪除工作沒有問題,但是,如果你做SELECT 100 * FROM {table}它總是返回頂部相同的前100,它並沒有基於正在執行的查詢的前100。有時他們在需要工作的查詢中有WHERE語句。儘管如此。 – tplaner 2010-05-20 14:45:44

1

必須有一個命令。

我知道在MYSQL中是「LIMIT(firstindex,lastindex)」在sql語句的末尾。

我想我在MSSQL聽說你可以這樣寫:

選擇TOP 10,20 ......或者像這樣

這將意味着你選擇20排,10年初我認爲

1

您可以使用select頂部

SELECT TOP 50%* FROM人(http://www.w3schools.com/sql/sql_top.asp

不要這樣分頁會幫你

CREATE PROCEDURE [dbo].[GetRequestedRecordByPage] 
@FromList nvarchar(200)    -- Table Name 
,@SortingCol nvarchar(200)   -- Sorting column Name 
,@SelectList nvarchar(200) = '*'   -- Select columns list 
,@WhereClause nvarchar(200) = ''  -- Where clause i.e condition 
,@PageNum int = 1       -- Requested page number 
,@PageSize int = 5     -- No of record in page 
,@TotalNoOfRecord int output   -- Total no of selected records 
AS 
Begin 
    SET NOCOUNT ON 
    DECLARE @Query nvarchar(max)   -- query going to be execute 

    IF rtrim(ltrim(@WhereClause)) <> '' 
    BEGIN 
     SET @Query ='SELECT @TotalNoOfRecord = COUNT(*) 
         FROM  ' + @FromList + ' 
     WHERE ' + @WhereClause 
    END 
    ELSE 
    BEGIN 
     SET @Query ='SELECT @TotalNoOfRecord = COUNT(*) 
         FROM  ' + @FromList 
    END 

    /* Count no. of record */ 
     EXEC sp_executeSQL 
     @Query, 
     @params = N'@TotalNoOfRecord INT OUTPUT', 
     = @TotalNoOfRecord OUTPUT 

DECLARE @lbound int, @ubound int 




/* Calculating upper and lower bound */ 
     SET @lbound = ((@PageNum - 1) * @PageSize) 
     SET @ubound = @lbound + @PageSize + 1 


/* Get list of record(s) */ 
     SELECT @Query = '' 
     SELECT @Query = 'SELECT * 
          FROM ( 
SELECT ROW_NUMBER() OVER(ORDER BY ' + @SortingCol + ') AS rownumber,' [email protected] + 
             ' FROM ' + @FromList 

     IF rtrim(ltrim(@WhereClause)) <> '' 
     BEGIN 
      SELECT @Query = @Query + ' WHERE ' + @WhereClause 
     END 

      SELECT @Query = @Query + ' ) AS tbl 
WHERE rownumber > ' + CONVERT(varchar(9), @lbound) + 
     ' AND rownumber < ' + CONVERT(varchar(9), @ubound) 

     EXEC (@Query)     
End 
+3

聽起來好像他沒有訪問SQL – 2010-05-20 13:38:38

1

如果客戶端使用TCP連接到數據庫,則可以在服務器端的客戶端和數據庫服務器之間插入一個大多數透明的TCP代理服務器。然後,您可以重寫來自客戶端的任何違規查詢(使用TOP或改進查詢的一些方法)。

然後,您將SQL Server配置爲在不同的端口上運行,啓動您的代理服務於原始端口並將其連接到新端口上的SQL服務器。如果您知道客戶端的始發IP地址,則可以使用端口轉發,以便您可以將它們僅指向代理,並使數據庫服務器保持原樣。

我可以在一個小時內編寫並測試它,但它確實需要一些套接字編程的知識。

+0

+1。作爲一個ubergeek解決方案,這將是很酷的。我懷疑它在一個小時內是可行的,但它肯定是可行的。 – 2010-05-20 14:18:42

+0

很酷的解決方案,雖然不太合理。 – tplaner 2010-05-20 14:22:03

+0

@Evolve,我已將此解決方案用於其他類型的生產系統。無可否認,我並沒有將它用於數據庫系統,但我會這樣做。 – 2010-05-20 14:41:35

0

你可以從表中刪除所有,但X記錄並將其存儲在別處