2014-04-23 17 views
8

Ho una tabella in Sql Azure contiene circa 6 milioni di righe. Voglio creare un nuovo indice per questo. il cmd è come:sql query che richiede tempo azzurro

CREATE NONCLUSTERED INDEX [INDEX1] ON [dbo].Table1 
(
    [Column1] ASC, 
    [Column2] ASC, 
    [Column3] ASC, 
    [Column4] ASC 
) 
INCLUDE ([Column5],[Column6]) 

E dopo circa 15 minuti, un errore si verifica

"Msg 10054, Level 20, State 0, Line 0

A transport-level error has occurred when receiving results from the server. (provider: TCP Provider, error: 0 - An existing connection was forcibly closed by the remote host.)"

Ho provato diverse volte, ho ottenuto lo stesso errore. Ma ho realizzati altri in termini di tempo di query, come:

Insert into table1(Col1,Col2,Col3) select Col1,Col2,Col3 from table2

Quali sono voluti 20 minuti ed è tornato con successo.

Le query sono state eseguite nello stesso database SQL di Sql. Non so cosa sta succedendo qui. Qualcuno potrebbe aiutare? Grazie!

+0

Puoi provare a creare una nuova tabella con indice e quindi migrare le righe dalla vecchia tabella alla nuova tabella e quindi eliminare la vecchia tabella e rinominare la nuova tabella? –

risposta

8

Ho avuto lo stesso problema con una tabella contenente 100 milioni di righe e contattato il supporto Microsoft. Questa è la risposta che ho ottenuto:

The reason why you can’t create the index on your table is that you are facing a limitation on the platform that prevents to have transactions larger than 2GB.

The creation of an index is a transactional operation that relies on the transaction log to execute the move of the table pages. More rows in a table means more pages to put in the T-Log. Since your table contains 100 million of records (which is quite a big number), it is easy for you to hit this limit.

In order to create the index we need to change the approach. Basically we are going to use a temporary(staging) table to store the data while you create the index on the source table, that you would have previously cleared from data.

Action Plan:

  1. Create a staging table identical to the original table but without any index (this makes the staging table a heap)
  2. move the data from the original table to a staging table (the insert is faster because the staging table is a heap)
  3. empty the original table
  4. create the index on the original table (this time the transaction should be almost empty)
  5. move back data from staging table to original table (this would take some time, as the table contains indexes)
  6. delete the staging table

Essi suggeriscono di usare BCP per spostare i dati tra la tabella di gestione temporanea e la tabella originale.

Quando si cerca nella tabella event_log ...

select * from sys.event_log 
where database_name ='<DBName>' 
and event_type <> 'connection_successful' 
order by start_time desc 

.. Ho trovato questo messaggio di errore:

The session has been terminated because of excessive transaction log space usage. Try modifying fewer rows in a single transaction.

+3

Se questo è davvero l'approccio migliore disponibile per creare un grande indice su Azure, ho perso molta fiducia in esso. – usr

+0

Ora stiamo usando SQL Server su Azure IaaS Virtual Machine. Funziona esattamente come un ambiente on-premise, senza limitazioni sulla dimensione del log delle transazioni. – andersh

+0

Questo articolo, https://alexandrebrisebois.wordpress.com/2013/09/29/creating-nonclustered-indexes-on-massive-tables-in-windows-azure-sql-database/, suggerisce di utilizzare l'opzione ONLINE = ON per evitare questa limitazione critica su SQL Azure. –

2

grazie per la risposta! In realtà, ho trovato anche la causa principale.
C'è una soluzione, imposta ONLINE = ON, in modalità online, l'attività di creazione dell'indice verrà suddivisa in più piccole attività in modo che il T-Log non superi i 2 GB.
Ma c'è una limitazione, la 'colonna di inclusione' del comando di creazione dell'indice non può essere oggetto con dimensione illimitata, come nvarchar (max), in caso affermativo il comando fallirà immediatamente.

Quindi, in SQL Azure, per la creazione di un indice di un'operazione simile al seguente:

CREATE NONCLUSTERED INDEX [INDEX1] ON [dbo].Table1 
(
    [Column1] ASC, 
    [Column2] ASC, 
    [Column3] ASC, 
    [Column4] ASC 
) 
INCLUDE ([Column5],[Column6]) 

adottare le seguenti azioni, se il precedente non è riuscito.
1.creare l'indice con 'online = on'
2.se il numero 1 non è riuscito, significa che colonna5 o colonna6 è nvarchar (max), interrogare la dimensione della tabella, se < 2GB, creare direttamente l'indice utilizzando online = off.
3.se fallito # 2, significa dimensione tabella> 2 GB, quindi non esiste un modo semplice per creare un indice senza una tabella temporanea coinvolta, deve agire come ha risposto ahkvk.

+0

Ecco un buon articolo sull'argomento che chiarisce il tuo suggerimento altrimenti ottimo: https://alexandrebrisebois.wordpress.com/2013/09/ 29/creation-nonclustered-indexes-on-massive-tables-in-windows-azure-sql-database/ –

+0

Solo un aggiornamento; il tuo suggerimento mi guida alla soluzione. Per me - e spero che gli altri - questa è la risposta accettata. +1 –

+0

Questo ha funzionato per me. In un secondo tentativo almeno. INCLUDE ([Column5], [Column6]) WITH (ONLINE = ON); – McGaz

Problemi correlati