J'ai essayé de résoudre le problème suivant pendant environ une heure maintenant et je n'ai toujours pas pu aller plus loin.
D'accord, j'ai une table (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 | |
+---------+-------------+------+-----+-------------------+----------------+
S'il vous plaît, ne vous occupez pas des index, j'ai essayé de trouver une solution. Maintenant, voici ma requête.
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;
le tableau stocke des informations sur les requêtes Web entrantes, c'est donc une base de données assez volumineuse.
+-----------+
| count(id) |
+-----------+
| 782412 |
+-----------+
notez qu'il n'y a pas de meilleur moyen de définir une clé primaire car la colonne id sera le seul identifiant unique que j'ai. La requête mentionnée ci-dessus prend environ 0,6 à 1,6 seconde pour s'exécuter.
Quel indice serait intelligent? J'ai pensé que la date d' indexation me donnerait une "mauvaise" cardinalité et donc MySQL ne l'utiliserait pas. http est également un mauvais choix car il n'y a qu'environ 20 valeurs possibles différentes.
Merci pour ton aide!
Mise à jour 1 J'ai ajouté un index sur (http, date) comme suggéré par ypercube:
mysql> CREATE INDEX httpDate ON reqs (http, date);
et utilisé sa requête, mais il a tout aussi mal fonctionné. L'index ajouté:
+-------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+
| 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 | |
+-------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+
et l' EXPLIQUER
+----+--------------------+-------+-------+---------------+----------+---------+------+-------+-----------------------------------------------------------+
| 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 |
+----+--------------------+-------+-------+---------------+----------+---------+------+-------+-----------------------------------------------------------+
Version du serveur 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)
la source
http
colonne pouvant être annulée. Je vais enquêter demain, si je trouve du temps.http NOT NULL
) et en y copiant toutes les données (sauf les lignes avec http NULL bien sûr.)Réponses:
J'ai trois suggestions
SUGGESTION # 1: Réécrivez la requête
Vous devez réécrire la requête comme suit
ou
Le WHERE ne doit pas avoir de fonction des deux côtés du signe égal. Le fait d'avoir la date sur le côté gauche du signe égal permet à l'Optimiseur de requête d'utiliser plus facilement un index.
SUGGESTION # 2: Index justificatif
Je suggérerais également un index différent
Je suggère cet ordre de colonnes car les
date
entrées seraient toutes contiguës dans l'index. Ensuite, la requête collecte simplement leshttp
valeurs sans ignorer les lacuneshttp
.SUGGESTION # 3: Tampon de clé plus grand (facultatif)
MyISAM utilise uniquement la mise en cache d'index. Étant donné que la requête ne doit pas toucher le
.MYD
fichier, vous devez utiliser un tampon de clé MyISAM légèrement plus grand.Pour le régler sur 256M
Ensuite, placez-le dans
my.cnf
Redémarrage de MySQL non requis
Essaie !!!
la source
Remplacez votre type de colonne de date par un entier. Stockez la date en tant que date Unix dans un entier. L'horodatage est beaucoup plus grand qu'un int. Vous en tireriez un coup.
la source
INT
et ontTIMESTAMP
besoin de 4 octets.