Tengo una consulta que se está ejecutando lentamente (tanto en Mysql 8 como en MariaDB 10):
select SQL_NO_CACHE UNIX_TIMESTAMP(created_at)* 1000 AS x,
value AS y, day(created_at), month(created_at), year(created_at)
from `portfolios`
where `user_id` = 3 and (created_at)>( CURDATE() - INTERVAL 1 MONTH)
group by day(created_at),month(created_at), year(created_at)
order by `created_at` asc;
Si elimino la columna 'valor' de la selección, se ejecuta rápidamente.
La mesa es:
portfolios | CREATE TABLE `portfolios` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`user_id` int(10) unsigned NOT NULL,
`value` decimal(15,8) NOT NULL,
`created_at` timestamp NULL DEFAULT NULL,
`updated_at` timestamp NULL DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `portfolios_user_id_created_at_index` (`user_id`,`created_at`),
KEY `portfolios_user_id_updated_at_index` (`user_id`,`updated_at`),
KEY `portfolios_id_user_id_updated_at_index` (`id`,`user_id`,`updated_at`),
KEY `portfolios_user_id_index` (`user_id`)
) ENGINE=InnoDB AUTO_INCREMENT=11767164 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
la tabla tiene alrededor de 12 millones de filas.
Ejecutando explicar (sin la columna 'valor'):
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+------+-------------+------------+-------+--------------------------------------------------------------------------------------------------+-------------------------------------+---------+------+--------+-----------------------------------------------------------+
| 1 | SIMPLE | portfolios | range | portfolios_user_id_created_at_index,portfolios_user_id_updated_at_index,portfolios_user_id_index | portfolios_user_id_created_at_index | 9 | NULL | 183996 | Using where; Using index; Using temporary; Using filesort |
Ejecutando explicar (con la columna 'valor'):
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+------+-------------+------------+-------+--------------------------------------------------------------------------------------------------+-------------------------------------+---------+------+--------+--------------------------------------------------------+
| 1 | SIMPLE | portfolios | range | portfolios_user_id_created_at_index,portfolios_user_id_updated_at_index,portfolios_user_id_index | portfolios_user_id_created_at_index | 9 | NULL | 184038 | Using index condition; Using temporary; Using filesort |
Entonces, cuando agrego esta columna a la consulta, parece dejar de 'usar dónde, usar índice' y comenzar a 'usar condición de índice'.
Realmente no entiendo por qué simplemente agregar una columna a la selección hace que esto se ralentice (15 segundos en comparación con aproximadamente .3): ¿se debe al tamaño de la tabla?
¡Agradecería cualquier consejo sobre cómo hacer que esto funcione más rápido!
Gracias por adelantado.
Su petición consiste en tres columnas: user_id
, created_at
y value
.
Tiene algunos índices en su tabla, pero ninguno de ellos contiene la value
columna. La explicación parece indicar que MySQL está usando el (user_id, updated_at)
índice para filtrar las filas coincidentes, pero para generar el resultado completo, también escanea la tabla para extraer valores de la value
columna para las filas coincidentes.
Si crea un índice en (user_id, created_at, value)
él, podría usarse como un índice de cobertura ... para que coincida con la cláusula where y para buscar value
desde el índice. MySQL ya no necesita tocar la tabla de filas de 22 mil.
Además, tu GROUP BY
es incorrecto. Supongo que debe contar o sumar los valores para cada día del año, en cuyo caso debe:
SELECT UNIX_TIMESTAMP(CAST(created_at AS DATE)) * 1000, SUM(values)
FROM t
WHERE ...
GROUP BY CAST(created_at AS DATE)
ORDER BY CAST(created_at AS DATE)
Este artículo se recopila de Internet, indique la fuente cuando se vuelva a imprimir.
En caso de infracción, por favor [email protected] Eliminar
Déjame decir algunas palabras