2011-04-13 3 views
1

Bon, voici l'affaire:mysql requête de sélection lent malgré indexé

J'ai une belle petite table 4Gb appelé Mails sur lequel je les deux requêtes suivantes:

SELECT * FROM Mails WHERE sent = 1 ORDER BY date ASC LIMIT 600; // 200ms 
SELECT * FROM Mails WHERE sent = 0 ORDER BY date ASC LIMIT 600; // >9000ms 

La relation entre les types envoyés est suivant:

0 192070 
1 1112341 
2 11992 
3 5369 

La requête de création est la suivante:

CREATE TABLE `Mails` (
    `id` int(10) unsigned NOT NULL AUTO_INCREMENT, 
    `idMail` varchar(100) COLLATE utf8_bin NOT NULL, 
    `type` varchar(100) COLLATE utf8_bin DEFAULT NULL, 
    `idSender` varchar(100) COLLATE utf8_bin DEFAULT NULL, 
    `senderfName` varchar(100) COLLATE utf8_bin DEFAULT NULL, 
    `senderlName` varchar(100) COLLATE utf8_bin DEFAULT NULL, 
    `senderMail` varchar(100) COLLATE utf8_bin DEFAULT NULL, 
    `receiverMail` varchar(100) COLLATE utf8_bin DEFAULT NULL, 
    `reference` varchar(100) COLLATE utf8_bin DEFAULT NULL, 
    `mailContent` text COLLATE utf8_bin, 
    `mailSubject` varchar(100) COLLATE utf8_bin DEFAULT NULL, 
    `sent` int(1) unsigned DEFAULT '0', 
    `opened` int(1) unsigned DEFAULT '0', 
    `clicked` int(1) unsigned DEFAULT '0', 
    `completed` int(1) unsigned DEFAULT '0', 
    `abstract` varchar(100) COLLATE utf8_bin DEFAULT NULL, 
    `date` datetime DEFAULT NULL, 
    PRIMARY KEY (`id`), 
    UNIQUE KEY `idMail` (`idMail`), 
    KEY `fk_type` (`type`), 
    KEY `fk_idSender` (`idSender`), 
    KEY `fk_senderMail` (`senderMail`), 
    KEY `fk_receiverMail` (`receiverMail`), 
    KEY `fk_sent` (`sent`), 
    KEY `fk_reference` (`reference`), 
    KEY `fk_date` (`date`) 
) ENGINE=MyISAM AUTO_INCREMENT=1321784 DEFAULT CHARSET=utf8 COLLATE=utf8_bin$$ 

Pourquoi diable est la requête "plus lourde" plus vite ou en fait à tout chargement? Indices à soi-même: Tout est lié à la clause order-by, car sans la date, il est rapide comme l'éclair pour les deux. Mauvaise chose, j'ai besoin de cette date pour commander mal. Je ne peux pas commander par l'identifiant parce que les mails peuvent être générés dans le futur et j'ai besoin de ceux qui ont passé NOW() et n'ont pas été envoyés.

[EDIT 2011-04-14]

La bonne réponse au ralentissement par AJ peut trouver ci-dessous. Notre solution à ce problème était de créer un index joint

KEY `sent` (`sent`,`date`) 

Résolu absolument tout.

+1

Est-ce que la colonne de date ont un groupe de nulls quand envoyé = 0? – Dave

+0

Un index 'composé (envoyé, date)' peut être utile. Comme @Dave: pointé, les valeurs NULL peuvent tuer les performances avec une requête ORDER BY. –

+0

Non, pas de null dans la date. – John

Répondre

2

Utilisez EXPLAIN pour déterminer comment MySQL est mise en mémoire tampon des résultats pour le tri:

http://dev.mysql.com/doc/refman/5.1/en/using-explain.html

Si vous ne disposez pas de tampon assez de tri, il utilisera l'espace temporaire sur le disque, ce qui est plus lent. Voir aussi des paramètres du serveur, et myisam_sort_buffer_size:

http://dev.mysql.com/doc/refman/5.1/en/server-parameters.html

+0

Super. La taille du tampon de tri en a expliqué la plupart. Nous avons depuis appliqué une solution. – John

Questions connexes