Empresas
Empregos
  • Sobre nós
  • Soluções
    • Publicação de vagas
      Publique sua vaga e receba candidatos qualificados em 48h.
    • Avaliações de candidatos
      Mais de 500 testes técnicos e psicológicos, mais anti-fraude.
    • Headhunting
      Busca executiva personalizada do início ao fim.
    • Folha de Pagamento + EOR
      Dispersão de folha e EOR em mais de 15 países da LATAM.
  • Preços
  • Empregos

0

360
Visualizações
Laravel - ¿Cómo optimizar MIN - MAX - orderBy consultas?

Mi código en Laravel es:

 Car::selectRaw('*, MIN(car_prices.price) AS min_price, MAX(car_prices.price) AS max_price, MAX(car_prices.updated_at) AS latest_update') ->leftJoin('car_prices', 'car_prices.car_id', 'cars.id') ->groupBy('car_prices.car_id') ->orderBy('latest_update', 'desc') ->paginate(10);

Se tarda mucho tiempo en ejecutarse hasta que arroja un error:

Tiempo máximo de ejecución de 60 segundos excedido

El conteo de registros en la tabla de cars es 100,000 y 6,000,000 en car_prices .

La estructura de las tablas:

 CREATE TABLE `cars` ( `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT, `name` varchar(191) COLLATE utf8mb4_unicode_ci NOT NULL, `created_at` timestamp NULL DEFAULT NULL, `updated_at` timestamp NULL DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=MyISAM AUTO_INCREMENT=110001 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci CREATE TABLE `car_prices` ( `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT, `car_id` bigint(20) unsigned NOT NULL, `price` decimal(8,2) NOT NULL, `created_at` timestamp NULL DEFAULT NULL, `updated_at` timestamp NULL DEFAULT NULL, PRIMARY KEY (`id`), KEY `car_prices_car_id_foreign` (`car_id`) ) ENGINE=MyISAM AUTO_INCREMENT=5506827 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci

La consulta:

 select count(*) as aggregate from `cars` left join `car_prices` on `car_prices`.`car_id` = `cars`.`id` group by `car_prices`.`car_id`; select *, MIN(car_prices.price) AS min_price, MAX(car_prices.price) AS max_price, MAX(car_prices.updated_at) AS latest_update from `cars` left join `car_prices` on `car_prices`.`car_id` = `cars`.`id` group by `car_prices`.`car_id` order by `latest_update` desc limit 10 offset 0;

¿Cómo puedo optimizarlo? ¿Debo almacenar en caché los datos? ¿O hay alguna consulta mejor que esta?

  • Mi disco duro es SSD
  • Valor de innodb_flush_log_at_trx_commit = 1
  • El número de escrituras/inserciones es de aproximadamente 1000/segundo de 10:00 a. m. a 02:00 p. m. y antes y después de este período hay muchas menos solicitudes.
over 4 years ago · Santiago Trujillo
3 Respostas
Responde à pergunta

0

Necesita tener un mejor índice único de la tabla de automóviles last_update o eliminar ->orderBy('latest_update', 'desc') en la consulta. y ordenarlo después de recibir los resultados

Puedes verificar el rendimiento en mysql con explicación

EXPLICAR SELECCIONAR * DESDE orden de auto por last_update desc;

/// Verifique esto https://www.exoscale.com/syslog/explaining-mysql-queries/#:~:text=the%20last%20decade.-,Explain,DELETE%20%2C%20REPLACE%20%2C %20y%20ACTUALIZAR%20 .

y https://dev.mysql.com/doc/refman/5.7/en/using-explain.html#:~:text=The%20EXPLAIN%20statement%20provides%20information,%2C%20REPLACE%20%2C%20and %20UPDATE%20statements.&text=Eso%20es%2C%20MySQL%20explica%20cómo,se unió%20y%20en%20qué%20orden .

Básicamente, necesita optimizar (mejor indexar) el "automóvil" de su tabla DB para que funcione bien

Y otra cosa que podría intentar aumentar el tiempo de ejecución. En php.ini, debe establecer max_execution_time = 600 o algo más para verificar cuánto tiempo se necesita para completar la ejecución. https://www.codewall.co.uk/aumentar-php-script-max-execution-time-limit-using-ini_set-function/

over 4 years ago · Santiago Trujillo Relatório

0

En ambas consultas,

 GROUP BY cars.id

Esto es en lugar de usar car_prices . car_id , que podría faltar debido a LEFT JOIN .

Una vez que haya hecho eso, la primera consulta (con solo COUNT ) puede descartar JOIN . Y luego el GROUP BY se vuelve redundante:

 select count(*) as aggregate from `cars`

La segunda consulta tiene problemas.

Con el diseño actual, debe pasar por todas las dos tablas. Puaj.

Además... Si no hay precios para un automóvil dado, tendrá NULL para la latest_update , por lo tanto, ordenará al final de las 100,000 filas. Dado eso, es mejor que no muestre esos autos; esto simplificaría la consulta lo suficiente como para optimizarla mejor.

Si necesita enumerar los automóviles para los que no tiene precios, haga una solicitud por separado en la interfaz de usuario. Esa consulta será LEFT JOIN .. IS NULL y no necesitará los MAX()s .

Pero, todavía estoy preocupado por las 10,000 páginas que el usuario necesita para paginar.

Cambie de MyISAM a InnoDB.

Mezcle created_at y updated_at , si no los está usando para nada.

Después de eso, cars es simplemente un mapeo entre id y name . Esto podría permitirle evitar pasar entre cars . En su lugar haz algo como

 SELECT ( SELECT name FROM cars WHERE id = x.car_id ) AS name, ... FROM ...

Otro pensó que cada vez que agrega una fila a car_prices , actualiza updated_at en cars . Esto le permitiría encontrar los 10 autos completamente en cars .

Decide lo que estás dispuesto a sacrificar.

Más

Nota: Con MyISAM, un SELECT lento bloquea la UPDATE . Con InnoDB, puede ejecutarse en paralelo; SELECT usa los valores antes de UPDATE . De cualquier manera, la selección es en algún "punto en el tiempo". Pero InnoDB permite más paralelismo.

Es una compensación. Una pequeña ralentización en las actualizaciones para lograr una gran aceleración en las selecciones. (No, no estoy seguro de que mi sugerencia sea "más rápida")

Algunas preguntas adicionales para analizar la compensación:

  • Disco: HDD o SSD?
  • Valor de innodb_flush_log_at_trx_commit (después de cambiar a InnoDB).
  • ¿Cuánto tráfico? Como primer corte, ¿es el número de escrituras (insertar/eliminar) más de 100/segundo?
over 4 years ago · Santiago Trujillo Relatório

0

La consulta que ha utilizado no es apta para tablas tan grandes. en cambio, cada vez que ingrese a la tabla car_prices , establezca una operación y tome el valor mínimo y máximo y guárdelo en la tabla de autos. o puede configurar una anciana para esto.

over 4 years ago · Santiago Trujillo Relatório
Responde à pergunta
Encontrar trabalhos remotos

Descubra a nova forma de encontrar um emprego!

melhores empregos
Principais categorias de trabalho
Empresas
Postar vaga Preços Comercial
Jurídico
Termos e Condições Política de privacidade
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomende algumas ofertas para mim
Preciso de ajuda