Traté de resolver el siguiente problema durante aproximadamente una hora ahora y todavía no conseguí más.
Bien, tengo una mesa (MyISAM):
+---------+-------------+------+-----+-------------------+----------------+
| Field | Type | Null | Key | Default | Extra |
+---------+-------------+------+-----+-------------------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| http | smallint(3) | YES | MUL | 200 | |
| elapsed | float(6,3) | NO | | NULL | |
| cached | tinyint(1) | YES | | NULL | |
| ip | int(11) | NO | | NULL | |
| date | timestamp | NO | MUL | CURRENT_TIMESTAMP | |
+---------+-------------+------+-----+-------------------+----------------+
No te preocupes por los índices, he estado jugando tratando de encontrar una solución. Ahora, aquí está mi consulta.
SELECT http,
COUNT( http ) AS count
FROM reqs
WHERE DATE(date) >= cast(date_sub(date(NOW()),interval 24 hour) as datetime)
GROUP BY http
ORDER BY count;
la tabla almacena información sobre solicitudes web entrantes, por lo que es una base de datos bastante grande.
+-----------+
| count(id) |
+-----------+
| 782412 |
+-----------+
tenga en cuenta que no hay una mejor manera de configurar una clave principal, ya que la columna de identificación será el único identificador único que tengo. La consulta mencionada anteriormente tarda aproximadamente 0.6-1.6 segundos en ejecutarse.
¿Qué índice sería inteligente? Pensé que la fecha de indexación me daría una cardinalidad "mala" y, por lo tanto, MySQL no la usará. http también es una mala elección, ya que solo hay unos 20 valores diferentes posibles.
¡Gracias por tu ayuda!
Actualización 1 He agregado un índice en (http, fecha) como sugirió ypercube:
mysql> CREATE INDEX httpDate ON reqs (http, date);
y usó su consulta, pero funcionó igualmente mal. El índice agregado:
+-------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+
| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment |
+-------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+
| reqs | 0 | PRIMARY | 1 | id | A | 798869 | NULL | NULL | | BTREE | |
| reqs | 1 | httpDate | 1 | http | A | 19 | NULL | NULL | YES | BTREE | |
| reqs | 1 | httpDate | 2 | date | A | 99858 | NULL | NULL | | BTREE | |
+-------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+
y el EXPLICAR
+----+--------------------+-------+-------+---------------+----------+---------+------+-------+-----------------------------------------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+--------------------+-------+-------+---------------+----------+---------+------+-------+-----------------------------------------------------------+
| 1 | PRIMARY | r | range | NULL | httpDate | 3 | NULL | 20 | Using index for group-by; Using temporary; Using filesort |
| 2 | DEPENDENT SUBQUERY | ri | ref | httpDate | httpDate | 3 | func | 41768 | Using where; Using index |
+----+--------------------+-------+-------+---------------+----------+---------+------+-------+-----------------------------------------------------------+
Versión del servidor MySQL:
mysql> SHOW VARIABLES LIKE "%version%";
+-------------------------+---------------------+
| Variable_name | Value |
+-------------------------+---------------------+
| protocol_version | 10 |
| version | 5.1.73 |
| version_comment | Source distribution |
| version_compile_machine | x86_64 |
| version_compile_os | redhat-linux-gnu |
+-------------------------+---------------------+
5 rows in set (0.00 sec)
fuente
http
columna sea anulable. Investigaré mañana, si encuentro tiempo.http NOT NULL
) y la copia de todos los datos en él (excepto las filas con NULL http por supuesto.)Respuestas:
Tengo tres sugerencias
SUGERENCIA # 1: Reescribe la consulta
Debería reescribir la consulta de la siguiente manera
o
WHERE no debe tener una función en ambos lados del signo igual. Tener la fecha en el lado izquierdo del signo igual hace que sea más fácil para el Optimizador de consultas usar un índice en su contra.
SUGERENCIA # 2: Índice de apoyo
También sugeriría un índice diferente
Sugiero este orden de columnas porque todas las
date
entradas serían contiguas en el índice. Luego, la consulta simplemente recopilahttp
valores sin omitir huecoshttp
.SUGERENCIA # 3: Búfer de clave más grande (opcional)
MyISAM solo usa el almacenamiento en caché de índice. Como la consulta no debe tocar el
.MYD
archivo, debe usar un búfer de clave MyISAM un poco más grande.Para configurarlo a 256M
Luego, configúralo
my.cnf
No se requiere reiniciar MySQL
Darle una oportunidad !!!
fuente
Cambie su tipo de columna de fecha a un entero. Almacene la fecha como una fecha Unix en entero. La marca de tiempo es mucho más grande que una int. Conseguirías algo de eso.
fuente
INT
yTIMESTAMP
necesitan 4 bytes.