Haga que MySQL haga tanto trabajo como sea posible. Si no es eficiente en lo que está haciendo, entonces las cosas probablemente no estén configuradas correctamente (ya sea que se trate de una indexación adecuada para la consulta que está intentando ejecutar, o configuraciones con búferes de ordenación).
Si tiene un índice en la columna year
, entonces usar DISTINCT
debería ser eficiente. Si no lo hace, entonces es necesario un escaneo completo de la tabla para obtener las distintas filas. Si intenta clasificar las distintas filas en PHP en lugar de MySQL, entonces transmite (potencialmente) muchos más datos de MySQL a PHP, y PHP consume mucha más memoria para almacenar todos esos datos antes de eliminar los duplicados.
Aquí hay un ejemplo de salida de una base de datos de desarrollo que tengo. También tenga en cuenta que esta base de datos se encuentra en un servidor diferente en la red desde donde se ejecutan las consultas.
SELECT COUNT(SerialNumber) FROM `readings`;
> 97698592
SELECT SQL_NO_CACHE DISTINCT `SerialNumber`
FROM `readings`
ORDER BY `SerialNumber` DESC
LIMIT 10000;
> Fetched 10000 records. Duration: 0.801 sec, fetched in: 0.082 sec
> EXPLAIN *above_query*
+----+-------------+----------+-------+---------------+---------+---------+------+------+-----------------------------------------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+----------+-------+---------------+---------+---------+------+------+-----------------------------------------------------------+
| 1 | SIMPLE | readings | range | NULL | PRIMARY | 18 | NULL | 19 | Using index for group-by; Using temporary; Using filesort |
+----+-------------+----------+-------+---------------+---------+---------+------+------+-----------------------------------------------------------+
Si intento la misma consulta, excepto reemplazar la columna de la SerialNumber
con uno que no es indexada, entonces se necesita siempre para funcionar ya que MySQL tiene que examinar los 97 millones de filas.
Parte de la eficiencia tiene que ver con la cantidad de datos que espera recuperar. Si modifico ligeramente las consultas anteriores para operar en la columna time
(la marca de tiempo de la lectura), tarda 1 min 40 segundos en obtener una lista distinta de 273,505 veces, la mayor parte de la sobrecarga que hay en la transferencia de todos los registros sobre el red. Por lo tanto, tenga en cuenta los límites de la cantidad de datos que está recuperando, y desea mantenerlos lo más bajos posible para los datos que intenta obtener.
En cuanto a su pregunta final:
select distinct line from car_cache
where year='$postyear' and make='$postmake'
order by line desc
No debe haber ningún problema con que, o bien, simplemente asegúrese de que tiene un índice compuesto sobre year
y make
y, posiblemente, un índice en line
.
En una nota final, el motor que estoy utilizando para la tabla de lecturas es InnoDB, y mi servidor es: 5.5.23-55-log Percona Server (GPL), Release 25.3
que es una versión de MySQL por Percona Inc.
Espero que ayude.
Para la consulta final, el mejor índice sería '(año, marca, línea)' o '(marca, año, línea)' –
excelente respuesta completa no podría pedir un mejor agradecimiento :) – Wolfe