Mysql
 sql >> Base de Dados >  >> RDS >> Mysql

UPDATE MySQL:as 5 principais dicas para desenvolvedores T-SQL


Você está adicionando o MySQL à sua lista de conjuntos de habilidades de banco de dados? Então a instrução MySQL UPDATE é um dos comandos que você precisa aprender.

Continuamos nossa jornada para o MySQL do ponto de vista do SQL Server. Começou com CREATE TABLE, seguido por INSERT, e a parte mais recente foi sobre DELETE. Hoje, UPDATE é nosso ponto focal.

As diferenças são sutis e fáceis de aprender. Mas, assim como nos artigos anteriores, nosso objetivo é colocar você em funcionamento rapidamente. Mas antes de prosseguirmos, vamos deixar esses itens claros:
  • Os exemplos usados ​​aqui foram executados no MySQL 8.0.23 usando o mecanismo de armazenamento InnoDB.
  • Usamos o SQL Server 2019.

Prepare os dados de amostra


Não podemos prosseguir sem dados de amostra. Eu gostaria de colocar os desenvolvedores T-SQL em casa neste exercício. Então, vamos importar algumas tabelas familiares para o AdventureWorks banco de dados de exemplo do SQL Server:
  • Produto
  • SalesOrderHeader
  • Detalhes do pedido de vendas

Para importar essas tabelas para o MySQL, usei o dbForge Studio for MySQL. Aqui estão os passos:
  1. Crie um novo banco de dados chamado adventureworks2019 .
  2. Clique com o botão direito do mouse em adventureworks2019 e selecione Ferramentas .
  3. Selecione Importar dados . Uma nova janela aparecerá.
  4. Selecione ODBC . Você precisa criar um DSN de usuário para se conectar ao SQL Server e ao AdventureWorks banco de dados.
  5. Clique em Avançar .
  6. Selecione a tabela que você precisa importar, a conexão MySQL e o banco de dados de destino (adventureworks2019 ).
  7. Clique em Avançar .
  8. Altere as configurações da coluna. Você também pode ver dados de exemplo. Você pode pular isso clicando em Próximo ou altere as configurações como achar melhor.
  9. Clique em Importar .
  10. Importe a próxima tabela seguindo as mesmas instruções na tela.
  11. Clique em Concluir .

Depois de importar essas tabelas, você está pronto para os exemplos deste artigo. Então, vamos começar.

1. Noções básicas de sintaxe


A sintaxe da instrução MySQL UPDATE é assim:
UPDATE [LOW_PRIORITY] [IGNORE] table_references
    SET assignment_list
    [WHERE where_condition]
    [ORDER BY ...]
    [LIMIT row_count]

Eu quase posso ouvir você depois de ler a sintaxe:LOW PRIORITY, IGNORE, ORDER BY e LIMIT não se encaixam! Vamos começar a discutir de cima.

Primeiro, LOW_PRIORITY é uma palavra-chave estranha para nós porque o SQL Server não a suporta. É opcional, mas se você incluí-lo, as atualizações serão atrasadas até que todos os outros clientes não estejam lendo a tabela.

Outra palavra-chave alienígena é IGNORE. Também é opcional, mas se você incluí-lo e ocorrerem duplicatas, um erro não será gerado. Para mais erros ignoráveis, confira este link.

Então, ORDEM POR. Sabemos para que serve. Mas tente no SQL Server Management Studio e linhas onduladas aparecerão abaixo das palavras-chave.

Por fim, LIMITE. Isso é o mesmo que TOP no SQL Server. Mais disso e ORDER BY em uma seção posterior.

Essas são as diferenças óbvias. Leia mais nas próximas 2 subseções.

Atualização do MySQL Coluna Única


Atualizar uma única coluna é quase semelhante. Portanto, o exemplo abaixo produzirá o mesmo resultado de ambas as plataformas de banco de dados. Observe, no entanto, que em vez de acentos graves, o SQL Server usa colchetes.
-- MySQL UPDATE single column
UPDATE `production.product`
SET ReorderPoint = 650
WHERE ProductID = 316;

Aqui está uma sintaxe T-SQL equivalente:
-- T-SQL UPDATE single column
UPDATE [Production].[Product]
SET ReorderPoint = 650
WHERE ProductID = 316;

O valor atribuído a uma coluna pode ser qualquer expressão de valor único, desde que o tipo retornado seja o mesmo que o tipo de dados da coluna.

Atualização do MySQL várias colunas


A atualização de várias colunas também é quase semelhante ao T-SQL. Aqui está um exemplo:
UPDATE `production.product`
SET ReorderPoint = 650, SafetyStockLevel = 1200
WHERE ProductID = 316;

Para atualizar várias colunas, basta separar os pares de valor de coluna com uma vírgula. Novamente, a única diferença aqui são os backticks.

Até agora, essas são todas as atualizações de tabela única. Vamos passar para MySQL UPDATE de outra tabela.

2. UPDATE MySQL com JOIN


Existem pequenas diferenças que você verá ao atualizar uma tabela com junções. A melhor maneira de mostrar isso é através de um exemplo de uso de 3 tabelas.
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';

Observe que algumas cláusulas são organizadas de forma diferente quando comparadas ao SQL Server. As junções aparecem primeiro antes da cláusula SET. Também não há cláusula FROM. Como você pode esperar, o SQL Server Management Studio colocará linhas onduladas para a sintaxe incorreta. Veja isso e a sintaxe T-SQL correta na Figura 1 abaixo.

Antes da atualização, o valor do preço unitário era 874,7940, conforme visto na Figura 2.

Após a atualização, UnitPrice é atualizado a partir do Produto ListPrice da tabela . Consulte a Figura 3.

Além de INNER JOIN, você pode usar LEFT ou RIGHT JOIN dependendo de suas necessidades.

3. UPDATE MySQL com Subconsulta


Você pode usar a instrução MySQL UPDATE de outra tabela usando uma subconsulta. A consulta com uma junção na seção anterior pode ser reescrita usando uma subconsulta. Os resultados serão os mesmos. Aqui vai:
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';

A abordagem é diferente, mas o resultado é o mesmo da Figura 3. No entanto, observe que a subconsulta usada para atualizar uma coluna deve retornar 1 valor.

Há outra maneira de expressar essa instrução UPDATE do MySQL.

4. UPDATE MySQL com CTE


Common Table Expressions (CTE) são suportados no MySQL e no SQL Server. Se você não estiver familiarizado com CTEs, confira o artigo anterior.

Agora, aqui está a declaração equivalente com o CTE usado.
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

O SQL Server oferece suporte ao mesmo conceito, mas sem backticks. O resultado será o mesmo da Figura 3.

Você pode perguntar, qual das 3 abordagens são melhores? Vamos comparar o desempenho deles mais adiante.

5. UPDATE MySQL com LIMIT


MySQL UPDATE pode limitar o número de linhas a serem atualizadas com a palavra-chave LIMIT. Suponha que queremos atualizar 5 registros no Produto tabela. Podemos expressar a afirmação assim:
UPDATE `production.product` p
SET p.StandardCost = p.StandardCost + 10, p.ListPrice = p.ListPrice + 10
ORDER BY p.ProductID
LIMIT 5;

Isso classificará os registros com base em ProductID e, em seguida, atualize os primeiros 5 registros. Ele pára após o 5º registro.

A contraparte do SQL Server de LIMIT é TOP. No entanto, você não pode simplesmente alterar a palavra-chave LIMIT para TOP e esperar que ela funcione no SQL Server. Aqui está a versão modificada em T-SQL que dará o mesmo resultado:
UPDATE Production.Product
SET StandardCost += 10, ListPrice += 10
WHERE ProductID IN (SELECT TOP 5 ProductID 
		    FROM Production.Product 
		    ORDER BY ProductID)

A lógica é um pouco diferente. Ele atualiza StandardCost e ListaPreço colunas com base nos ProductIDs encontrados na subconsulta. A subconsulta, por outro lado, retorna os 5 primeiros registros do Produto tabela classificada por ProductID .

Embora TOP também seja compatível com T-SQL UPDATE, ORDER BY não é. Assim, usar TOP com UPDATE modificará os registros aleatórios. A sintaxe acima é aplicável para registros ordenados com TOP.

Desempenho da ATUALIZAÇÃO do MySQL


Anteriormente, tínhamos uma instrução UPDATE com os mesmos resultados, embora usássemos métodos diferentes. Usamos um JOIN, subconsulta e CTE. Qual deles terá melhor desempenho?

Há também um plano de execução no MySQL usando a palavra-chave EXPLAIN. A sintaxe é assim:
EXPLAIN [FORMAT=JSON]
<SQL statement>

Sem o formato JSON, você tem informações básicas como tabelas, chaves de índice usadas e linhas verificadas. Quando o formato JSON é especificado, você tem informações mais detalhadas. O dbForge Studio para MySQL inclui um Query Profiler além do resultado de EXPLAIN. MySQL Workbench inclui um Visual EXPLAIN onde você pode ver uma visualização gráfica do plano baseado em EXPLAIN FORMAT=JSON.

Agora que conhecemos as instruções de linha de comando e as ferramentas gráficas, como podemos usá-las para comparar diferentes métodos?

Antes de prosseguirmos, deixe-me ser honesto. Minha proficiência no SQL Server é maior do que no MySQL. Posso perder alguma coisa ao longo do caminho ou estar errado. Você pode preencher as lacunas na seção Comentários posteriormente.

Dissecando resultados EXPLAIN para UPDATE com JOIN


A primeira vez que executei a instrução MySQL UPDATE com JOIN, levou 11,3 segundos para 24 linhas atualizadas. Inacreditável, não é?

Aqui está o que aconteceu como visto no dbForge Studio. Confira a Figura 4 abaixo.

O que a Figura 4 nos diz?
  1. Os 3 aliases de tabela usados ​​estão lá. Todos os 3 têm tipos de acesso de ALL. Isso significa que o MySQL usou o Table Scan para todos os 3.
  2. Veja a chave coluna. Nada é exibido em todas as 3 tabelas, o que significa que nenhuma chave de índice foi usada. Isso é compatível com o ponto anterior do Table Scan.
  3. Finalmente, as linhas coluna. Ele informa quantas linhas o MySQL acredita que deve verificar para obter o resultado final. Para 24 linhas atualizadas, milhares de linhas foram verificadas para SalesOrderHeader e Detalhes do pedido de vendas . Enquanto isso, todas as linhas do Produto tabela foram digitalizados.

Cocei a cabeça ao saber disso. Percebi que ao importar tabelas do SQL Server, apenas a estrutura da tabela e os dados eram importados, não os índices .

Então, criei índices apropriados e chaves primárias no dbForge Studio. Aqui está o que eu criei:
  • Eu criei o ProductID no Produto tabela uma chave primária.
  • Também adicionei SalesOrderID como chave primária no SalesOrderHeader tabela. Então, fiz um índice para OrderDate também.
  • Finalmente, criei SalesOrderDetailID no Detalhes do pedido de vendas tabela uma chave primária. Também adicionei um índice para o SalesOrderID e ProductID colunas desta tabela.

Após isso, gerei um novo plano de execução para a mesma consulta para ver as melhorias. O resultado?

AUMENTO DE VELOCIDADE APÓS ADICIONAR ÍNDICES


O tempo de execução foi reduzido de 11,3 segundos para 0,019 segundos. Muito legal!

Vamos verificar o novo plano usando o dbForge Studio na Figura 5 abaixo.

O que a Figura 5 nos diz?
  • O acesso tipos de 3 tabelas foram alteradas. Os 2 valores a serem evitados aqui são ALL e INDEX, especialmente em tabelas grandes. ALL é Table Scan e INDEX é Index Scan.
  • A chave coluna agora inclui os índices usados. Isso é bom. Todos os índices adicionados foram usados.
  • As linhas coluna agora mostra números menores. Os índices adicionados reduziram muito E/S em nossa consulta.

Para obter mais informações sobre os detalhes e valores do EXPLAIN, consulte esta documentação oficial.

Mas como isso se compara ao MySQL UPDATE com subconsulta?

Dissecando resultados EXPLAIN para UPDATE com subconsulta


A consulta anterior para atualizar o UnitPrice coluna tem outra alternativa de consulta, que está usando uma subconsulta. Como ele se compara ao JOIN? Confira a Figura 6 abaixo.

A Figura 6 mostra:
  • Os valores das colunas de tipo, chave e linhas são os mesmos em comparação com o uso de JOIN. Isso é lógico, pois deve ter os mesmos resultados.
  • O tempo de execução foi um pouco mais rápido. Isso não vai acontecer todas as vezes, no entanto. Depende dos recursos atuais disponíveis. A diferença de velocidade também é insignificante. Você não vai sentir nada.

Outra maneira é usar EXPLAIN FORMAT=JSON para obter mais informações sobre o plano. Na verificação, os valores de custo da consulta (84,79) e informações de custo são os mesmos.

Agora, vamos compará-lo com MySQL UPDATE com CTE.

Dissecando resultados EXPLAIN para UPDATE com CTE


Usando o CTE como base para atualizar o UnitPrice coluna é como ter uma tabela temporária primeiro e depois juntar a tabela temporária a SalesOrderDetails . À primeira vista, pode parecer que não é uma boa opção em comparação com os dois primeiros. Mas nos mostra que é possível ter uma atualização no MySQL usando CTE. Pode ser uma boa opção em outras situações. De qualquer forma, vamos ter os resultados EXPLAIN para esta abordagem.

Se você não possui o dbForge Studio for MySQL, você pode tentar produzir resultados EXPLAIN usando o comando em qualquer outro editor. Aqui está um exemplo:
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

O resultado está na Figura 7 abaixo.

A Figura 7 mostra:
  • 4 tabelas foram usadas em vez de 3. O primeiro uso de SalesOrderDetail está no CTE e depois na instrução UPDATE.
  • Mais tabelas significam mais linhas em comparação com as duas abordagens anteriores.

Surpreendentemente, isso funcionou em 0,015 segundos (não mostrado na figura). O mesmo é com o uso de uma subconsulta. No entanto, isso não vai acontecer todas as vezes. Depende dos recursos do sistema disponíveis no momento da execução.

O custo total da consulta é 166,69. É maior do que as 2 abordagens anteriores. Quanto menor o custo da consulta, melhor para o desempenho ao longo do tempo.

Recomendações


Mergulhamos profundamente nas diferenças entre a instrução UPDATE do MySQL e do SQL Server. Aprendemos como isso é feito ao atualizar
  • uma única coluna
  • várias colunas
  • tabelas com junção
  • colunas usando uma subconsulta
  • tabelas com CTE
  • com um LIMIT

Neste post, você também deu uma prévia do EXPLAIN e como usá-lo para comparar diferentes abordagens de UPDATE.

Espero que isso possa ser útil para você enquanto aprende MySQL vindo do SQL Server. Se você gostou deste post, compartilhe-o em suas plataformas de mídia social preferidas. E se algo estiver faltando, avise-nos na seção de comentários.

Boa codificação!