VENDITE: 1-800-867-1389

Considerazioni sulle prestazioni con il database SQL di Windows Azure

Aggiornamento: gennaio 2014

In questo articolo vengono illustrate le procedure consigliate tramite cui vengono migliorate le prestazioni delle applicazioni in cui viene utilizzato un database sottoposto a migrazione al database SQL di Windows Azure. Quando lo stesso rack viene condiviso tra un server di database e il server applicazioni, è possibile che queste procedure consigliate non abbiano molto impatto. Tuttavia, quando il server di database viene spostato in un data center remoto, queste stesse procedure consigliate sono essenziali per il mantenimento di prestazioni ottimali. Inoltre, Windows Azure è un ambiente condiviso, poiché tutte le risorse sono condivise con altri ruoli, database e applicazioni. Tramite i componenti del bilanciamento del carico di rete e del gateway, disponibili in Windows Azure, è possibile mantenere un'economia di scala e fornire in modo più efficiente risorse di calcolo e di rete a tutto l'ambiente. Questi fattori devono essere presi in considerazione quando si progettano e si distribuiscono applicazioni in Windows Azure.

In questo articolo vengono illustrate le procedure consigliate relative alla progettazione e all'implementazione per ottimizzare le prestazioni per l'ambiente del database SQL di Windows Azure. In particolare, in questo articolo vengono riviste le procedure consigliate relative a due aree che possono determinare problemi di prestazioni effettivi quando viene eseguita la migrazione di database locali nel database SQL di Windows Azure:

Sono disponibili alcuni altri articoli correlati alle prestazioni del database di Windows Azure come descritto di seguito:

Il database SQL di Windows Azure offre la possibilità di riservare risorse per il database tramite l'edizione Premium attualmente disponibile con il programma di anteprima. Nel documento Informazioni aggiuntive sull'anteprima della versione Premium per il database SQL vengono fornite informazioni aggiuntive per stabilire se il database Premium disponibile con il programma di anteprima rappresenta la soluzione adatta all'applicazione in uso. Inoltre, vengono forniti consigli per ottimizzare l'applicazione in modo da ottenere il massimo da questa funzionalità.

Nell'articolo Database SQL di Windows Azure e SQL Server: confronto e contrapposizioni di prestazioni e scalabilità vengono illustrati alcuni modelli di prestazioni per il database SQL e diverse tecniche per valutare correttamente le prestazioni. Inoltre, sono inclusi vari script SQL utili per valutare e risolvere i problemi relativi alle istanze del database SQL.

  • Gestione delle connessioni

  • Latenza di rete tra il livello applicazione e il livello del database

Autori: Silvano Coriani, Steve Howard
Revisori: Mark Simms, Valery Mizonov, Kun Cheng, Paolo Salvatori, Jaime Alva Bravo

Gestione delle connessioni nel database SQL di Windows Azure

Le connessioni di database potrebbero essere terminate con una maggior frequenza quando un database è ospitato nel database SQL di Windows Azure rispetto a un ambiente locale. Gli utenti potrebbero percepire questi arresti come un problema di prestazioni se tramite le applicazioni non viene rapidamente rilevata l'eventuale perdita di connessione e se, in caso di errore temporaneo, la connessione non viene ristabilita. In qualità di provider di servizi di database su larga scala e multi-tenant in risorse condivise, tramite il database SQL di Windows Azure vengono eseguiti il clustering di ogni database attraverso tre nodi e il bilanciamento delle risorse tra i nodi del cluster per garantire un utilizzo ottimale a tutti i tenant. Un esempio di errore temporaneo è il rilevamento da parte del database SQL di Windows Azure di un elevato carico di lavoro di un server in cui sono ospitati più database. In questo caso, tramite il database SQL di Windows Azure è possibile che venga eseguito il failover di uno dei database in un nodo del cluster secondario a cui è associato un carico di elaborazione inferiore. Tramite il failover vengono terminate tutte le connessioni aperte al database e viene eseguito il rollback delle transazioni arretrate. Tramite le applicazioni deve essere rilevato rapidamente l'errore, ristabilita la connessione al database e ritentata l'ultima transazione.

Nell'elenco seguente vengono illustrati alcuni dei motivi per cui le connessioni potrebbero essere terminate dal database SQL di Windows Azure:

  • Nella topologia di rete complessiva del database SQL di Windows Azure sono inclusi firewall, servizi di bilanciamento del carico e gateway di flusso TDS. Tramite ognuno di questi componenti della topologia viene aggiunto un livello tra il codice di accesso ai dati e il nodo del database. In caso di errori in questi livelli aggiuntivi è possibile che le connessioni vengano terminate.

  • Tramite il database SQL di Windows Azure vengono continuamente raccolte e analizzate le statistiche di utilizzo del database. In base a queste statistiche, è possibile che tramite il database SQL di Windows Azure le connessioni vengano terminate, se necessario, per mantenere l'integrità del servizio.

  • A causa di attacchi Denial of Service, tramite il database SQL di Windows Azure vengono bloccate le connessioni da un indirizzo IP specifico per un periodo di tempo.

  • La presenza di alcuni eventi di failover potrebbe determinare il blocco improvviso di una sessione da parte del database SQL di Windows Azure. Si noti che qualsiasi connessione aperta in un nodo prima di un evento di failover non sarà disponibile nel nuovo nodo dopo il failover.

Nell'elenco precedente sono riportati solo alcuni dei motivi dei blocchi della connessione. Per ulteriori informazioni sugli errori di connessione e sulla gestione delle connessioni nel database SQL di Windows Azure, vedere i documenti seguenti:

Opzioni per la gestione delle connessioni nel codice

Le funzionalità seguenti sono state sviluppate da Microsoft come supporto per la gestione dei problemi di connessione del database SQL di Windows Azure:

  • Approccio coerente sulla modalità di specifica delle informazioni di base, come nomi di server e credenziali di sicurezza, o della fedeltà completa utilizzando strumenti come programmi per la copia bulk (bpc.exe). Ad esempio, a partire da SQL Server Native Client 11, JDBC versione 4.0 e Provider di dati .NET Framework per SQL Server (System.Data.SqlClient) da .NET Framework versione 4.0, non è necessario specificare nomeutente@server in caso di accesso al database SQL di Windows Azure.

  • Garanzia che una connessione possa essere gestita da tutte le tecnologie di connessione, anche durante periodi di inattività. Ad esempio, a differenza di Windows, tramite la piattaforma Java gli intervalli keep-alive per le connessioni di database non vengono gestiti a livello nativo. Pertanto, per i componenti JDBC che vengono connessi al database SQL di Windows Azure sono richieste alcune modifiche all'impostazione del Registro di sistema per assicurarsi che le connessioni inattive non vengano eliminate.
    Per ulteriori informazioni, vedere l'argomento in MSDN Library Connessione a un database nel database SQL di Windows Azure.

Inoltre, nelle librerie di accesso ai dati più comuni e nella versione Service Release del database SQL di Windows Azure sono stati continuamente distribuiti numerosi aggiornamenti da parte di Microsoft. L'aggiornamento più importante è probabilmente quello relativo al blocco di applicazioni per la gestione di errori temporanei, cioè una libreria di applicazioni in cui è disponibile una logica affidabile di gestione degli errori temporanei. Gli errori temporanei si verificano in determinate condizioni temporanee, ad esempio in caso di problemi di connettività di rete o di indisponibilità del servizio. Nella sezione successiva viene fornita una panoramica dettagliata della modalità di utilizzo del blocco di applicazioni per la gestione di errori temporanei in un'applicazione.

Breve descrizione dell'utilizzo del blocco di applicazioni per la gestione di errori temporanei

Tramite il blocco di applicazioni per la gestione di errori temporanei vengono incapsulate informazioni sugli errori temporanei che possono verificarsi quando si utilizzano i seguenti servizi di Windows Azure nell'applicazione:

  • database SQL di Windows Azure

  • Service Bus di Windows Azure

  • Servizio di archiviazione Windows Azure

  • Servizio di caching di Windows Azure

In ognuno di questi servizi possono verificarsi diversi errori temporanei. Pertanto, nel blocco di applicazioni per la gestione di errori temporanei vengono utilizzati criteri di rilevamento degli errori specifici per ogni servizio. Analogamente, per applicazioni diverse sono richieste strategie di gestione degli errori differenti. Per supportare queste differenze, tramite il blocco di applicazioni per la gestione di errori temporanei vengono forniti diversi approcci di logica di tentativi per affrontare i vari scenari di errori temporanei. Questi criteri predefiniti possono essere estesi creando classi personalizzate in cui vengono esposte interfacce ben definite.

L'utilizzo del blocco di applicazioni per la gestione di errori temporanei nelle applicazioni esistenti ha un impatto minimo. In base alla relativa progettazione, nel blocco di applicazioni per la gestione di errori temporanei sono disponibili molte classi e metodi di estensione tramite cui viene imitato il comportamento di un livello di accesso tipico ai dati ADO.NET.

Per dimostrare la facilità di utilizzo di questa libreria di applicazioni, nei paragrafi successivi viene illustrato come applicare il blocco di applicazioni per la gestione di errori temporanei al codice esistente. Nell'esempio seguente viene mostrato un metodo semplice tramite cui viene eseguita una query su un database e viene utilizzato il set di risultati:

        public static void ReadFromDB()
        {

            using (SqlConnection conn = new SqlConnection(connString))
            {
                try
                {
                    conn.Open();

                    SqlCommand selectCommand = 
new SqlCommand(@"SELECT SOH.SalesOrderID
                         FROM SalesLT.SalesOrderHeader SOH 
                         JOIN SalesLT.SalesOrderDetail SOD ON SOH.SalesOrderID = SOD.SalesOrderID
                         JOIN SalesLT.Product P ON SOD.ProductID = P.ProductID
                         JOIN SalesLT.Customer C ON SOH.CustomerID = C.CustomerID
                         JOIN SalesLT.CustomerAddress CA on C.CustomerID = CA.CustomerID
                         JOIN SalesLT.Address A on CA.AddressID = A.AddressID
                         WHERE A.City=@City", conn);

                    selectCommand.Parameters.Add(new SqlParameter("@City", SqlDbType.VarChar, 20, ParameterDirection.Input, false, 0, 0, "", DataRowVersion.Current, "London"));
                    selectCommand.CommandType = CommandType.Text;

                    IDataReader dataReader = selectCommand.ExecuteReader();

                    while (dataReader.Read())
                    {
                        Console.WriteLine("OrderID: {0}", dataReader["SalesOrderID"]);
                    }
                }
                catch (Exception e)
                {
                    Console.WriteLine("Exception: {0}",e.Message);
                }
            }

Per rendere più affidabile questo codice, definire innanzitutto una strategia di tentativi appropriata. La soluzione migliore è una strategia di tentativi incrementale. Per implementare questa strategia, utilizzare innanzitutto la classe Microsoft.Practices.EnterpriseLibrary.WindowsAzure.TransientFaultHandling.SqlAzure.SqlAzureTransientErrorDetectionStrategy. Tramite questa classe vengono intercettati i codici di errori correlati alle condizioni di errore temporanee. Quindi, sostituire la classe System.Data.SqlClient SqlConnection con la classe Microsoft.Practices.EnterpriseLibrary.WindowsAzure.TransientFaultHandling.SqlAzure.ReliableSqlConnection, come mostrato nell'esempio di codice seguente:

        public static void ReadFromDBWithReliableConnection()
        {

            // Define retry Strategy and Policy
            var retryStrategy = new Incremental(5, TimeSpan.FromSeconds(1), TimeSpan.FromSeconds(2));
            var retryPolicy = new RetryPolicy<SqlAzureTransientErrorDetectionStrategy>(retryStrategy);

            // Receive notifications about retries.
            retryPolicy.Retrying += new EventHandler<RetryingEventArgs>(retryPolicy_Retrying);

            using (ReliableSqlConnection conn = new ReliableSqlConnection(connString,retryPolicy))
            {
                try
                {
                    conn.Open();

                    SqlCommand selectCommand = new SqlCommand(@"SELECT SOH.SalesOrderID
                                        FROM SalesLT.SalesOrderHeader SOH 
                                        JOIN SalesLT.SalesOrderDetail SOD ON SOH.SalesOrderID = SOD.SalesOrderID
                                        JOIN SalesLT.Product P ON SOD.ProductID = P.ProductID
                                        JOIN SalesLT.Customer C ON SOH.CustomerID = C.CustomerID
                                        JOIN SalesLT.CustomerAddress CA on C.CustomerID = CA.CustomerID
                                        JOIN SalesLT.Address A on CA.AddressID = A.AddressID
                                        WHERE A.City=@City");

                    selectCommand.Parameters.Add(new SqlParameter("@City", SqlDbType.VarChar, 20, ParameterDirection.Input, false, 0, 0, "", DataRowVersion.Current, "London"));
                    selectCommand.CommandType = CommandType.Text;

                    IDataReader dataReader = conn.ExecuteCommand<IDataReader>(selectCommand);

                    while (dataReader.Read())
                    {
                        Console.WriteLine("OrderID: {0}", dataReader["SalesOrderID"]);
                    }
                }
                catch (Exception e)
                {
                    Console.WriteLine("Exception: {0}", e.Message);
                }
            }
        
        }

Nell'esempio di codice precedente, oltre a essere stata aggiunta la logica di tentativi appropriata, il codice SQLConnection esistente è stato sostituito con il codice ReliableSQLConnection. Per ridurre la quantità di codice da riscrivere, esiste un approccio alternativo, cioè l'utilizzo dei metodi di estensione forniti con il blocco di applicazioni per la gestione di errori temporanei. Tramite questo approccio non viene solo ridotta la quantità di riscrittura necessaria, bensì viene offerto un modo generico per aggiungere funzionalità di tentativi a un'applicazione ADO.NET. Per utilizzare i metodi di estensione, sostituire Open() e i vari metodi Execute (ad esempio ExecuteScalar(), ExecuteReader() o ExecuteNonQuery()) con i relativi equivalenti in cui è disponibile la funzionalità di tentativi, ad esempio OpenWithRetry() o ExecuteScalarWithRetry(). Questa condizione è illustrata nell'esempio di codice seguente:

        public static void ReadFromDBWithExecute()
        {

            // Define retry Strategy and Policy
            var retryStrategy = new Incremental(5, TimeSpan.FromSeconds(1), TimeSpan.FromSeconds(2));
            var retryPolicy = new RetryPolicy<SqlAzureTransientErrorDetectionStrategy>(retryStrategy);

            // Receive notifications about retries.
            retryPolicy.Retrying += new EventHandler<RetryingEventArgs>(retryPolicy_Retrying);

            try
            {
                retryPolicy.ExecuteAction(
                  () =>
                  {
                      using (SqlConnection conn = new SqlConnection(connString))
                      {
                          conn.OpenWithRetry();

                          SqlCommand selectCommand = new SqlCommand(@"SELECT SOH.SalesOrderID
                                                FROM SalesLT.SalesOrderHeader SOH 
                                                JOIN SalesLT.SalesOrderDetail SOD ON SOH.SalesOrderID = SOD.SalesOrderID
                                                JOIN SalesLT.Product P ON SOD.ProductID = P.ProductID
                                                JOIN SalesLT.Customer C ON SOH.CustomerID = C.CustomerID
                                                JOIN SalesLT.CustomerAddress CA on C.CustomerID = CA.CustomerID
                                                JOIN SalesLT.Address A on CA.AddressID = A.AddressID
                                                WHERE A.City=@City",conn);

                          selectCommand.Parameters.Add(new SqlParameter("@City", SqlDbType.VarChar, 20, ParameterDirection.Input, false, 0, 0, "", DataRowVersion.Current, "London"));
                          selectCommand.CommandType = CommandType.Text;

                          // Execute the above query using a retry-aware ExecuteCommand method which will
                          // automatically retry if the query has failed (or connection was dropped)
                          IDataReader dataReader = selectCommand.ExecuteReaderWithRetry(retryPolicy);
                          
                            while (dataReader.Read())
                            {
                                Console.WriteLine("OrderID: {0}", dataReader["SalesOrderID"]);
                            }                          
                      }
                  });
            }
            catch (Exception e)
            {
                Console.WriteLine("Exception: {0}", e.Message );
            }

        }

Il blocco di applicazioni per la gestione di errori temporanei supporta la dichiarazione di criteri di tentativi configurabili. Per ulteriori informazioni sulla dichiarazione di criteri di tentativi, vedere la pagina relativa alla specifica di strategie di tentativi nella configurazione

Negli esempi di codice mostrati in questa sezione viene fornito uno sguardo rapido sull'utilizzo del blocco di applicazioni per la gestione di errori temporanei. Per ulteriori informazioni sull'utilizzo di questa libreria di applicazioni, vedere l'esercitazione nella pagina Wiki di TechNet relativa alla logica di tentativi per errori temporanei nel database SQL di Windows Azure

Latenza di rete nel database SQL di Windows Azure

Oltre agli errori delle connessioni, la latenza di rete rappresenta l'altro problema di prestazioni maggiormente rilevato dagli utenti correnti del database SQL di Windows Azure.

Mentre l'impatto della latenza di Internet è ben noto, gli utenti tendono a sottovalutare l'impatto della latenza tra l'applicazione e il database SQL di Windows Azure. Anche quando l'applicazione e i database sono ospitati nello stesso data center, la latenza è generalmente più elevata rispetto a quella di un ambiente locale tradizionale. Questa latenza più elevata deriva dalla natura multi-tenant di Azure. Inoltre, a causa di questa latenza più elevata viene aumentato l'impatto di comportamenti di applicazioni "chatty", poiché in ogni chiamata al database si verificherà la latenza aggiuntiva che potrebbe determinare il calo complessivo delle prestazioni. Pertanto, per l'accesso a un database ospitato nel database SQL di Windows Azure da parte delle applicazioni "chatty" viene richiesto molto più tempo rispetto a un database di SQL Server ospitato localmente.

Oltre alla latenza tra l'applicazione e il database SQL di Windows Azure, si verifica una latenza maggiore nelle comunicazioni tra i diversi componenti distribuiti della soluzione. Questo tipo di latenza è forse una delle maggiori differenze fra le applicazioni locali e quelle cloud. Questo tipo di latenza viene trasferita per le comunicazioni sia tra l'utente e l'applicazione sia tra l'applicazione e il database SQL di Windows Azure.

Dalla prospettiva di utente finale, tutte queste cause della latenza di rete corrispondono al seguente tempo di risposta percepito da un utente:

Response Time = 2 x (Latency_1 + Latency_2) + Application_Processing_Time + Query_Exec_Time

Dove

  • Latency_1 è la latenza tra l'utente finale e il data center in cui è ospitata l'applicazione. Questo tipo di latenza può verificarsi anche in ambienti locali.

  • Latency_2 è la latenza tra l'applicazione e i database nel database SQL di Windows Azure.

Per garantire l'ottimizzazione delle prestazioni, è consigliabile effettuare innanzitutto le azioni di base seguenti:

  • Ridurre Latency_1 selezionando un data center più vicino alla maggior parte degli utenti.

  • Ridurre Latency_2 posizionando insieme i dati con l'applicazione Windows Azure per ridurre i round trip della rete.

  • Ridurre Application_Processing_Time e Query_Exec_Time attenendosi alle procedure consigliate generali che si utilizzerebbero per i database locali quando si accede al livello dati, si gestiscono le prestazioni e si scrive codice per l'ottimizzazione.

Ridurre la distanza tra dati e applicazioni

È importante tenere i database ospitati il più vicino possibile al punto in cui viene eseguita l'applicazione. Se l'applicazione viene eseguita nel data center che si trova negli Stati Uniti del Centro Nord e il database è ospitato nello stesso data center si otterrà il round trip più breve e, di conseguenza, la latenza più corta relativa alla distanza.

Anche se è possibile accedere a un database ospitato in Windows Azure da un'applicazione ospitata localmente, tenere in considerazione che questa condizione determinerà una latenza più elevata per l'accesso ai dati, nonché un costo per l'uscita dei dati dal data center.

Nei casi in cui l'accesso ai dati deve essere effettuato in più ubicazioni geografiche, utilizzare la rete per la distribuzione di contenuti per distribuire dati statistici in siti diversi. In alternativa, creare più copie di un database in data center diversi e utilizzare la Sincronizzazione dati SQL (anteprima) per sincronizzare i dati in questi data center. Questi approcci sono utili per le applicazioni che vengono eseguite in più siti geografici, in quanto consentono di individuare i dati più vicini alle diverse istanze dell'applicazione e di ridurre la latenza complessiva.

noteNota
La Sincronizzazione dati SQL (anteprima) è attualmente disponibile solo come anteprima ai fini esclusivi di valutazione del prodotto per versioni future e non deve essere utilizzata in ambienti di produzione.

Ridurre i round trip della rete

La riduzione dei round trip della rete, sebbene importante per l'applicazione locale, è fondamentale in Windows Azure. Le query elaborate dal database SQL di Windows Azure devono essere applicate ai livelli di bilanciamento del carico della rete, nonché al gateway del protocollo del flusso TDS prima di essere ricevute dal database SQL di Windows Azure. Tramite questa astrazione disponibile nel database SQL di Windows Azure vengono offerte all'utente finale funzionalità di scala e disponibilità, ma è anche richiesta una certa quantità di elaborazione che determina una latenza di piccole dimensioni in ogni round trip. Nelle applicazioni tramite cui vengono inviati dati al database SQL di Windows Azure attraverso molti round trip è possibile riscontrare un calo significativo delle prestazioni.

Per ridurre gli effetti dei round trip, attenersi alle stesse procedure consigliate che si utilizzerebbero per le applicazioni locali:

  • Utilizzare le stored procedure, in particolare per incapsulare la logica di accesso ai dati complessi e i comportamenti transazionali: quando si effettuano chiamate sequenziali in cui la seconda chiamata dipende dai dati restituiti dalla prima, se si utilizza una stored procedure per eseguire la logica tramite cui viene effettuata la seconda chiamata, vengono eliminati uno o più round trip e vengono accelerate le prestazioni. Tramite questo approccio verranno ridotti in modo naturale i round trip, nonché il blocco e l'utilizzo delle risorse sul lato server.

  • Ridurre l'utilizzo dei cursori o dell'accesso riga per riga: dove possibile, utilizzare le operazioni basate su set. Se è necessario utilizzare i cursori, considerare quelli sul lato client.

  • Utilizzare i parametri con valori di tabella per inviare più righe al database SQL di Windows Azure in ogni round trip: nel database SQL di Windows Azure vengono utilizzati parametri con valori di tabella, come avviene nelle versioni locali del motore di database di SQL Server. Tramite i parametri con valori di tabella è possibile ridurre più chiamate alla stessa stored procedure per elaborare un set di record/valori. È anche possibile passare parametri tabulari a una singola query con parametri, ad esempio un comando SELECT, INSERT, UPDATE o DELETE.
    Per ulteriori informazioni, vedere il seguente argomento della documentazione online Utilizzare parametri con valori di tabella.

  • Utilizzare la memorizzazione nella cache locale, dove possibile: tramite la memorizzazione nella cache locale è possibile riutilizzare gli stessi risultati senza numerosi round trip al database SQL di Windows Azure. Inoltre, tenere in considerazione che è possibile memorizzare nella cache le chiamate per archiviare le procedure tramite cui viene restituito lo stesso valore, se quello specificato è uguale.

  • Utilizzare la memorizzazione nella cache di Windows Azure, dove possibile: utilizzare la memorizzazione nella cache di Windows Azure per i dati di ricerca di sola lettura per ridurre il traffico di rete nel database SQL di Windows Azure. Per ulteriori informazioni, vedere la pagina relativa alla riduzione dei round trip della rete utilizzando la memorizzazione nella cache di Windows Azure.

  • Memorizzare nella cache i metadati e i dati, dove possibile.

  • Evitare il recupero dei metadati in fase di esecuzione, se possibile.

  • Evitare classi come SqlCommandBuilder: tramite queste classi viene eseguita una query sui metadati in fase di esecuzione, pertanto si verificano round trip aggiuntivi.

  • Includere in batch le istruzioni SQL, se possibile: è possibile concatenare più istruzioni Transact-SQL in un unico comando batch per recuperare più set di risultati o eseguire più operazioni DML in un singolo round trip della rete. Questo approccio è particolarmente utile in caso di grandi quantità di operazioni INSERT consecutive.

  • Evitare la gestione di transazioni basate su applicazioni: l'incapsulamento di operazioni di gestione delle transazioni, ad esempio BEGIN TRAN, COMMIT/ROLLBACK, nelle stored procedure può determinare la riduzione dei round trip e dei blocchi della rete.

Attenersi alle procedure consigliate generali per i database locali

Dopo aver ridotto la distanza tra i dati e gli utenti e i round trip della rete, è necessario assicurarsi che nell'applicazione vengono seguite le procedure consigliate generali per i database locali. Applicando le procedure consigliate e le indicazioni note a livello di accesso ai dati dell'applicazione, nonché le procedure consigliate relative alle prestazioni e all'ottimizzazione, si dovrebbero notare numerosi vantaggi in un ambiente a latenza elevata come il cloud.

Nelle procedure consigliate generali per l'interazione del database con i database locali sono incluse le indicazioni seguenti:

  • Aprire una connessione in un secondo momento e chiuderla appena possibile: per ridurre l'utilizzo di risorse e la possibilità di limitazioni, aprire una connessione nell'applicazione solo nel momento in cui è richiesta dal codice. Inoltre, restituire la connessione al pool non appena l'utilizzo della connessione da parte del codice termina, eliminando l'oggetto connessione. Esiste, tuttavia, una condizione di eccezione a questi criteri di restituzione, cioè se è necessario completare un lavoro immediato, la connessione deve essere restituita solo al termine del lavoro in questione.

  • Utilizzare il pool di connessioni: a livello di processo, nei pool di connessioni saranno incluse connessioni in cui viene utilizzato lo stesso contesto di sicurezza e la cui destinazione è costituita dallo stesso database. Dove possibile, utilizzare la stessa stringa di connessione per tutte le connessioni con caratteristiche uguali.

  • Recuperare solo i dati necessari: definire attentamente l'elenco SELECT e la clausola WHERE. Tramite questo approccio è possibile ridurre l'utilizzo della larghezza di banda della rete, nonché indicizzare in modo efficiente il database per le prestazioni.

  • Mantenere più corte possibili le transazioni ed evitare il coinvolgimento di risorse non necessarie: la progettazione di modelli di dati non ottimali e round trip eccessivi tra il codice dell'applicazione e i database sono problemi comuni, ma, grazie a un ambiente di connettività a latenza bassa, potrebbero non essere critici nelle distribuzioni locali. Di seguito sono riportati i motivi per cui anche la modifica di queste applicazioni potrebbe essere difficile:

    • Vincoli di architettura esistenti.

    • Progettazione monolitica in cui l'accesso ai dati e la logica di business sono strettamente connessi e interdipendenti.

    • Aspetti, come l'elaborazione dei dati riga per riga, richiesti dalla logica dell'applicazione stessa e difficili da modificare senza un notevole lavoro di riscrittura.

Oltre a queste procedure consigliate generali, ne esistono altre correlate alle tecnologie utilizzate nell'applicazione. Ad esempio, nelle applicazioni in cui viene utilizzato .NET Framework è possibile utilizzare tecnologie come ADO.NET, Entity Framework e WCF Data Services. Queste tecnologie offrono tempi di sviluppo ridotti e una flessibilità elevata per l'implementazione del livello di accesso ai dati in qualsiasi stile dell'applicazione. Queste tecnologie si adattano anche bene all'orientamento di un servizio separando i livelli, offrendo flessibilità dello schema, utilizzando architetture di dati aperti (ad esempio OData) e fornendo progettazione "disconnessa" per natura. Tuttavia, nonostante i vantaggi, tramite queste tecnologie potrebbero verificarsi gli stessi problemi descritti per le applicazioni legacy, ad esempio la condizione "chatty", se non vengono prese in considerazione una progettazione appropriata dei dati e un'ottimizzazione delle operazioni, in cui sono inclusi una rappresentazione ottimale dei dati, l'utilizzo di cache e l'inclusione in batch di operazioni correlate ai dati per ridurre i round trip non necessari.

Nelle sezione seguenti vengono descritte alcune delle procedure consigliate per queste tecnologie e viene illustrato l'utilizzo della programmazione asincrona nelle applicazioni Azure.

Procedure consigliate per ODBC e JDBC

Per le librerie di accesso ai dati, ad esempio ODBC e JDBC, in cui il supporto lato client per operazioni intelligenti (ad esempio l'ordinamento, l'applicazione di filtri e così via) è limitato, è ancora possibile applicare le tecniche di ottimizzazione esistenti come la riduzione delle operazioni basate su cursore e l'elaborazione riga per riga. Se è necessario utilizzare i cursori, considerare quelli di sola lettura o forward-only per recuperare i valori e utilizzare i comandi SQL per apportare modifiche ai dati invece di utilizzare gli aggiornamenti posizionati nei cursori.

Procedure consigliate per ADO.NET

In ADO.NET sono disponibili diverse ottimizzazioni che possono essere applicate per migliorare l'efficienza del codice di accesso ai dati:

  • Scegliere la modalità di esecuzione appropriata con SqlCommand: ad esempio se è necessario solo recuperare un valore scalare, utilizzare il metodo ExecuteScalar() oppure ExecuteNonQuery(), se non occorre recuperare un set di risultati.

  • Scegliere la proprietà UpdateBatchSize quando si utilizza la classe SqlDataAdapter per eseguire più operazioni: in questo modo, vengono inclusi in un batch più comandi durante la relativa trasmissione e si riducono i round trip della rete.

  • Utilizzare SqlDataAdapter per implementare interazioni dirette del database tramite stored procedure per le operazioni SELECT, INSERT, UPDATE e DELETE.

  • Impostare la proprietà SerializationFormat su Binario quando i database vengono utilizzati come cache lato client: in questo modo si riduce la quantità di dati trasmessi nella rete.

Procedure consigliate per Entity Framework

Per quanto riguarda lo sviluppo dell'accesso ai dati, Entity Framework risulta molto interessante per i motivi seguenti:

  • Offre un ambiente di object-relational mapping avanzato tramite cui è possibile ridurre notevolmente il tempo necessario per lo sviluppo.

  • Viene introdotta una maggiore flessibilità separando la definizione fisica dello schema del database dalla rappresentazione concettuale dei dati dell'applicazione.

  • Viene fornito un set completo di servizi utili per la persistenza.

  • Vengono ridotti i round trip della rete grazie alla possibilità di caricare set di risultati dal database SQL di Windows Azure in set di oggetti disponibili nella memoria dell'applicazione e di riutilizzarli in modo disconnesso senza dover interagire con il back-end per ogni operazione.

Tuttavia, come con qualsiasi altro strumento di programmazione, tramite Entity Framework possono verificarsi alcuni problemi di prestazioni, se non viene prestata un'attenzione particolare alle interazioni del database. Inoltre, questi problemi di prestazioni aumentano nell'ambiente di Windows Azure.

Per ottimizzare l'utilizzo di Entity Framework con il database SQL di Windows Azure, attenersi alle linee guida delle procedure consigliate:

  • Disabilitare in modo esplicito il rilevamento dello stato dell'oggetto a livello ObjectStateManager sia per le entità sia per le relazioni: applicare questa linea guida se nell'applicazione non è necessario rilevare lo stato dell'oggetto poiché si tratta di un classico utilizzo di sola lettura.

  • Disabilitare il caricamento lazy per controllare meglio l'interazione tra il codice e il database: per ridurre i round trip, è consigliabile precaricare tutti gli elementi necessari in una singola interazione. È possibile includere in un batch più comandi durante il caricamento e il mantenimento dei dati nel relativo archivio applicabile estendendo il contesto dell'oggetto con metodi specifici.

  • Utilizzare stored procedure per le interazioni dell'archivio dati, dove possibile: nei casi in cui non è possibile utilizzare le stored procedure, utilizzare le query con parametri e le viste indicizzate per migliorare le prestazioni.

  • Eseguire operazioni in più database in un singolo round trip integrando parametri con valori di tabella ed eseguendo il mapping di set di oggetti ai parametri tabulari delle stored procedure: è possibile utilizzare questo approccio anche se non è direttamente supportato dagli strumenti di progettazione.

  • Dove possibile, eseguire il mapping di più set di risultati agli oggetti in un'unica operazione.

  • Eseguire il mapping di set di oggetti al metodo System.Data.SqlClient.SqlBulkCopy.WriteToServer() per attività di inserimento di grandi quantità di dati: tramite il metodo SQLBulkCopy è possibile consentire l'utilizzo di ottimizzazioni della registrazione di operazioni bulk nel motore di database di SQL Server e nel database SQL di Windows Azure. In questo modo, è possibile effettuare più rapidamente e in molti casi inserimenti di grandi dimensioni.

Per ulteriori informazioni, vedere Utilizzo di Entity Framework per ridurre la latenza di rete verso il database SQL di Windows Azure.

Procedure consigliate per la programmazione asincrona

Per il completamento di alcune operazioni del database, ad esempio le esecuzioni di comandi, può essere richiesto molto tempo. In questi casi, tramite le applicazioni a thread singolo è necessario bloccare le altre operazioni e attendere il completamento del comando prima di riprenderle. Invece, tramite l'assegnazione di un'operazione con esecuzione prolungata a un thread in background è possibile mantenere attivo il thread in primo piano per tutta l'operazione.

ADO.NET supporta questi stessi modelli di progettazione nella relativa classe SqlCommand. In particolare, accoppiando i metodi BeginExecuteNonQuery(), BeginExecuteReader() e BeginExecuteXmlReader() con, rispettivamente, i metodi EndExecuteNonQuery(), EndExecuteReader() e EndExecuteXmlReader() viene fornito un supporto asincrono.

Nonostante l'utilizzo di questi metodi asincroni, sarà comunque necessario applicare tutte le ottimizzazioni e le procedure consigliate illustrate nelle sezioni precedenti. Tuttavia, grazie all'esecuzione in parallelo di altre operazioni con la query nel database SQL di Windows Azure, tramite questi metodi asincroni è possibile ridurre l'impatto delle operazioni del database a esecuzione prolungata nel livello di accesso ai dati.

Il documento è risultato utile?
(1500 caratteri rimanenti)
Grazie per i commenti inviati.

Aggiunte alla community

Mostra:
© 2014 Microsoft