2010-05-20 11 views
6

Vì vậy, chúng tôi có một phần mềm có câu lệnh SQL được viết kém gây ra mọi hàng từ một bảng được trả lại. Có một vài triệu hàng trong bảng vì vậy điều này gây ra vấn đề bộ nhớ nghiêm trọng và treo trên máy khách hàng của chúng tôi. Nhà cung cấp đang trong quá trình tạo bản vá cho vấn đề, tuy nhiên vẫn còn vài tuần nữa. Trong thời gian đó, chúng tôi đã cố gắng tìm ra một phương pháp hạn chế số lượng kết quả được trả về ở phía máy chủ giống như một bản sửa lỗi tạm thời.Giới hạn số hàng được trả về ở phía máy chủ (giới hạn bắt buộc)

Tôi không có hy vọng thực sự về việc có giải pháp, tôi đã nhìn xung quanh và không thực sự thấy bất kỳ cách nào để làm điều này, tuy nhiên tôi hy vọng ai đó có thể có ý tưởng.

Cảm ơn bạn trước.

EDIT

Tôi quên một phần quan trọng của thông tin, chúng tôi không có quyền truy cập vào mã nguồn vì vậy chúng tôi không thể thay đổi điều này trên các mặt hàng mà các câu lệnh SQL được hình thành. Không có thành phần phía máy chủ thực, máy khách chỉ truy cập trực tiếp vào cơ sở dữ liệu. Bất kỳ giải pháp nào về cơ bản sẽ yêu cầu một thủ tục, kích hoạt hoặc một số loại thiết lập/lệnh SQL-Server 2008.

+0

Việc sửa tạm thời đó có phá vỡ ứng dụng không? Bạn có biết dữ liệu này đang được sử dụng như thế nào không? – Paddy

+2

Đổi tên bảng và thay thế bằng một chế độ xem thực hiện 'SELECT TOP x * FROM new_name_of_the_table'. Lưu ý, tuy nhiên, thao tác dữ liệu (INSERT, UPDATE, DELETE) được thực hiện bởi ứng dụng sẽ không thành công sau đó. – Heinzi

+0

@Heinzi Thật không may, chúng tôi cần phải có thể chèn, cập nhật và xóa. – tplaner

Trả lời

2

Một giải pháp khả thi có thể là để

  • đổi tên bảng vi phạm
  • tạo updatable view với tablename gốc
  • thực hiện SELECT TOP x * FROM OffendingTable làm định nghĩa chế độ xem của bạn

Như vậy, khách hàng không nhận thức được sự thay đổi khi chọn dữ liệu.


Sử dụng query governor

Nếu bạn không nhớ trở về không có dữ liệu nào cho truy vấn vi phạm, thống đốc truy vấn cho phép bạn làm như vậy.

+0

Đề xuất tuyệt vời, tương tự như bình luận của Heinzi, tuy nhiên sau đó chèn, cập nhật và xóa các câu lệnh trong ứng dụng sẽ không hoạt động. – tplaner

+0

@evolve, nó trở nên khó khăn hơn nhưng bạn nên đọc trên các khung nhìn có thể cập nhật. Tôi không biết nếu nó có thể với yêu cầu của bạn nhưng tôi tin như vậy. –

+0

Điều này hầu như làm việc, chèn/cập nhật/xóa hoạt động mà không có vấn đề, tuy nhiên nếu bạn chọn SELECT 100 * FROM {table} thì nó luôn trả về cùng 100 top trên cùng, nó không dựa trên 100 truy vấn đầu tiên được thực thi. Đôi khi họ có câu lệnh WHERE trong truy vấn cần phải làm việc. Vì vậy, gần gũi mặc dù. – tplaner

1

Đã có một lệnh cho nó.

Tôi biết trong MYSQL đó là "LIMIT (firstindex, lastindex)" ở cuối câu lệnh sql.

Tôi nghĩ rằng tôi nghe trong MSSQL bạn có thể viết:

Chọn TOP 10,20 ... hoặc một cái gì đó như thế này

Điều đó sẽ có nghĩa là bạn chọn 20 hàng với 10 đầu tôi nghĩ rằng

1

bạn có thể sử dụng chọn top

SELECT tOP 50 PERCENT * FROM Persons (http://www.w3schools.com/sql/sql_top.asp)

hoặc

Đừng phân trang như thế này sẽ giúp bạn

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

Có vẻ như anh ta không có quyền truy cập vào SQL –

1

Nếu khách hàng đang sử dụng TCP để kết nối với cơ sở dữ liệu, bạn có thể chèn máy chủ proxy TCP chủ yếu trong suốt giữa máy khách và máy chủ cơ sở dữ liệu ở phía máy chủ. Sau đó, bạn có thể viết lại bất kỳ truy vấn vi phạm nào đến từ ứng dụng khách (sử dụng TOP hoặc một số phương tiện để cải thiện truy vấn).

Sau đó bạn định cấu hình SQL Server để chạy trên một cổng khác, khởi động proxy của bạn để phân phát trên cổng gốc và kết nối với máy chủ SQL trên cổng mới. Nếu bạn biết địa chỉ IP khởi tạo của máy khách, bạn có thể sử dụng cổng chuyển tiếp để bạn có thể hướng chúng đến proxy, và để máy chủ cơ sở dữ liệu được cấu hình như cũ.

Tôi có thể viết và kiểm tra điều này trong một giờ, nhưng nó có một số kiến ​​thức về lập trình socket.

+0

+1. Như một giải pháp ubergeek này sẽ là cách mát mẻ. Tôi nghi ngờ nó sẽ có thể làm được trong một giờ nhưng chắc chắn là có thể làm được. –

+0

Giải pháp mát mẻ, không đáng tin cậy. – tplaner

+0

@Evolve, tôi đã sử dụng giải pháp này cho các loại hệ thống sản xuất khác. Phải thừa nhận rằng, tôi đã không sử dụng nó cho một hệ thống cơ sở dữ liệu, nhưng tôi sẽ. –

0

Bạn có thể xóa tất cả trừ bản ghi X khỏi bảng và lưu trữ chúng ở một nơi khác