Ir al contenido

Ingeniería de base de datos

Ingeniería de base de datos y Eloquent

El trabajo de consultas que hay detrás de una aplicación Laravel que ha superado su esquema - eliminar N+1, índices a partir de planes reales, y migraciones que no bloquean una tabla en producción.

Casi toda aplicación Laravel que se vuelve lenta se vuelve lenta en la base de datos, y casi todas ellas iban bien en desarrollo. Una página que ejecuta once consultas contra cuarenta filas ejecuta once consultas contra cuatro millones de filas de la misma manera, y solo una de las dos cosas es sobrevivible.

Adónde se va el tiempo en realidad

A lo largo de los encargos que hacemos, las causas se agrupan en una lista corta.

Un N+1 que solo aparece en producción. La página de listado carga su relación por adelantado. La de detalle no, porque solo carga un registro, y entonces alguien reutiliza el componente de detalle dentro de un bucle. El número de consultas pasa de dos a doscientas y nada en el diff parece mal.

Una relación cargada dentro de un accessor. getFullAddressAttribute() toca $this->country, el accessor se llama durante la serialización, y la aplicación emite una consulta por fila mientras aparenta estar formateando una cadena.

Un índice que existe y no se usa. Una columna envuelta en una función, una conversión implícita de tipo entre una columna de texto y un parámetro entero, un comodín inicial en un LIKE. El índice está ahí, EXPLAIN dice que no se está leyendo, y todo el mundo confía en el esquema en lugar del plan de la consulta.

Agregación hecha en PHP. La tubería de colecciones es lo bastante expresiva como para que ->get()->groupBy()->map() se lea mejor que el SQL, así que cien mil filas se convierten en modelos para producir seis números.

Una migración que bloqueó una tabla en producción. Añadir un índice, añadir una columna con valor por defecto, o cambiar un tipo de columna, sobre una tabla lo bastante grande como para que el bloqueo dure más que el tiempo de espera de la petición. El despliegue tuvo éxito; el sitio estaba caído.

Cómo trabajamos

Medir primero, desde el sistema real. Registros de consultas lentas, el número de consultas por endpoint, y EXPLAIN sobre las consultas que importan. No un profiler en un portátil con una base de datos sembrada, que le informa de forma fiable sobre un problema que no tiene.

Arreglar la causa y no el síntoma. Una caché delante de una consulta mala es una forma de pagar la consulta mala con menos frecuencia. A veces esa es la decisión correcta y lo diremos; con más frecuencia la consulta quiere un índice, un join, o no emitirse en tiempo de ejecución en absoluto.

Hacer permanente el arreglo. Carga perezosa desactivada fuera de producción, para que el N+1 que acaba de eliminar no pueda reintroducirse en silencio. Una aserción sobre el número de consultas en los endpoints que importan, para que una carga anticipada eliminada en el futuro haga fallar una prueba y no un ticket de soporte. Ambas son unas pocas líneas y son la diferencia entre un arreglo y un arreglo que se queda.

Trabajo de esquema en un sistema que no puede parar

La mayor parte de lo que nos piden arreglar no es una consulta sino una forma: una columna de estado que debería ser una tabla de estados, una relación polimórfica que hizo imposible restringir dos filas, un registro de auditoría que crece sin política de retención, una tabla que hace tres trabajos porque dividirla parecía caro hace dos años.

Ese trabajo se hace en pasos individualmente seguros:

  1. Añadir la nueva estructura junto a la vieja, sin que nada la lea.
  2. Rellenar por lotes, en una cola, con un progreso que sobreviva a un despliegue.
  3. Escribir en ambas, leer de la vieja, y conciliar hasta que la diferencia sea cero.
  4. Cambiar las lecturas. Esperar. Luego dejar de escribir en la vieja.
  5. Eliminarla, en una entrega aparte, una vez que nada la haya tocado en una semana.

Son más pasos que una sola migración y son la diferencia entre un cambio de esquema y una interrupción programada.

Qué recibe

Un documento de hallazgos con cada problema trazado hasta la consulta o la migración que lo causa y dimensionado por esfuerzo, los arreglos como pull requests revisables, los cambios de índices como migraciones seguras de ejecutar con su volumen de datos, y las aserciones en CI que impiden que las regresiones vuelvan.

Cuando la respuesta es estructural y no una reescritura de consulta, los hallazgos lo dicen y ponen ambas cifras una al lado de la otra: qué cuesta cambiarlo y qué cuesta dejarlo durante el próximo año. Eso debería leerlo en la primera semana y no oírlo en una reunión de cierre.

Antes de empezar, la gente suele querer leer dos cosas: lo que cuesta un cambio de esquema que bloquea una tabla en producción y en qué se diferencian de verdad MySQL y Postgres para una aplicación Laravel. Si lo lento resulta ser la ruta de la petición y no la consulta, rendimiento es el encargo vecino.

Alcance y condiciones

Modelo de colaboración
Alcance cerrado, acordado por escrito antes de empezar. No es una tarifa por día contra una lista abierta.
Precio y plazo
Los dos se fijan por proyecto, una vez fijado el alcance. Se ofertan juntos, antes de construir nada.
Qué necesitamos de usted
Una persona que pueda aprobar decisiones, y acceso a su repositorio y a su gestor de incidencias.
No incluido
Todo lo que quede fuera del alcance acordado. Pasa a ser su propio alcance, no una modificación.
Costes de terceros
El alojamiento, las licencias, las tarifas de API y las suscripciones SaaS los contrata y paga usted.
Facturación
Codefacture Yazılım A.Ş., Türkiye. EUR, USD o GBP por transferencia, sin IVA turco en servicios exportados.

Preguntas frecuentes

¿Es lo mismo que el trabajo de rendimiento?
Se solapan pero no son lo mismo. Rendimiento y escalado cubre toda la ruta de la petición - caché, colas, workers, la capa web. Esto es la base de datos en concreto, que es donde resulta vivir la mayor parte de la lentitud de Laravel, pero no toda. Si no sabe cuál de las dos tiene, la auditoría lo dice.
¿Van a sustituir Eloquent por SQL en crudo?
Rara vez, y nunca por completo. Eloquent no es el problema en la mayoría de las aplicaciones lentas: cómo se usa, sí. Cuando un informe pide de verdad un query builder o SQL en crudo lo diremos, pero sustituir un ORM para arreglar un N+1 es tratar una costumbre como si fuera una arquitectura.
¿Pueden trabajar sobre una base de datos que no podemos copiar?
Sí, y es habitual. Trabajamos con registros de consultas, salidas de EXPLAIN y un volcado del esquema sin filas dentro. Cuando necesitamos formas de datos y no datos, basta con un subconjunto anonimizado.
¿Cambian el esquema en un sistema en producción?
Solo con un plan escrito y una vuelta atrás, y normalmente en más pasos de los que parece necesitar: añadir, rellenar por lotes, cambiar las lecturas, cambiar las escrituras, eliminar. Una migración que parece una línea son con frecuencia cinco despliegues cuando la tabla es grande y la aplicación no puede parar.
Llamar+1 848 272 7583WhatsApp+90 850 308 5436Correoinfo@codefacture.comPágina de contacto