Ich habe versucht, das folgende Problem etwa eine Stunde lang zu lösen und bin trotzdem nicht weitergekommen.
Okay, ich habe einen Tisch (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 | |
+---------+-------------+------+-----+-------------------+----------------+
Bitte beachten Sie die Indizes, ich habe versucht, eine Lösung zu finden. Hier ist meine Frage.
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;
Die Tabelle speichert Informationen über eingehende Webanfragen, sodass es sich um eine ziemlich große Datenbank handelt.
+-----------+
| count(id) |
+-----------+
| 782412 |
+-----------+
Beachten Sie, dass es keine bessere Möglichkeit gibt, einen Primärschlüssel festzulegen, da die ID- Spalte die einzige eindeutige Kennung ist, die ich habe. Die oben genannte Abfrage dauert ca. 0,6-1,6 Sekunden.
Welcher Index wäre schlau? Ich stellte dar , dass die Indizierung Datum gibt mir „schlecht“ Mächtigkeit und damit MySQL wird es nicht verwenden. http ist auch eine schlechte Wahl, da es nur ungefähr 20 verschiedene mögliche Werte gibt.
Danke für deine Hilfe!
Update 1 Ich habe einen Index für (http, Datum) hinzugefügt, wie von ypercube vorgeschlagen:
mysql> CREATE INDEX httpDate ON reqs (http, date);
und verwendete seine Abfrage, aber es lief genauso schlecht. Der hinzugefügte Index:
+-------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+
| 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 | |
+-------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+
und die EXPLAIN
+----+--------------------+-------+-------+---------------+----------+---------+------+-------+-----------------------------------------------------------+
| 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 |
+----+--------------------+-------+-------+---------------+----------+---------+------+-------+-----------------------------------------------------------+
MySQL Server Version:
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)
quelle
http
Spalte nullwertfähig ist. Ich werde morgen nachforschen, ob ich Zeit finde.http NOT NULL
) und alle Daten darauf kopieren (außer natürlich die Zeilen mit http NULL.)Antworten:
Ich habe drei Vorschläge
VORSCHLAG 1: Schreiben Sie die Abfrage neu
Sie sollten die Abfrage wie folgt umschreiben
oder
Das WHERE sollte nicht auf beiden Seiten des Gleichheitszeichens eine Funktion haben. Das Datum auf der linken Seite des Gleichheitszeichens erleichtert es dem Abfrageoptimierer, einen Index dafür zu verwenden.
VORSCHLAG 2: Unterstützender Index
Ich würde auch einen anderen Index vorschlagen
Ich schlage diese Reihenfolge der Spalten vor, da
date
alle Einträge im Index zusammenhängend wären. Die Abfrage sammelt dann einfachhttp
Werte, ohne Lücken zu überspringenhttp
.VORSCHLAG 3: Größerer Schlüsselpuffer (optional)
MyISAM verwendet nur Index-Caching. Da die Abfrage die
.MYD
Datei nicht berühren sollte , sollten Sie einen etwas größeren MyISAM-Schlüsselpuffer verwenden.Um es auf 256M zu setzen
Dann setzen Sie es ein
my.cnf
Neustart von MySQL nicht erforderlich
Versuche es !!!
quelle
Ändern Sie den Datenspaltentyp in eine Ganzzahl. Speichern Sie das Datum als Unix-Datum in Ganzzahl. Timestamp Ist viel größer als ein Int. Sie würden etwas Knall davon bekommen.
quelle
INT
undTIMESTAMP
benötigen 4 Bytes.