Mysql
 sql >> Database >  >> RDS >> Mysql

AGGIORNAMENTO MySQL:i 5 migliori suggerimenti per gli sviluppatori T-SQL

Stai aggiungendo MySQL al tuo elenco di skillset di database? Quindi l'istruzione MySQL UPDATE è uno dei comandi che devi imparare.

Stiamo continuando il nostro viaggio verso MySQL dal punto di vista di SQL Server. È iniziato con CREATE TABLE, seguito da INSERT, e il pezzo più recente riguardava DELETE. Oggi UPDATE è il nostro punto focale.

Le differenze sono sottili e facili da imparare. Ma proprio come negli articoli precedenti, il nostro obiettivo è di averti subito operativo. Ma prima di procedere, chiariamo questi elementi:

  • Gli esempi qui utilizzati sono stati eseguiti su MySQL 8.0.23 utilizzando il motore di archiviazione InnoDB.
  • Abbiamo utilizzato SQL Server 2019.

Prepara i dati di esempio

Non possiamo procedere senza dati di esempio. Vorrei mettere a proprio agio gli sviluppatori T-SQL in questo esercizio. Quindi, importiamo alcune tabelle familiari in AdventureWorks database di esempio da SQL Server:

  • Prodotto
  • Intestazione ordine di vendita
  • Dettagli dell'ordine di vendita

Per importare queste tabelle in MySQL, ho usato dbForge Studio per MySQL. Ecco i passaggi:

  1. Crea un nuovo database chiamato adventureworks2019 .
  2. Fai clic con il pulsante destro del mouse su adventureworks2019 e seleziona Strumenti .
  3. Seleziona Importa dati . Apparirà una nuova finestra.
  4. Seleziona ODBC . Devi creare un DSN utente per connetterti al tuo SQL Server e ad AdventureWorks banca dati.
  5. Fai clic su Avanti .
  6. Seleziona la tabella che desideri importare, la connessione MySQL e il database di destinazione (adventureworks2019 ).
  7. Fai clic su Avanti .
  8. Cambia le impostazioni della colonna. Puoi anche vedere dati di esempio. Puoi ignorarlo facendo clic su Avanti oppure modifica le impostazioni come meglio credi.
  9. Fai clic su Importa .
  10. Importa la tabella successiva seguendo le stesse istruzioni sullo schermo.
  11. Fai clic su Fine .

Dopo aver importato queste tabelle, sei pronto per gli esempi in questo articolo. Quindi, iniziamo.

1. Nozioni di base sulla sintassi

La sintassi dell'istruzione MySQL UPDATE è la seguente:

UPDATE [LOW_PRIORITY] [IGNORE] table_references
    SET assignment_list
    [WHERE where_condition]
    [ORDER BY ...]
    [LIMIT row_count]

Riesco quasi a sentirti dopo aver letto la sintassi:LOW PRIORITY, IGNORE, ORDER BY e LIMIT non vanno bene! Iniziamo a discutere dall'alto.

Innanzitutto, LOW_PRIORITY è una parola chiave estranea per noi perché SQL Server non la supporta. È facoltativo, ma se lo includi, gli aggiornamenti vengono ritardati finché tutti gli altri client non leggono la tabella.

Un'altra parola chiave aliena è IGNORARE. È anche facoltativo, ma se lo includi e si verificano duplicati, non verrà generato un errore. Per errori più ignorabili, controlla questo link.

Quindi, ORDINA PER. Sappiamo a cosa serve. Ma provalo in SQL Server Management Studio e le linee ondulate appariranno sotto le parole chiave.

Infine, LIMITE. È lo stesso di TOP in SQL Server. Maggiori informazioni e ORDINA PER in una sezione successiva.

Queste sono le differenze evidenti. Continua a leggere nelle prossime 2 sottosezioni.

MySQL UPDATE singola colonna

L'aggiornamento di una singola colonna è quasi simile. Quindi, l'esempio seguente produrrà lo stesso risultato da entrambe le piattaforme di database. Si noti, tuttavia, che invece dei backtick, SQL Server utilizza parentesi quadre.

-- MySQL UPDATE single column
UPDATE `production.product`
SET ReorderPoint = 650
WHERE ProductID = 316;

Ecco una sintassi T-SQL equivalente:

-- T-SQL UPDATE single column
UPDATE [Production].[Product]
SET ReorderPoint = 650
WHERE ProductID = 316;

Il valore assegnato a una colonna può essere qualsiasi espressione a valore singolo purché il tipo restituito sia lo stesso del tipo di dati della colonna.

AGGIORNAMENTO MySQL di più colonne

Anche l'aggiornamento di più colonne è quasi simile a T-SQL. Ecco un esempio:

UPDATE `production.product`
SET ReorderPoint = 650, SafetyStockLevel = 1200
WHERE ProductID = 316;

Per aggiornare più colonne, separa semplicemente le coppie di valori di colonna con una virgola. Ancora una volta, l'unica differenza qui sono i backtick.

Finora, questi sono tutti aggiornamenti di una singola tabella. Passiamo a MySQL UPDATE da un'altra tabella.

2. AGGIORNAMENTO MySQL con JOIN

Ci sono piccole differenze che vedrai quando aggiorni una tabella con join. Il modo migliore per mostrarlo è attraverso un esempio di utilizzo di 3 tabelle.

UPDATE `sales.salesorderdetail` sod
INNER JOIN `sales.salesorderheader` soh ON sod.SalesOrderID = soh.SalesOrderID
INNER JOIN `production.product` p ON sod.ProductID = p.ProductID
set UnitPrice = p.ListPrice
WHERE p.ProductID = 758
AND soh.OrderDate = '2012-04-30';

Si noti che alcune clausole sono disposte in modo diverso rispetto a SQL Server. I join vengono visualizzati prima della clausola SET. Non c'è neanche una clausola FROM. Come puoi aspettarti, SQL Server Management Studio inserisce linee ondulate per la sintassi offensiva. Vedi questo e la sintassi T-SQL corretta nella Figura 1 di seguito.

Prima dell'aggiornamento, il valore del prezzo unitario è 874,7940 come mostrato nella Figura 2.

Dopo l'aggiornamento, UnitPrice viene aggiornato dal Prodotto PrezzoLista della tabella . Vedi figura 3.

Oltre a INNER JOIN, puoi utilizzare LEFT o RIGHT JOIN a seconda delle tue esigenze.

3. AGGIORNAMENTO MySQL con sottoquery

È possibile utilizzare l'istruzione MySQL UPDATE da un'altra tabella utilizzando una sottoquery. La query con un join nella sezione precedente può essere riscritta utilizzando una sottoquery. I risultati saranno gli stessi. Ecco:

UPDATE `sales.salesorderdetail` sod
INNER JOIN `sales.salesorderheader` soh ON sod.SalesOrderID = soh.SalesOrderID
SET sod.UnitPrice = (select ListPrice from `production.product` WHERE ProductID = 758)
WHERE sod.ProductID = 758
AND soh.OrderDate = '2012-04-30';

L'approccio è diverso, ma il risultato è lo stesso della Figura 3. Tuttavia, si noti che la sottoquery utilizzata per aggiornare una colonna dovrebbe restituire 1 valore.

C'è un altro modo per esprimere questa istruzione MySQL UPDATE.

4. AGGIORNAMENTO MySQL con CTE

Le Common Table Expressions (CTE) sono supportate sia in MySQL che in SQL Server. Se non hai dimestichezza con i CTE, consulta l'articolo precedente.

Ora, ecco l'istruzione equivalente con CTE utilizzata.

WITH priceIncrease AS
(
  SELECT soh.SalesOrderID, p.ProductID, p.ListPrice
  FROM `sales.salesorderdetail` sod
  INNER JOIN `sales.salesorderheader` soh ON sod.SalesOrderID = soh.SalesOrderID
  INNER JOIN `production.product` p ON sod.ProductID = p.ProductID
  WHERE p.ProductID = 758
  AND soh.OrderDate = '2012-04-30'
)
UPDATE `sales.salesorderdetail` s
INNER JOIN priceIncrease pi ON s.SalesOrderID = pi.SalesOrderID AND s.ProductID = pi.ProductID
SET s.UnitPrice = pi.ListPrice

SQL Server supporta lo stesso concetto, ma senza backtick. Il risultato sarà lo stesso della Figura 3.

Potresti chiedere, quale dei 3 approcci è migliore? Confronteremo ulteriormente le loro prestazioni.

5. AGGIORNAMENTO MySQL con LIMIT

MySQL UPDATE può limitare il numero di righe da aggiornare con la parola chiave LIMIT. Supponiamo di voler aggiornare 5 record nel Prodotto tavolo. Possiamo esprimere l'affermazione in questo modo:

UPDATE `production.product` p
SET p.StandardCost = p.StandardCost + 10, p.ListPrice = p.ListPrice + 10
ORDER BY p.ProductID
LIMIT 5;

Questo ordinerà i record in base a ProductID e quindi aggiornare i primi 5 record. Si ferma dopo il 5° record.

La controparte di LIMIT di SQL Server è TOP. Tuttavia, non puoi semplicemente modificare la parola chiave LIMIT su TOP e aspettarti che funzioni in SQL Server. Ecco la versione modificata in T-SQL che darà lo stesso risultato:

UPDATE Production.Product
SET StandardCost += 10, ListPrice += 10
WHERE ProductID IN (SELECT TOP 5 ProductID 
		    FROM Production.Product 
		    ORDER BY ProductID)

La logica è un po' diversa. Aggiorna StandardCost e Prezzo di listino colonne basate sui ProductID trovati nella sottoquery. La subquery, invece, restituisce i primi 5 record del Prodotto tabella ordinata per ProductID .

Sebbene TOP sia supportato anche in T-SQL UPDATE, ORDER BY non lo è. Pertanto, l'utilizzo di TOP con UPDATE modificherà i record casuali. La sintassi di cui sopra è applicabile per i record ordinati con TOP.

Prestazioni AGGIORNAMENTO MySQL

In precedenza, avevamo un'istruzione UPDATE con gli stessi risultati anche se utilizzavamo metodi diversi. Abbiamo usato JOIN, subquery e CTE. Quale di loro funzionerà meglio?

Esiste anche un piano di esecuzione in MySQL che utilizza la parola chiave EXPLAIN. La sintassi è questa:

EXPLAIN [FORMAT=JSON]
<SQL statement>

Senza il formato JSON, hai informazioni di base come tabelle, chiavi di indice utilizzate e righe scansionate. Quando viene specificato il formato JSON, hai informazioni più dettagliate. dbForge Studio per MySQL include un Query Profiler oltre al risultato di EXPLAIN. MySQL Workbench include un Visual EXPLAIN in cui puoi vedere una vista grafica del piano basato su EXPLAIN FORMAT=JSON.

Ora che conosciamo le istruzioni della riga di comando e gli strumenti grafici, come possiamo usarli per confrontare metodi diversi?

Prima di procedere, permettimi di essere onesto. La mia competenza in SQL Server è superiore a quella in MySQL. Potrei perdere qualcosa lungo la strada o sbagliarmi. Puoi colmare le lacune nella sezione Commenti in seguito.

Analisi dei risultati EXPLAIN per UPDATE con JOIN

La prima volta che ho eseguito l'istruzione MySQL UPDATE con JOIN, sono stati necessari 11,3 secondi per l'aggiornamento di 24 righe. Incredibile, vero?

Ecco cosa è successo come visto in dbForge Studio. Dai un'occhiata alla Figura 4 di seguito.

Cosa ci dice la Figura 4?

  1. Ci sono i 3 alias di tabella utilizzati. Tutti e 3 hanno tipi di accesso di TUTTI. Significa che MySQL ha utilizzato Table Scan per tutti e 3.
  2. Guarda la chiave colonna. Non viene visualizzato nulla su tutte e 3 le tabelle, il che significa che non sono state utilizzate chiavi di indice. Ciò supporta il punto precedente di Scansione tabella.
  3. Infine, le righe colonna. Indica quante righe MySQL ritiene di dover scansionare per ottenere il risultato finale. Per 24 righe aggiornate, migliaia di righe sono state scansionate per SalesOrderHeader e Dettagli dell'ordine di vendita . Nel frattempo, tutte le righe del Prodotto la tabella è stata scansionata.

Mi sono grattato la testa dopo aver appreso questo. Mi sono reso conto che quando importavo le tabelle da SQL Server, venivano importati solo la struttura delle tabelle ei dati, non gli indici .

Quindi, ho creato indici e chiavi primarie appropriati in dbForge Studio. Ecco cosa ho creato:

  • Ho creato il ProductID nel Prodotto tabella una chiave primaria.
  • Ho anche aggiunto SalesOrderID come chiave primaria in SalesOrderHeader tavolo. Quindi, ho creato un indice per OrderDate anche.
  • Infine, ho creato SalesOrderDetailID in Dettagli ordine di vendita tabella una chiave primaria. Ho anche aggiunto un indice per SalesOrderID e ID prodotto colonne di questa tabella.

Successivamente, ho generato un nuovo piano di esecuzione per la stessa query per vedere i miglioramenti. Il risultato?

AUMENTO DELLA VELOCITÀ DOPO L'AGGIUNTA DEGLI INDICI

Il tempo di esecuzione è stato ridotto da 11,3 secondi a 0,019 secondi. Molto bello!

Controlliamo il nuovo piano utilizzando dbForge Studio nella Figura 5 di seguito.

Cosa ci dice la Figura 5?

  • L'accesso tipi di 3 tabelle sono state cambiate. I 2 valori da evitare qui sono ALL e INDEX, specialmente su tabelle di grandi dimensioni. ALL è Table Scan e INDEX è Index Scan.
  • La chiave colonna ora include gli indici utilizzati. Questo è buono. Sono stati utilizzati tutti gli indici aggiunti.
  • Le righe colonna ora mostra cifre più piccole. Gli indici aggiunti hanno ridotto molto l'I/O sulla nostra query.

Per ulteriori informazioni sui dettagli e sui valori di EXPLAIN, controlla questa documentazione ufficiale.

Ma come si confronta con MySQL UPDATE con sottoquery?

Analisi dei risultati EXPLAIN per UPDATE con subquery

La query precedente per aggiornare UnitPrice colonna ha un'altra alternativa alla query, che utilizza una sottoquery. Come si confronta con il JOIN? Dai un'occhiata alla Figura 6 di seguito.

La figura 6 mostra:

  • I valori delle colonne di tipo, chiave e righe sono gli stessi rispetto all'utilizzo di JOIN. Questo è logico poiché dovrebbe avere gli stessi risultati.
  • Il tempo di esecuzione è stato un po' più veloce. Questo non accadrà ogni volta, però. Dipende dalle attuali risorse disponibili. Anche la differenza di velocità è trascurabile. Non lo sentirai affatto.

Un altro modo è utilizzare EXPLAIN FORMAT=JSON per ottenere maggiori informazioni sul piano. Al momento del controllo, i valori del costo della query (84,79) e delle informazioni sui costi sono gli stessi.

Ora, confrontiamolo con MySQL UPDATE con CTE.

Analisi dei risultati di EXPLAIN per UPDATE con CTE

Utilizzo di CTE come base per l'aggiornamento di UnitPrice colonna è come avere prima una tabella temporanea e poi unire la tabella temporanea a SalesOrderDetails . A prima vista, potrebbe sembrare che non sia una buona opzione rispetto alle prime due. Ma ci mostra che è possibile avere un aggiornamento in MySQL usando CTE. Può essere una buona opzione in altre situazioni. Ad ogni modo, abbiamo i risultati di EXPLAIN per questo approccio.

Se non hai dbForge Studio per MySQL, puoi provare a produrre risultati EXPLAIN usando il comando in qualsiasi altro editor. Ecco un esempio:

EXPLAIN
WITH priceIncrease AS
(
  SELECT soh.SalesOrderID, p.ProductID, p.ListPrice
  FROM `sales.salesorderdetail` sod
  INNER JOIN `sales.salesorderheader` soh ON sod.SalesOrderID = soh.SalesOrderID
  INNER JOIN `production.product` p ON sod.ProductID = p.ProductID
  WHERE p.ProductID = 758
  AND soh.OrderDate = '2012-04-30'
)
UPDATE `sales.salesorderdetail` s
INNER JOIN priceIncrease pi ON s.SalesOrderID = pi.SalesOrderID AND s.ProductID = pi.ProductID
SET s.UnitPrice = pi.ListPrice

Il risultato è nella Figura 7 di seguito.

La figura 7 mostra:

  • Sono state utilizzate 4 tabelle anziché 3. Il primo utilizzo di SalesOrderDetail si trova nel CTE e quindi nell'istruzione UPDATE.
  • Più tabelle significano più righe rispetto ai 2 approcci precedenti.

Sorprendentemente, questo ha funzionato a 0,015 secondi (non mostrato nella figura). Lo stesso vale per l'utilizzo di una sottoquery. Tuttavia, non accadrà ogni volta. Dipende dalle risorse di sistema disponibili al momento dell'esecuzione.

Il costo totale della query è 166,69. È superiore ai 2 approcci precedenti. Minore è il costo della query, migliori saranno le prestazioni nel tempo.

Da asporto

Abbiamo approfondito le differenze tra MySQL e l'istruzione UPDATE di SQL Server. Abbiamo imparato come si fa durante l'aggiornamento

  • una singola colonna
  • più colonne
  • tabelle con un join
  • colonne che utilizzano una sottoquery
  • tabelle con CTE
  • con un LIMITE

In questo post, hai anche avuto un'anteprima di EXPLAIN e di come utilizzarlo per confrontare diversi approcci UPDATE.

Spero che questo possa esserti utile mentre impari MySQL proveniente da SQL Server. Se ti piace questo post, condividilo sulle tue piattaforme di social media preferite. E se manca qualcosa, faccelo sapere nella sezione Commenti.

Buona codifica!