sql >> Base de Datos >  >> RDS >> Mysql

ACTUALIZACIÓN de MySQL:los 5 mejores consejos para desarrolladores de T-SQL

¿Está agregando MySQL a su lista de conjuntos de habilidades de base de datos? Entonces, la instrucción ACTUALIZAR de MySQL es uno de los comandos que necesita aprender.

Continuamos nuestro viaje a MySQL desde el punto de vista de SQL Server. Comenzó con CREATE TABLE, seguido de INSERT, y la pieza más reciente fue sobre DELETE. Hoy, UPDATE es nuestro punto focal.

Las diferencias son sutiles y fáciles de aprender. Pero al igual que en los artículos anteriores, nuestro objetivo es que esté listo y funcionando rápidamente. Pero antes de continuar, aclaremos estos elementos:

  • Los ejemplos utilizados aquí se ejecutaron en MySQL 8.0.23 utilizando el motor de almacenamiento InnoDB.
  • Utilizamos SQL Server 2019.

Preparar los datos de muestra

No podemos proceder sin datos de muestra. Me gustaría que los desarrolladores de T-SQL se sintieran cómodos en este ejercicio. Entonces, importemos algunas tablas familiares a AdventureWorks base de datos de muestra de SQL Server:

  • Producto
  • Cabecera de pedido de venta
  • Detalles del pedido de venta

Para importar estas tablas a MySQL, utilicé dbForge Studio para MySQL. Estos son los pasos:

  1. Cree una nueva base de datos llamada adventureworks2019 .
  2. Haga clic con el botón derecho en adventureworks2019 y seleccione Herramientas .
  3. Seleccione Importar datos . Aparecerá una nueva ventana.
  4. Seleccione ODBC . Debe crear un DSN de usuario para conectarse a su servidor SQL y AdventureWorks base de datos.
  5. Haga clic en Siguiente .
  6. Seleccione la tabla que necesita importar, la conexión MySQL y la base de datos de destino (adventureworks2019 ).
  7. Haga clic en Siguiente .
  8. Cambie la configuración de la columna. También puede ver datos de muestra. Puede omitir esto haciendo clic en Siguiente o cambie la configuración como mejor le parezca.
  9. Haga clic en Importar .
  10. Importe la siguiente tabla siguiendo las mismas instrucciones en pantalla.
  11. Haga clic en Finalizar .

Después de importar estas tablas, ahora está listo para los ejemplos de este artículo. Entonces, comencemos.

1. Conceptos básicos de sintaxis

La sintaxis de la instrucción UPDATE de MySQL es así:

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

Casi puedo oírte después de leer la sintaxis:¡BAJA PRIORIDAD, IGNORAR, ORDENAR POR y LÍMITE no encajan! Empecemos a discutir desde arriba.

Primero, LOW_PRIORITY es una palabra clave ajena para nosotros porque SQL Server no la admite. Es opcional, pero si lo incluye, las actualizaciones se retrasan hasta que todos los demás clientes no estén leyendo la tabla.

Otra palabra clave alienígena es IGNORAR. También es opcional, pero si lo incluye y se producen duplicados, no se generará un error. Para ver más errores que se pueden ignorar, consulta este enlace.

Luego, ORDENAR POR. Sabemos para qué sirve. Pero pruébelo en SQL Server Management Studio y aparecerán líneas onduladas debajo de las palabras clave.

Finalmente, LÍMITE. Esto es lo mismo que TOP en SQL Server. Más de esto y ORDENAR POR en una sección posterior.

Estas son las diferencias obvias. Siga leyendo en las próximas 2 subsecciones.

Columna única de ACTUALIZACIÓN de MySQL

Actualizar una sola columna es casi similar. Entonces, el ejemplo a continuación producirá el mismo resultado desde ambas plataformas de base de datos. Tenga en cuenta, sin embargo, que en lugar de acentos graves, SQL Server utiliza corchetes.

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

Aquí hay una sintaxis T-SQL equivalente:

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

El valor asignado a una columna puede ser cualquier expresión de valor único siempre que el tipo devuelto sea el mismo que el tipo de datos de la columna.

Actualización de MySQL en varias columnas

Actualizar varias columnas también es casi similar a T-SQL. He aquí un ejemplo:

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

Para actualizar varias columnas, simplemente separe los pares de valores de columna con una coma. Una vez más, la única diferencia aquí son los acentos graves.

Hasta ahora, todas estas son actualizaciones de una sola tabla. Pasemos a MySQL UPDATE desde otra tabla.

2. ACTUALIZACIÓN de MySQL con ÚNETE

Hay pequeñas diferencias que verá al actualizar una tabla con uniones. La mejor manera de mostrar esto es a través de un ejemplo del uso de 3 tablas.

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';

Tenga en cuenta que algunas cláusulas se organizan de manera diferente en comparación con SQL Server. Las uniones aparecen primero antes de la cláusula SET. Tampoco hay una cláusula FROM. Como es de esperar, SQL Server Management Studio colocará líneas onduladas para la sintaxis infractora. Vea esto y la sintaxis correcta de T-SQL en la Figura 1 a continuación.

Antes de la actualización, el valor del precio unitario es 874,7940, como se ve en la Figura 2.

Después de la actualización, UnitPrice se actualiza desde el Producto ListPrice de la tabla . Consulte la figura 3.

Además de INNER JOIN, puede usar LEFT o RIGHT JOIN según sus requisitos.

3. ACTUALIZACIÓN de MySQL con Subconsulta

Puede usar la declaración UPDATE de MySQL desde otra tabla usando una subconsulta. La consulta con una combinación en la sección anterior se puede reescribir utilizando una subconsulta. Los resultados serán los mismos. Aquí va:

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';

El enfoque es diferente, pero el resultado es el mismo que en la Figura 3. Sin embargo, tenga en cuenta que la subconsulta utilizada para actualizar una columna debe devolver 1 valor.

Hay otra forma de expresar esta declaración de ACTUALIZACIÓN de MySQL.

4. ACTUALIZACIÓN de MySQL con CTE

Las expresiones de tabla comunes (CTE) son compatibles con MySQL y SQL Server. Si no está familiarizado con los CTE, consulte el artículo anterior.

Ahora, aquí está la declaración equivalente con CTE utilizada.

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 admite el mismo concepto, pero sin acentos graves. El resultado será el mismo que en la Figura 3.

Puede preguntar, ¿cuál de los 3 enfoques es mejor? Seguiremos comparando su rendimiento.

5. ACTUALIZACIÓN de MySQL con LÍMITE

MySQL UPDATE puede limitar el número de filas para actualizar con la palabra clave LIMIT. Supongamos que queremos actualizar 5 registros en el Producto mesa. Podemos expresar la declaración así:

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

Esto ordenará los registros según ProductID y luego actualice los primeros 5 registros. Se detiene después del quinto registro.

La contraparte de SQL Server de LIMIT es TOP. Sin embargo, no puede simplemente cambiar la palabra clave LIMIT a TOP y esperar que funcione en SQL Server. Aquí está la versión modificada en T-SQL que dará el mismo resultado:

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

La lógica es un poco diferente. Actualiza StandardCost y Precio de lista columnas basadas en los ProductID encontrados en la subconsulta. La subconsulta, por otro lado, devuelve los primeros 5 registros del Producto tabla ordenada por ProductID .

Aunque TOP también es compatible con T-SQL UPDATE, ORDER BY no lo es. Por lo tanto, usar TOP con UPDATE modificará registros aleatorios. La sintaxis anterior es aplicable para registros ordenados con TOP.

Rendimiento de la ACTUALIZACIÓN de MySQL

Anteriormente, teníamos una declaración de ACTUALIZACIÓN con los mismos resultados a pesar de que usamos métodos diferentes. Utilizamos JOIN, subconsulta y CTE. ¿Cuál de ellos funcionará mejor?

También hay un plan de ejecución en MySQL usando la palabra clave EXPLAIN. La sintaxis es así:

EXPLAIN [FORMAT=JSON]
<SQL statement>

Sin el formato JSON, tiene información básica como tablas, claves de índice utilizadas y filas escaneadas. Cuando se especifica el formato JSON, tiene información más detallada. dbForge Studio para MySQL incluye un Query Profiler además del resultado de EXPLAIN. MySQL Workbench incluye un Visual EXPLAIN donde puede ver una vista gráfica del plan basado en EXPLAIN FORMAT=JSON.

Ahora que conocemos las instrucciones de la línea de comandos y las herramientas gráficas, ¿cómo podemos usarlas para comparar diferentes métodos?

Antes de continuar, déjame ser honesto. Mi competencia en SQL Server es mayor que en MySQL. Puedo perder algo en el camino o estar equivocado. Puede llenar los espacios en la sección Comentarios más adelante.

Diseccionando los resultados de EXPLAIN para UPDATE con JOIN

La primera vez que ejecuté la instrucción ACTUALIZAR de MySQL con JOIN, tardé 11,3 segundos en actualizar 24 filas. Increíble, ¿no?

Esto es lo que sucedió como se ve en dbForge Studio. Consulte la Figura 4 a continuación.

¿Qué nos dice la Figura 4?

  1. Los 3 alias de tabla utilizados están ahí. Los 3 tienen tipos de acceso de ALL. Significa que MySQL usó Table Scan para los 3.
  2. Mira la clave columna. No se muestra nada en las 3 tablas, lo que significa que no se usaron claves de índice. Esto respalda el punto anterior de Table Scan.
  3. Finalmente, las filas columna. Indica cuántas filas MySQL cree que debe escanear para lograr el resultado final. Para 24 filas actualizadas, se escanearon miles de filas para SalesOrderHeader y Detalles del pedido de venta . Mientras tanto, todas las filas del Producto tabla fueron escaneados.

Me rasqué la cabeza al enterarme de esto. Me di cuenta de que cuando importaba tablas de SQL Server, solo se importaban la estructura de la tabla y los datos, no los índices .

Entonces, creé índices apropiados y claves primarias en dbForge Studio. Esto es lo que creé:

  • Hice el ProductID en el Producto tabla una clave principal.
  • También agregué SalesOrderID como clave principal en el SalesOrderHeader mesa. Luego, hice un índice para OrderDate también.
  • Finalmente, hice SalesOrderDetailID en el Detalle del pedido de venta tabla una clave principal. También agregué un índice para el SalesOrderID y ID de producto columnas de esta tabla.

Después de esto, generé un nuevo plan de ejecución para la misma consulta para ver las mejoras. ¿El resultado?

AUMENTO DE VELOCIDAD DESPUÉS DE AGREGAR ÍNDICES

El tiempo de ejecución se redujo de 11,3 segundos a 0,019 segundos. ¡Muy genial!

Revisemos el nuevo plan usando dbForge Studio en la Figura 5 a continuación.

¿Qué nos dice la Figura 5?

  • El acceso tipos de 3 tablas fueron cambiadas. Los 2 valores a evitar aquí son ALL e INDEX, especialmente en tablas grandes. ALL es Table Scan e INDEX es Index Scan.
  • La clave columna ahora incluye los índices utilizados. Esto es bueno. Se usaron todos los índices agregados.
  • Las filas columna ahora muestra figuras más pequeñas. Los índices agregados redujeron una gran cantidad de E/S en nuestra consulta.

Para obtener más información sobre los detalles y valores de EXPLAIN, consulte esta documentación oficial.

Pero, ¿cómo se compara esto con MySQL UPDATE con subconsulta?

Disección de los resultados de EXPLAIN para UPDATE con subconsulta

La consulta anterior para actualizar el UnitPrice column tiene otra alternativa de consulta, que utiliza una subconsulta. ¿Cómo se compara con JOIN? Consulte la Figura 6 a continuación.

La Figura 6 muestra:

  • Los valores de columna de tipo, clave y filas son los mismos en comparación con el uso de JOIN. Esto es lógico ya que debería tener los mismos resultados.
  • El tiempo de ejecución fue un poco más rápido. Sin embargo, esto no sucederá siempre. Depende de los recursos actuales disponibles. La diferencia de velocidad también es despreciable. No lo sentirás en absoluto.

Otra forma es usar EXPLAIN FORMAT=JSON para obtener más información sobre el plan. Al verificar, el costo de la consulta (84.79) y los valores de información de costos son los mismos.

Ahora, comparémoslo con MySQL UPDATE con CTE.

Disección de los resultados de EXPLAIN para UPDATE con CTE

Usar CTE como base para actualizar el UnitPrice columna es como tener una tabla temporal primero y luego unir la tabla temporal a SalesOrderDetails . A primera vista, puede parecer que no es una buena opción en comparación con las dos primeras. Pero nos muestra que es posible tener una actualización en MySQL usando CTE. Puede ser una buena opción en otras situaciones. De todos modos, veamos los resultados de EXPLAIN para este enfoque.

Si no tiene dbForge Studio para MySQL, puede intentar producir resultados EXPLAIN usando el comando en cualquier otro editor. He aquí un ejemplo:

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

El resultado se muestra en la Figura 7 a continuación.

La Figura 7 muestra:

  • Se utilizaron 4 tablas en lugar de 3. El primer uso de SalesOrderDetail está en el CTE y luego en la instrucción UPDATE.
  • Más tablas significan más filas en comparación con los 2 enfoques anteriores.

Sorprendentemente, esto duró 0,015 segundos (no se muestra en la figura). Lo mismo ocurre con el uso de una subconsulta. Sin embargo, no sucederá siempre. Depende de los recursos del sistema disponibles en el momento de la ejecución.

El coste total de la consulta es de 166,69. Es más alto que los 2 enfoques anteriores. Cuanto menor sea el costo de la consulta, mejor será el rendimiento a lo largo del tiempo.

Puntos para llevar

Nos sumergimos profundamente en las diferencias entre MySQL y la instrucción UPDATE de SQL Server. Hemos aprendido cómo se hace al actualizar

  • una sola columna
  • columnas múltiples
  • tablas con una unión
  • columnas que usan una subconsulta
  • tablas con un CTE
  • con un LÍMITE

En esta publicación, también tuvo un adelanto sobre EXPLAIN y cómo usarlo para comparar diferentes enfoques de UPDATE.

Espero que esto pueda ser útil para usted a medida que aprende MySQL proveniente de SQL Server. Si te gusta esta publicación, compártela en tus plataformas de redes sociales preferidas. Y si falta algo, háznoslo saber en la sección de Comentarios.

¡Feliz codificación!