Translate

Mostrando las entradas con la etiqueta MySQL. Mostrar todas las entradas
Mostrando las entradas con la etiqueta MySQL. Mostrar todas las entradas

martes, 26 de mayo de 2026

Cómo detectar cuando MySQL elige un mal plan de ejecución?


El optimizador de MySQL es muy bueno… pero no es perfecto.


A veces elige un plan que:

❌ No usa índices

❌ Hace scans innecesarios

❌ Escala mal con más datos


El problema es que la query funciona… pero lento.


Primero: qué es un “mal plan”. Un mal plan no significa que falle.

Significa que:

  • Hace más trabajo del necesario
  • No usa la mejor estrategia disponible


Señales claras de un mal plan

❌ 1. Gran diferencia entre estimado y real

rows=1000 (estimated)

actual rows=10


Esto es una alarma 🚨

MySQL toma decisiones basadas en estimaciones.


Si están mal:

  • Puede elegir un índice incorrecto
  • O directamente no usar índice

❌ 2. Full Table Scan inesperado

Table scan on libros


Si tenés índice y aun así escanea todo:

🚨 Algo está mal


Posibles causas

  • Falta de índice
  • Índice no selectivo
  • Uso de funciones en columnas
  • LIKE '%texto%'


❌ 3. Índice ignorado

Tenés índice:

CREATE INDEX idx_nombre ON autores(nombre);


Pero el plan dice:

Table scan on autores


❌ No lo está usando


Causas típicas

  • Baja selectividad
  • Estadísticas desactualizadas
  • El optimizador cree que el scan es más barato


❌ 4. Nested loops con muchas filas

Nested loop (loops=10000)


Esto escala MUY mal


Problema

Por cada fila de A:

  • Busca en B


Complejidad tipo: O(n * m)


❌ 5. Filtros aplicados tarde


👉 Si aparece después de un scan:

❌ Primero lee todo

❌ Después filtra


❌ 6. Uso excesivo de “Using temporary” o “Sort”

Using temporary

Sort: ...


Señales de:

  • Falta de índices
  • Ordenamientos costosos


Ejemplo real:

SELECT *

FROM libros

WHERE titulo LIKE '%Java%';


Plan:

Table scan on libros


Aunque tengas índice en titulo:

No se usa por el `%` inicial


Caso interesante: estimaciones incorrectas

rows=1.25 actual rows=1

Esto es normal.


Pero:

rows=10000 actual rows=1

Problema serio


Consecuencia


MySQL puede pensar:

“Esto devuelve muchas filas → mejor full scan”

Pero en realidad devuelve pocas


Cómo confirmar que el plan es malo


1. Usar EXPLAIN ANALYZE

EXPLAIN ANALYZE SELECT ...


Comparar:

  • estimado vs real
  • tiempos


2. Medir tiempo real

A veces el plan “feo” igual es rápido.


3. Probar alternativas

  • Reescribir query
  • Forzar índice:

SELECT * FROM libros FORCE INDEX (idx_titulo)

WHERE titulo LIKE 'Java%';


Cómo corregir un mal plan

1. Actualizar estadísticas

ANALYZE TABLE libros;

Muchas veces esto solo ya arregla todo


2. Crear índices correctos

Pensar en:

  • WHERE
  • JOIN
  • ORDER BY


3. Cambiar la query


Ejemplo:

LIKE '%Java%' ❌

LIKE 'Java%'  ✔️


4. Reducir datos

Menos filas = mejores decisiones


5. Forzar plan (último recurso)

USE INDEX / FORCE INDEX

Solo si estás seguro


Error común

“Si EXPLAIN dice que usa índice, está todo bien”

❌ No necesariamente

👉 Puede usarlo… pero mal


Regla de oro

Siempre mirar:

  • rows vs actual rows
  • loops
  • tipo de acceso


El optimizador de MySQL:

✔️ Es bueno

❌ Pero depende de estadísticas


Y cuando se equivoca:

  • No falla
  • Solo se vuelve lento 

sábado, 23 de mayo de 2026

Guía de EXPLAIN ANALYZE en MySQL: cómo leer el plan de ejecución de verdad


Cuando trabajamos con performance en MySQL, entender el plan de ejecución es fundamental.


EXPLAIN nos da una idea pero EXPLAIN ANALYZE nos dice la verdad.


Si hacemos: 

EXPLAIN ANALYZE SELECT ...


Ejecuta la query (Ojo! si la query demora tanto que no termina la ejecución, ya esta no podemos usarlo) y devuelve:

  • El plan de ejecución
  • Métricas reales de ejecución
  • Comparación entre estimaciones y realidad


Ejemplo típico:


-> Nested loop inner join  (cost=0.787 rows=1.25)

   (actual time=0.0644..0.0705 rows=1 loops=1)


    -> Index lookup on tabla1 ...

       (cost=...) (actual time=... rows=... loops=...)


    -> Index lookup on tabla2 ...

       (cost=...) (actual time=... rows=... loops=...)


Esto es un árbol de ejecución:

  • De arriba hacia abajo
  • Cada nodo es una operación


Conceptos clave (los más importantes):

cost


(cost=0.787 rows=1.25)


Es una estimación del optimizador.

Incluye:

  • I/O esperado
  • CPU estimado
  • Lecturas de índice / tabla


⚠️ Importante:

❌ No es tiempo real

❌ No está en milisegundos

✔️ Solo sirve para comparar planes


rows (estimado)

rows=1.25

Cantidad estimada de filas.


Puede ser decimal porque:

  • Es un promedio estadístico
  • Ej: 1.25 filas por iteración


actual time


actual time=0.0644..0.0705


Tiempo real en milisegundos:

  • Primer valor → tiempo hasta la primera fila
  • Segundo valor → tiempo hasta la última fila


actual rows

rows=1

Filas reales procesadas.


loops

loops=1


Cuántas veces se ejecutó ese paso.


Relación clave

filas totales ≈ rows × loops


Tipos de operaciones (nodos del plan)


Nested Loop Join

MySQL usa principalmente este tipo de join.


Funcionamiento:

  1. Toma una fila de la tabla A
  2. Busca coincidencias en tabla B
  3. Repite


Index Lookup

Index lookup on tabla using index_name


Búsqueda usando índice:

✔️ Rápido

✔️ Ideal


Covering Index Lookup

El índice tiene todas las columnas necesarias.


✔️ No accede a la tabla

✔️ Más eficiente


Table Scan

Table scan on tabla


Escaneo completo.

❌ Costoso

❌ Señal de posible problema


Range Scan

Range scan on index


Usa índice, pero en un rango:

WHERE fecha BETWEEN ...


✔️ Bueno, pero no tan óptimo como lookup exacto


Filter

Filter: (condición)


Filtra filas después de leerlas.


⚠️ Si aparece mucho → puede faltar índice


Sort

Ordenamiento (`ORDER BY`)

❌ Puede usar memoria o disco


Temporary Table

Using temporary


MySQL crea tabla intermedia y puede impactar performance


Cómo leer un plan (estrategia real)


Paso 1: leer de abajo hacia arriba

  • Primero las hojas (tablas base)
  • Luego los joins


Paso 2: comparar estimado vs real


rows=1000 vs actual rows=10


Mala estimación → posible mal plan


Paso 3: mirar loops

Detecta:

  • nested loops costosos
  • operaciones repetidas


Paso 4: identificar scans


Buscar:

Table scan


Candidato a optimización


Problemas comunes detectables

1. Mala estimación

2. Full table scan innecesario

3. Nested loops costosos

4. Filtros tardíos


Veamos un ejemplo:


-> Nested loop inner join  (rows=1.25)

   (actual rows=1 loops=1)


    -> Covering index lookup on autores

       (rows=1 actual rows=1)


    -> Index lookup on libros

       (rows=1.25 actual rows=1)


Interpretación:

1. Encuentra 1 autor

2. Estima 1.25 libros por autor

3. Realmente hay 1


✔️ Plan correcto

✔️ Estimación aceptable


EXPLAIN ANALYZE es la herramienta más poderosa para entender performance en MySQL.


Pero requiere cambiar la mentalidad:

  • No mirar solo el resultado
  • Entender cómo MySQL llega a él



miércoles, 20 de mayo de 2026

Errores más comunes al usar particionado en MySQL (y cómo evitarlos)


El particionado en MySQL es una herramienta poderosa, pero también tiene varias reglas “ocultas” que suelen generar errores frustrantes.


1. La clave primaria no incluye la columna de partición


Este es el clásico:

PARTITION BY RANGE (anio_publicacion)

PRIMARY KEY (id_libro)


Error: A PRIMARY KEY must include all columns in the table's partitioning function


Solución

PRIMARY KEY (id_libro, anio_publicacion)


MySQL necesita garantizar unicidad global entre particiones. Por eso tiene que ser primary key la partición. 


2. Índices UNIQUE que no incluyen la columna de partición


No solo afecta a la PK:

UNIQUE (email)


También falla si email no incluye la columna de partición.


Solución: 

UNIQUE (email, anio_publicacion)


3. Pensar que el particionado reemplaza índices


Error conceptual muy común:

> “Particiono y ya no necesito índices”


❌ Incorrecto


Particionado → reduce datos a escanear

Índices → optimizan acceso dentro de la partición


Se complementan, no compiten.


4. No usar la columna de partición en las consultas


Ejemplo:

SELECT * FROM logs WHERE usuario = 'Juan';


MySQL tiene que escanear todas las particiones.

Mejor:


SELECT * FROM logs 

WHERE fecha >= '2026-01-01'

AND usuario = 'Juan';


Activa partition pruning


5. Definir mal los rangos (RANGE)


Ejemplo peligroso:

PARTITION p2023 VALUES LESS THAN (2023),

PARTITION p2024 VALUES LESS THAN (2024)


 ¿Dónde van los valores de 2023? (error lógico)


Correcto:

PARTITION p2023 VALUES LESS THAN (2024)


6. Olvidarse de MAXVALUE


PARTITION p2024 VALUES LESS THAN (2025)


¿Qué pasa con datos futuros?

Solución:

PARTITION pFuture VALUES LESS THAN MAXVALUE


Evita errores al insertar nuevos datos.

7. Usar particionado en tablas pequeñas

Overkill total.

Problema:

  • Más complejidad
  • Sin beneficios reales
  • Incluso puede empeorar performance


8. Pensar que particionado = sharding

Error conceptual importante.

Diferencia

Particionado → dentro de una misma tabla (mismo servidor)

Sharding → distribución en múltiples servidores


9. Usar funciones no determinísticas o inválidas

Ejemplo:

PARTITION BY RANGE (YEAR(NOW()))

❌ No permitido


10. Problemas con AUTO_INCREMENT

Cuando combinás:

  • AUTO_INCREMENT
  • PK compuesta
  • Particionado


Puede volverse confuso

Tip:

El AUTO_INCREMENT:

  • Debe estar en una clave indexada
  • Y respetar la estructura de la PK


12. Creer que DELETE masivo es la mejor opción

DELETE FROM logs WHERE fecha < '2023-01-01';

Lento, bloqueante


Mejor con particionado:

ALTER TABLE logs DROP PARTITION p2022;

Instantáneo



El particionado en MySQL:

✔️ Puede mejorar muchísimo la performance

❌ Pero introduce restricciones de diseño importantes


La clave es entender que:

  • No es transparente
  • Afecta claves, índices y consultas
  • Debe planificarse desde el diseño


domingo, 17 de mayo de 2026

Particionado de Tablas en MySQL: Qué es, tipos y cuándo usarlo




El particionado en MySQL es una técnica que permite dividir una tabla grande en partes más pequeñas (particiones), manteniendo la ilusión de que sigue siendo una única tabla.


Esto es clave cuando trabajamos con:

  • Grandes volúmenes de datos (millones o billones de filas)
  • Consultas que pueden beneficiarse de “leer menos datos”
  • Mantenimiento más eficiente (archivar, borrar, etc.)


Imaginemos una tabla de logs:

logs(id, fecha, usuario, accion)


Con millones de registros, consultas como:

SELECT * FROM logs WHERE fecha >= '2026-01-01';


terminan escaneando demasiados datos.


Con particionado, MySQL puede hacer partition pruning:

  • Solo accede a las particiones relevantes
  • Reduce I/O y mejora performance


Tipos de particionado en MySQL


 RANGE (por rango)

Ideal para fechas o valores ordenados.


CREATE TABLE logs (

  id INT,

  fecha DATE,

  mensaje VARCHAR(255)

)

PARTITION BY RANGE (YEAR(fecha)) (

  PARTITION p2023 VALUES LESS THAN (2024),

  PARTITION p2024 VALUES LESS THAN (2025),

  PARTITION pFuture VALUES LESS THAN MAXVALUE

);


Muy usado para:

  • Logs
  • Eventos
  • Datos históricos


LIST (por valores específicos)


CREATE TABLE usuarios (

  id INT,

  pais VARCHAR(50)

)

PARTITION BY LIST COLUMNS(pais) (

  PARTITION p_latam VALUES IN ('Argentina', 'Brasil'),

  PARTITION p_europa VALUES IN ('España', 'Francia')

);


Útil cuando tenés categorías bien definidas.


HASH (distribución uniforme)


CREATE TABLE pedidos (

  id INT,

  cliente_id INT

)

PARTITION BY HASH(cliente_id)

PARTITIONS 4;


MySQL distribuye automáticamente los datos.


KEY (similar a HASH pero interno)


CREATE TABLE sesiones (

  id INT,

  usuario_id INT

)

PARTITION BY KEY(usuario_id)

PARTITIONS 4;


Usa funciones hash internas de MySQL.


Limitaciones importantes

Antes de usar particionado, hay que tener en cuenta:

  • Todas las claves primarias deben incluir la columna de partición
  • No todas las engines soportan particionado (InnoDB sí)
  • No reemplaza índices (se complementan)
  • Puede complicar el diseño si no se usa bien


Cuándo usar particionado:

✔️ Tablas muy grandes (millones de filas)

✔️ Consultas filtradas por la columna de partición

✔️ Necesidad de borrar datos antiguos fácilmente


Cuándo NO usar particionado:

❌ Tablas pequeñas

❌ Consultas que no usan la columna de partición

❌ Como reemplazo de índices


domingo, 10 de mayo de 2026

Cómo usar EXPLAIN en MySQL para optimizar tus consultas


EXPLAIN te muestra el plan de ejecución de una consulta SQL.


En otras palabras, responde preguntas como:

  • ¿Qué tablas se recorren?
  • ¿En qué orden?
  • ¿Se están usando índices?
  • ¿Cuántas filas se estiman procesar?


EXPLAIN 

SELECT * 

FROM libro 

WHERE titulo = 'El Quijote';


Salida típica:


| id | select_type | table | type | possible_keys | key  | rows | Extra       |

| -- | ----------- | ----- | ---- | ------------- | ---- | ---- | ----------- |

| 1  | SIMPLE      | libro | ALL  | idx_titulo    | NULL | 1000 | Using where |


Qué podemos saber con esto, sin ser un erudito: 

type = ALL → Full Table Scan ❌

key = NULL → no está usando ningún índice


Esto significa que MySQL recorre toda la tabla.


Veamos agregar un indice: 

CREATE INDEX idx_titulo ON libro(titulo);


Volvemos a ejecutar:

EXPLAIN 

SELECT * 

FROM libro 

WHERE titulo = 'El Quijote';


Nueva salida:

| type | key        | rows |

| ---- | ---------- | ---- |

| ref  | idx_titulo | 1    |


✅ Ahora sí:

  • Usa índice
  • Escanea pocas filas
  • Mucho más eficiente


Veamos las columnas clave de EXPLAIN

type (MUY importante)

Indica cómo accede a la tabla:


| type   | Significado             |

| ------ | ----------------------- |

| ALL    | Full scan (malo) ❌      |

| index  | Scan de índice completo |

| ref    | Uso de índice 👍        |

| eq_ref | Uso óptimo 🚀           |

| const  | Mejor caso posible 💎   |


key

  • Índice que se está utilizando
  • Si es `NULL` → problema 😬


rows

  • Cantidad estimada de filas a procesar
  • Mientras menor, mejor


Extra

Algunos valores importantes:


| Extra           | Significado             |

| --------------- | ----------------------- |

| Using where     | Filtro aplicado         |

| Using index     | Index-only scan 🚀      |

| Using temporary | Tabla temporal ⚠️       |

| Using filesort  | Ordenamiento costoso ⚠️ |


Veamos un ejemplo con JOIN


EXPLAIN

SELECT l.titulo, a.nombre

FROM libro l

JOIN autor a ON l.autor_id = a.id

WHERE a.nombre = 'Cervantes';


👉 Cosas a observar:

  • Orden de las tablas
  • Índices en autor.nombre y libro.autor_id
  • Tipo de join (`ref`, `eq_ref`, etc.)


Problema típico: filesort

EXPLAIN

SELECT * 

FROM libro

ORDER BY fecha_publicacion;


Si ves: Using filesort


MySQL está ordenando en memoria (o peor, en disco)

Solución:

CREATE INDEX idx_fecha ON libro(fecha_publicacion);


EXPLAIN ANALYZE (MySQL 8+)


Mysql agrega el analyze que es propio de mysql, por lo menos no conozco en otras bases. (si conocen me dicen en los comentarios) Analyze corre la query y nos tira data más precisa. Tema que hay que esperar a que ejecute la query. 


EXPLAIN ANALYZE

SELECT * 

FROM libro 

WHERE titulo = 'El Quijote';


Que diferencia tiene con explain clave:


| EXPLAIN             | EXPLAIN ANALYZE |

| Estimaciones         | Ejecución real  |

| No ejecuta query   | Ejecuta query   |

| Rápido                   | Más preciso     |


Ejemplo:


-> Index lookup on libro using idx_titulo

(cost=0.35 rows=1)

(actual time=0.01..0.02 rows=1 loops=1)


Como conclusión, EXPLAIN no es opcional: es una herramienta esencial.


Te permite:

  • Entender cómo piensa MySQL
  • Detectar problemas de performance
  • Validar el uso de índices
  • Optimizar queries complejas


Un buen flujo de trabajo sería:


1. Escribir la query

2. Ejecutar EXPLAIN

3. Detectar problemas

4. Agregar índices / refactorizar

5. Validar con EXPLAIN ANALYZE


Nunca andar tirando índices a lo loco o trabajar a tientas. 

martes, 5 de mayo de 2026

SELECT FOR UPDATE en MySQL


Cuando trabajamos con sistemas concurrentes (varios usuarios o procesos accediendo a los mismos datos), uno de los problemas más comunes es la inconsistencia de datos.


Ahí es donde entra en juego una herramienta clave de MySQL:

SELECT ... FOR UPDATE


Esta sentencia que:

1. Lee filas de una tabla

2. Las bloquea para escritura

3. Hasta que la transacción finalice (COMMIT o ROLLBACK)


Esto garantiza que nadie más pueda modificar esas filas mientras vos trabajás con ellas.


Veamos un ejemplo: 


START TRANSACTION;


SELECT * 

FROM cuentas 

WHERE id = 1

FOR UPDATE;


UPDATE cuentas 

SET saldo = saldo - 100 

WHERE id = 1;


COMMIT;


En este caso:

Se bloquea la fila con id = 1

Nadie más puede modificarla hasta el COMMIT


¿Por qué es importante? Imaginá este escenario sin bloqueo:

1. Proceso A lee saldo = 100

2. Proceso B lee saldo = 100

3. Ambos descuentan 50

4. Resultado final: ❌ saldo = 50 (incorrecto)


Con FOR UPDATE:

1. Proceso A bloquea la fila

2. Proceso B espera

3. Se ejecuta A completamente

4. Luego B trabaja con datos actualizados

✔️ Resultado correcto


¿Cómo funciona internamente?

Ojo, Solo funciona con motores como InnoDB

Usa bloqueo a nivel de fila (row-level locking)

Otros SELECT FOR UPDATE:

  • Quedan esperando
  • Otros SELECT normales, pueden leer (dependiendo del isolation level)


Para no cagarla podemos usar SKIP LOCKED


SELECT * FROM tareas

WHERE estado = 'pendiente'

FOR UPDATE SKIP LOCKED;


✔️ Ignora filas bloqueadas

✔️ Ideal para workers concurrentes

Ojo, no sé si es tan aplicable, si queremos modificar todas las filas queremos modificar todas, no solo las no loqueadas.  


NOWAIT


SELECT * FROM cuentas

WHERE id = 1

FOR UPDATE NOWAIT;


❌ Falla inmediatamente si la fila está bloqueada

✔️ Útil cuando no querés esperar


Cosas a tener en cuenta:

  • Siempre usar dentro de una transacción
  • Puede generar deadlocks
  • Usar índices para evitar locks innecesarios
  • No funciona bien con tablas sin InnoDB



sábado, 31 de enero de 2026

Optimización y Performance de base de datos

El rendimiento de una base de datos no depende solo de cómo están escritas las consultas o diseñadas las tablas, sino también de cómo está configurado el entorno en el que corre: el servidor, la memoria disponible, los discos, y los parámetros internos del SGBD.


🔹 Configuración del SGBD (Buffers y Caches)

Un SGBD moderno utiliza múltiples mecanismos de caché y buffering para reducir el acceso al disco (que es el componente más lento del sistema).

Optimizar estos parámetros es clave para lograr un rendimiento estable.


🔸 Buffer Pool / Shared Buffers

Es el área de memoria principal que el motor usa para guardar temporalmente páginas de datos leídas desde disco.

Cuanto más grande sea (dentro de lo razonable), menos lecturas físicas se necesitarán.

📘 Ejemplo (PostgreSQL):

SHOW shared_buffers;

-- Ejemplo: 128MB

📘 Configuración típica (postgresql.conf):

shared_buffers = 25% de la RAM total

📘 Ejemplo (MySQL / InnoDB):

innodb_buffer_pool_size = 2G

💡 Idealmente, el buffer pool debe poder contener los datos más consultados (tablas “calientes”).


🔸 Cache de Consultas (Query Cache)

Almacena los resultados de consultas recientes, evitando recalcularlas.

Muy útil en aplicaciones con consultas repetitivas y pocos cambios de datos.

📘 Ejemplo (MySQL):

SET GLOBAL query_cache_size = 64M;

💡 En sistemas con muchas escrituras, puede ser contraproducente (se invalida constantemente la caché).


🔸 Write-Ahead Log (WAL) / Redo Logs

Los SGBD guardan los cambios primero en un log de escritura secuencial antes de aplicarlos al disco.

Esto garantiza durabilidad (la D de ACID) y permite recuperación tras fallos.

📘 Parámetros importantes:

wal_buffers (PostgreSQL)

innodb_log_buffer_size (MySQL)

Aumentarlos puede mejorar el rendimiento de inserciones masivas o actualizaciones en bloque.


🔸 Checkpoints

Un checkpoint es el proceso que sincroniza los datos en memoria con el disco.

Si ocurre con demasiada frecuencia, puede generar picos de I/O; si ocurre muy poco, aumenta el riesgo de recuperación más lenta.

📘 Ejemplo (PostgreSQL):

checkpoint_timeout = 5min

checkpoint_completion_target = 0.9

💡 Ajustar según la frecuencia de escritura y la capacidad de disco.


domingo, 14 de junio de 2020

Programación reactiva + bases de datos relacionales = R2DBC


Al carecer de una API estándar y la falta de disponibilidad de controladores, un equipo de Pivotal comenzó a investigar la idea de una API relacional reactiva que sería ideal para fines de programación reactiva. Y en ese momento nació, R2DBC que significa Conectividad de base de datos relacional reactiva.

Entre las características de R2DBC podemos nombrar: 

R2DBC se basa en la especificación de Reactive Streams, que proporciona una API sin bloqueo totalmente reactiva.

Trabaja con bases de datos relacionales. A diferencia de la naturaleza bloqueante de JDBC, R2DBC le permite trabajar con bases de datos SQL utilizando una API reactiva.

Admite soluciones escalables. Con Reactive Streams, R2DBC le permite pasar del modelo clásico de "un subproceso por conexión" a un enfoque más potente y escalable.

Proporciona una especificación abierta. R2DBC es una especificación abierta y establece una interfaz de proveedor de servicios (SPI) para que los proveedores de controladores implementen y los clientes los consuman.

Actualmente existen las siguientes implementaciones : 
  • cloud-spanner-r2dbc: controlador para Google Cloud Spanner
  • jasync-sql: contenedor R2DBC para Java & Kotlin Async Database Driver para MySQL y PostgreSQL escrito en Kotlin.
  • r2dbc-h2: controlador nativo implementado para H2 como base de datos de prueba.
  • r2dbc-mariadb: controlador nativo implementado para MariaDB.
  • r2dbc-mssql: controlador nativo implementado para Microsoft SQL Server.
  • r2dbc-mysql: controlador nativo implementado para MySQL.
  • r2dbc-postgres: controlador nativo implementado para PostgreSQL.
Los estándares existentes, basados ​​en el bloqueo de I/O, cortan la programación reactiva de los usuarios de bases de datos relacionales. R2DBC especifica una nueva API para permitir código reactivo que funciona de manera eficiente con bases de datos relacionales.

R2DBC es una especificación diseñada desde cero para la programación reactiva con bases de datos SQL. Define un SPI sin bloqueo para implementadores de controladores de bases de datos y autores de bibliotecas de clientes. Los controladores R2DBC implementan completamente el protocolo de conexión de la base de datos sobre una capa de I/O sin bloqueo.

R2DBC está pensado principalmente como un SPI del controlador para ser consumido por las bibliotecas del cliente y no para ser utilizado directamente en el código de la aplicación.

R2DBC admite aplicaciones nativas en la nube que utilizan bases de datos relacionales como PostgreSQL, MySQL y otras. Los desarrolladores de aplicaciones son libres de elegir la base de datos adecuada para el trabajo sin estar limitados por las API.

Spring Data R2DBC, parte de la familia Spring Data, facilita la implementación de repositorios basados en R2DBC. Spring Data R2DBC aplica abstracciones de la familia de Spring y soporte de repositorio para R2DBC. Facilita la creación de aplicaciones basadas en Spring que utilizan tecnologías de acceso a datos relacionales en una stack de aplicaciones reactivas.

Spring Data R2DBC pretende ser conceptualmente fácil. Para lograr esto, NO ofrece almacenamiento en caché, carga diferida, escritura detrás o muchas otras características de los marcos ORM. Esto hace que Spring Data R2DBC sea un mapeador de objetos simple, limitado y con opiniones.

Spring Data R2DBC permite un enfoque funcional para interactuar con su base de datos proporcionando DatabaseClient como el punto de entrada para las aplicaciones.

Veamos un ejemplo con postgres : 

PostgresqlConnectionFactory connectionFactory = new PostgresqlConnectionFactory(PostgresqlConnectionConfiguration.builder()
.host(…)
.database(…)
.username(…)
.password(…).build());

DatabaseClient client = DatabaseClient.create(connectionFactory);

Mono<Integer> affectedRows = client.execute()
        .sql("UPDATE person SET name = 'Joe'")
        .fetch().rowsUpdated();

Flux<Person> all = client.execute()
        .sql("SELECT id, name FROM person")
        .as(Person.class)
        .fetch().all();

Otro enfoque para atacar el bloqueo de JDBC es Fibers. Fibers como una abstracción ligera que convertirá las API de bloqueo en no bloqueantes. Esto es posible mediante el cambio de pila tan pronto como una invocación ... Pero eso es otra Historia y va ha ser contada en otro post ... 

Dejo links: 

sábado, 17 de agosto de 2019

Entendiendo el Execution Plan en MySql


No sabia que Mysql tenia la clausula  PLAN EXPLAIN y la tiene! Pero para que sirve?

Dependiendo de los detalles de sus tablas, columnas, índices y las condiciones en su cláusula WHERE, el optimizador MySQL considera muchas técnicas para realizar eficientemente las búsquedas involucradas en una consulta SQL.

Se puede realizar una consulta en una tabla enorme sin leer todas las filas; se puede realizar una unión que involucre varias tablas sin comparar cada combinación de filas. El conjunto de operaciones que el optimizador elige para realizar la consulta más eficiente se denomina "plan de ejecución de consultas", y este se puede ver ejecutando el PLAN EXPLAIN. Sus objetivos son reconocer los aspectos que indican que una consulta está bien optimizada y aprender la sintaxis SQL y las técnicas de indexación para mejorar el plan si hay algunas operaciones ineficientes.

La declaración EXPLAIN proporciona información sobre cómo MySQL ejecuta las consultas.

Cuando precede a una instrucción SELECT con la palabra clave EXPLAIN, MySQL muestra información del optimizador sobre el plan de ejecución de la instrucción. Es decir, MySQL explica cómo procesaría la declaración, incluida la información sobre cómo se unen las tablas y en qué or

Con la ayuda de EXPLAIN, puede ver dónde debe agregar índices a las tablas para que la instrucción se ejecute más rápido mediante el uso de índices para buscar filas. También puede usar EXPLAIN para verificar si el optimizador se une a las tablas en un orden óptimo. Para dar una pista al optimizador para que use un orden de unión correspondiente al orden en que se nombran las tablas en una instrucción SELECT, comience la instrucción con SELECT STRAIGHT_JOIN en lugar de solo SELECT.

Si tenemos un problema con los índices que no se usan cuando sabemos que deberían ser usados, debemos ejecutar ANALYZE TABLE para actualizar las estadísticas de la tabla, como la cardinalidad de las claves, que pueden afectar las elecciones que realiza el optimizador.

EXPLAIN devuelve una fila de información para cada tabla utilizada en la instrucción SELECT. Enumera las tablas en la salida en el orden en que MySQL las leería mientras procesa la declaración. MySQL resuelve todas las uniones utilizando un método de unión de bucle anidado. Esto significa que MySQL lee una fila de la primera tabla y luego encuentra una fila coincidente en la segunda tabla, la tercera tabla, etc. Cuando se procesan todas las tablas, MySQL genera las columnas seleccionadas y retrocede a través de la lista de tablas hasta que se encuentra una tabla para la cual hay más filas coincidentes. La siguiente fila se lee de esta tabla y el proceso continúa con la siguiente tabla.

Cuando se usa la palabra clave EXTENDED, EXPLAIN produce información adicional que se puede ver emitiendo una declaración SHOW WARNINGS después de la declaración EXPLAIN. EXPLAIN EXTENDED también muestra la columna filtrada.

En la mayoría de los casos, puede estimar el rendimiento de la consulta contando las búsquedas de disco. Para tablas pequeñas, generalmente puede encontrar una fila en una búsqueda de disco (porque el índice probablemente está en caché). Para tablas más grandes, puede estimar que, utilizando índices de árbol B, necesita esta cantidad de búsquedas para encontrar una fila: log (row_count) / log (index_block_length / 3 * 2 / (index_length + data_pointer_length)) + 1.

En MySQL, un bloque de índice suele tener 1.024 bytes y el puntero de datos suele tener cuatro bytes. Para una tabla de 500,000 filas con una longitud de valor clave de tres bytes (el tamaño de MEDIUMINT), la fórmula indica log (500,000) / log (1024/3 * 2 / (3 + 4)) + 1 = 4 búsquedas.

Este índice requeriría un almacenamiento de aproximadamente 500,000 * 7 * 3/2 = 5.2MB (suponiendo una relación de llenado del búfer de índice típico de 2/3), por lo que probablemente tenga gran parte del índice en la memoria y, por lo tanto, solo necesite una o dos llamadas para leer datos para encontrar la fila.

Sin embargo, para las escrituras, necesita cuatro solicitudes de búsqueda para encontrar dónde colocar un nuevo valor de índice y normalmente dos buscar y actualizar el índice y escribir la fila.

La discusión anterior no significa que el rendimiento de su aplicación se degenere lentamente por el registro N. Mientras el sistema operativo o el servidor MySQL guarden en caché todo, las cosas se vuelven un poco más lentas a medida que la tabla se hace más grande. Después de que los datos se vuelven demasiado grandes para ser almacenados en caché, las cosas comienzan a ir mucho más lentamente hasta que sus aplicaciones están unidas solo por búsquedas de disco (que aumentan por log N). Para evitar esto, aumente el tamaño de la caché de claves a medida que crecen los datos. Para las tablas MyISAM, el tamaño del caché de claves está controlado por la variable de sistema key_buffer_size.

Por ahora eso es todo sobre nuestro querido explain, dejo link :
https://dev.mysql.com/doc/refman/8.0/en/explain.html
https://dev.mysql.com/doc/refman/5.5/en/execution-plan-information.html

lunes, 13 de febrero de 2017

Ganar ventaja competitiva con MySQL

Me llego un mail por demás interesante sobre mysql. Oracle regala un paper que nos indica como hacer una diferencia comercial.

Sin más les dejo el mail:

View this message in a Web browser
Guide to MySQL as an Embedded Database
White Paper
A Guide for SaaS Vendors: Gaining Competitive Advantage with MySQL
Guide to MySQL as an Embedded Database
Access Resource Kitcta-arrow
Proven Reliability 

Relied on by many of the world’s largest software vendors as well as small SaaS startups to power their solutions and help them
  • Get to market and into production faster
  • Gain competitive advantage
  • At lower total cost
Access Resource Kit text-cta-arrow
Stay Connected
FacebookLinkedinTwitterYoutubeGooglePlus
Terms of Use and Privacy | Subscriptions | Un‌subscribe | Contact Us

miércoles, 14 de diciembre de 2016

Oracle Premier Support for MySQL: Rely on The Experts & Get Unique Benefits

Me llego este mail y lo quiero compartir con ustedes:

View this message in a Web browser
Oracle
White Paper
Oracle MySQL Support

Oracle MySQL
Get Your White Papercta-arrow
Are you covered?
Disasters and errors happen without warning. That’s why you insure your business – its structures, and capital assets. Now that business is increasingly data-driven and online, your databases alone can determine if your business is up or down 
 
With Oracle MySQL Support, we’ve got you covered. You are assured of top-tier support from the source for both full problem resolution and best practice advice.
Oracle Premier Support for MySQL: Rely on The Experts & Get Unique Benefits
slap-hr
bullet24 x 7, Worldwide, in 27 Languages
bulletBacklines to the Engineers who develop & maintain MySQL 
bulletIt’s all Premier – with Consultative Support!
Get Your White Papercta-arrow
Quote"We embedded MySQL in our optical-disc archive system because it provides the performance and features we required, and it enhanced our product’s competitiveness. Oracle’s reliable and reputable open-source database also strengthened customer confidence in the quality of Sony products and improved our support capabilities." 

Muneyoshi Benzaki
Senior Software Engineer, Sony Corporation
Stay Connected
FacebookLinkedinTwitterYoutubeGooglePlus