Ich habe eine MySQL-Tabelle, die mit Mails aus einem Postfix-Mail-Protokoll gefüllt ist. Die Tabelle wird sehr oft mehrmals pro Sekunde aktualisiert. Hier ist die SHOW CREATE TABLE
Ausgabe:Gibt es eine Möglichkeit, diese SELECT-Abfrage weiter zu optimieren?
Create Table postfix_mails CREATE TABLE `postfix_mails` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`mail_id` varchar(20) COLLATE utf8_danish_ci NOT NULL,
`host` varchar(30) COLLATE utf8_danish_ci NOT NULL,
`queued_at` datetime NOT NULL COMMENT 'When the message was received by the MTA',
`attempt_at` datetime NOT NULL COMMENT 'When the MTA last attempted to relay the message',
`attempts` smallint(5) unsigned NOT NULL,
`from` varchar(254) COLLATE utf8_danish_ci DEFAULT NULL,
`to` varchar(254) COLLATE utf8_danish_ci NOT NULL,
`source_relay` varchar(100) COLLATE utf8_danish_ci DEFAULT NULL,
`target_relay` varchar(100) COLLATE utf8_danish_ci DEFAULT NULL,
`target_relay_status` enum('sent','deferred','bounced','expired') COLLATE utf8_danish_ci NOT NULL,
`target_relay_comment` varchar(4098) COLLATE utf8_danish_ci NOT NULL,
`dsn` varchar(10) COLLATE utf8_danish_ci NOT NULL,
`size` int(11) unsigned NOT NULL,
`delay` float unsigned NOT NULL,
`delays` varchar(50) COLLATE utf8_danish_ci NOT NULL,
`nrcpt` smallint(5) unsigned NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `mail_signature` (`host`,`mail_id`,`to`),
KEY `from` (`from`),
KEY `to` (`to`),
KEY `source_relay` (`source_relay`),
KEY `target_relay` (`target_relay`),
KEY `target_relay_status` (`target_relay_status`),
KEY `mail_id` (`mail_id`),
KEY `last_attempt_at` (`attempt_at`),
KEY `queued_at` (`queued_at`)
) ENGINE=InnoDB AUTO_INCREMENT=111592 DEFAULT CHARSET=utf8 COLLATE=utf8_danish_ci
Ich möchte wissen, wie viele E-Mails über einen bestimmten Host zu einem bestimmten Zeitpunkt weitergeleitet wurden, so dass ich mit dieser Abfrage:
SELECT COUNT(*) as `count`
FROM `postfix_mails`
WHERE `queued_at` LIKE '2016-04-11%'
AND `host` = 'mta03'
Die Abfrage dauert zwischen 100 und 110 ms.
Derzeit enthält die Tabelle etwa 70 000 Mails, und die Abfrage gibt rund 31 000 zurück. Dies sind nur ein paar Tage im Wert von Mails, und ich plane, mindestens einen Monat zu behalten. Der Abfragecache hilft nicht viel, da die Tabelle ständig aktualisiert wird.
Ich habe versucht, dies zu tun, statt:
SELECT SQL_NO_CACHE COUNT(*) as `count`
FROM `postfix_mails`
WHERE `queued_at` >= '2016-04-11'
AND `queued_at` < '2016-04-12'
AND `host` = 'mta03'
Aber die Abfrage dauert die exakt gleiche Zeit laufen zu lassen.
[mysqld]
query_cache_size = 128M
key_buffer_size = 256M
read_buffer_size = 128M
sort_buffer_size = 128M
innodb_buffer_pool_size = 4096M
Und bestätigt, dass sie alle in Kraft sind (SHOW VARIABLES
), aber die Abfrage läuft nicht schneller: Ich habe diese Änderungen an der MySQL-Konfiguration vorgenommen.
Mache ich etwas dumm, dass diese Abfrage so lange dauern macht? Können Sie irgendwelche offensichtlichen oder nicht offensichtlichen Wege finden, um es schneller zu machen? Gibt es eine andere Datenbank-Engine, die in diesem Szenario besser funktioniert als InnoDB?
mysql> EXPLAIN SELECT SQL_NO_CACHE COUNT(*) as `count`
-> FROM `postfix_mails`
-> WHERE `queued_at` >= '2016-04-11'
-> AND `queued_at` < '2016-04-12'
-> AND `host` = 'mta03';
+----+-------------+---------------+------+--------------------------+----------------+---------+-------+-------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+---------------+------+--------------------------+----------------+---------+-------+-------+-------------+
| 1 | SIMPLE | postfix_mails | ref | mail_signature,queued_at | mail_signature | 92 | const | 53244 | Using where |
+----+-------------+---------------+------+--------------------------+----------------+---------+-------+-------+-------------+
1 row in set (0.00 sec)
Leistungsfragen sollten 'EXPLAIN ANALYSE' und einige Informationen über Tabellengröße, Index, aktuelle Zeitleistung, Wunschzeit usw. enthalten.' Langsam' ist ein relativer Begriff und wir brauchen einen echten Vergleichswert. [** MySQL **] (http://dba.stackexchange.com/questions/15371/how-do-i-get-the-execution-plan-for-a-view) Überprüfen Sie auch den MySQL-Index [* * TIPS **] (http://mysql.rjweb.org/doc.php/index_cookbook_mysql) –
Bitte zeigen Sie uns die EXPLAIN SELECT SQL_NO_CACHE COUNT (*) als "count" VON 'postfix_mails' WHERE' queued_at'> = '2016-04-11' UND 'queued_at' <'2016-04-12' AND' host' = 'mta03'; –
@JuanCarlosOropeza MySQL hat nicht 'EXPLAIN ANALYSE' AFAIK, aber ich habe die' EXPLAIN' Ausgabe hinzugefügt – Hubro