2010-05-20 20 views
6

Quindi abbiamo un software che ha un'istruzione SQL scritta male che sta causando il ritorno di ogni riga da una tabella. Ci sono diverse milioni di righe nella tabella, quindi questo sta causando seri problemi di memoria e arresti anomali sul nostro computer client. Il fornitore sta creando una patch per il problema, tuttavia mancano ancora alcune settimane. Nel frattempo stavamo tentando di capire un metodo per limitare il numero di risultati restituiti sul lato server come una soluzione temporanea.Limitare il numero di righe restituite sul lato server (limite forzato)

Non ho alcuna speranza che ci sia una soluzione, mi sono guardato intorno e non vedo alcun modo di farlo, tuttavia spero che qualcuno possa avere un'idea.

Grazie in anticipo.

EDIT

ho dimenticato un pezzo importante di informazioni, non abbiamo accesso al codice sorgente in modo da non possiamo cambiare questo sul lato client in cui si forma l'istruzione SQL. Non esiste un vero componente lato server, il client accede direttamente al database. Qualsiasi soluzione richiederebbe fondamentalmente una procedura, un trigger o una sorta di impostazione/comando di SQL Server 2008.

+0

Tuttavia, questa correzione temporanea interromperà l'applicazione? Sai come vengono utilizzati questi dati? – Paddy

+2

Rinominare la tabella e sostituirla con una vista che fa un 'SELECT TOP x * FROM new_name_of_the_table'. Si noti, tuttavia, che le manipolazioni dei dati (INSERT, UPDATE, DELETE) eseguite dall'applicazione falliranno in seguito. – Heinzi

+0

@Heinzi Purtroppo dovremmo essere in grado di inserire, aggiornare ed eliminare. – tplaner

risposta

2

Una possibile soluzione potrebbe essere quella di

  • rinominare la tabella incriminata
  • creare un updatable view con il nome della tabella originale
  • fai un SELECT TOP x * FROM OffendingTable come definizione della vista

Come tale, il cliente non è a conoscenza del cambiamento quando seleziona i dati.


Utilizzare la query governor

Se non ti dispiace di tornare non ci sono dati a tutti per la query incriminata, il governatore di query consente di farlo.

+0

, simile al commento di Heinzi, tuttavia le istruzioni di inserimento, aggiornamento ed eliminazione all'interno dell'applicazione non funzionerebbero. – tplaner

+0

@evolve, diventa più difficile ma è necessario consultare le viste aggiornabili. Non so di mano se sarebbe possibile con le tue esigenze, ma io credo di sì. –

+0

Funziona quasi, inserisce/aggiorna/elimina il lavoro senza un problema, tuttavia se si seleziona SELECT 100 * FROM {table} restituisce sempre la stessa top 100 superiore, non basa i primi 100 della query in esecuzione. A volte hanno istruzioni WHERE all'interno della query che devono funzionare. Così vicino però. – tplaner

1

Deve esserci un comando per questo.

So che in MYSQL è "LIMIT (firstindex, lastindex)" alla fine dell'istruzione sql.

credo di aver sentito in MSSQL è possibile scrivere:

selezionare Home 10,20 ... o qualcosa di simile

che vorrebbe dire si seleziona 20 righe con 10 inizio penso

1

è possibile utilizzare selezionare top

selezionare Home 50 per cento * FROM Persone (http://www.w3schools.com/sql/sql_top.asp)

o

Do il paging come questo vi aiuterà a

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

Sembra che non abbia accesso al suggerimento Eccellente –

1

Se il client utilizza TCP per connettersi al database, è possibile inserire un server proxy TCP per lo più trasparente tra il client e il server di database sul lato server. È quindi possibile riscrivere qualsiasi query offensiva proveniente dal client (utilizzando TOP o alcuni metodi per migliorare la query).

Quindi configurare SQL Server per l'esecuzione su una porta diversa, avviare il proxy per servire sulla porta originale e collegarsi al server SQL sulla nuova porta. Se si conosce l'indirizzo IP di origine del client, è possibile utilizzare il port forwarding in modo che sia possibile indirizzarli solo al proxy e lasciare il server del database configurato così com'è.

Potrei scrivere e testare questo in un'ora, ma richiede una certa conoscenza della programmazione dei socket.

+0

+1. Come una soluzione ubergeek questo sarebbe molto interessante. Dubito che sarebbe fattibile in un'ora, ma è certamente fattibile. –

+0

Soluzione cool, non plausibile però. – tplaner

+0

@Evolve, ho utilizzato questa soluzione per altri tipi di sistemi di produzione. Devo ammettere che non l'ho usato per un sistema di database, ma lo farei. –

0

È possibile eliminare tutti i record X tranne dalla tabella e memorizzarli altrove.

Problemi correlati