mysql index de plusieurs colonnes ne fonctionne pas (comme prévu)?
-
10-10-2019 - |
Question
J'ai une table comme ceci
CREATE TABLE IF NOT EXISTS `tbl_folder` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`owner_userid` int(11) NOT NULL,
`name` varchar(63) NOT NULL,
`description` text NOT NULL,
`visibility` tinyint(4) NOT NULL DEFAULT '2',
`num_items` int(11) NOT NULL DEFAULT '0',
`num_subscribers` int(11) NOT NULL DEFAULT '0',
PRIMARY KEY (`id`),
KEY `owner_userid` (`owner_userid`),
KEY `vis_sub_item` (`visibility`,`num_subscribers`,`num_items`)
) ENGINE=InnoDB
depuis que je suis un indice sur la visibilité, NUM_SUBSCRIBERS et num_items, je pense que seuls les 15 premiers rangs ne doivent être regardé, au lieu, dit EXPLIQUER 55856 lignes. Une idée? Merci
EXPLAIN SELECT t.id, name, description, owner_userid, num_items, num_subscribers
FROM `tbl_folder` `t`
WHERE visibility =2
ORDER BY `t`.`num_subscribers` DESC , `t`.`num_items` DESC
LIMIT 15
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t ref vis_sub_item vis_sub_item 1 const 55856 Using where
La solution
Votre 3 index sur le terrain semble bon et le EXPLAIN
est prometteur.
Bien qu'il dit "55856 lignes", qui est juste un estimation fourni par EXPLAIN
.
Depuis key_len =1
, vous savez qu'il utilise le premier octet de votre index composé comme une égalité / référence.
Comme il n'y a pas filesort mentionné dans votre champ Extra
, vous savez que le ORDER BY
/ tri en cours de traitement par l'indice.
Si vous vérifiez vos statistiques de session handler_%
, vous aurez une meilleure idée de combien de lignes sont en fait lecture.
Pensées secondaires:
Puisque vous savez que vous allez finalement sur le disque de succès pour récupérer vos lignes, si 99% de vos données a visibility=2
(juste spéculant), vous auriez probablement obtenir tout aussi bonne / résultats rapides avec un indice composé seulement sur num_subscribers
& num_items
. Ou sans doute aussi bon / rapide si vous a un seul indice sur num_subscribers
, selon lui est cardinalité / unique.
Autres conseils
Je ne pense pas que les regards de EXPLAIN
à la clause OFFSET
ou LIMIT
. EXPLAIN
est censé indiquer comment la requête sera exécutée, quelles touches il sert, comment les tables sont jointes, etc. La clause LIMIT
est un peu comme un modificateur de requête post ... maintenant que nous savons ce que nous voulons, em donner seulement premier tant. Ainsi, le champ contient des lignes le nombre de lignes possibles qui existent dans la requête. De là, OFFSET
et LIMIT
choisiraient ceux de spécifiques que vous voulez.
Je pensant que si vous avez exécuté votre SELECT
sans EXPLAIN
, vous obtiendrez le nombre d'enregistrements que vous vouliez.
oui, le problème est que l'index n'est pas correct. Je veux dire indexé tous les 3 champs et sélectionnez votre requête vérifie uniquement pour un. Dans indexation MySQL 2 rangées séparément est différent de l'indexation de 3 rangées ensemble.
Essayez
CREATE TABLE IF NOT EXISTS `tbl_folder` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`owner_userid` int(11) NOT NULL,
`name` varchar(63) NOT NULL,
`description` text NOT NULL,
`visibility` tinyint(4) NOT NULL DEFAULT '2',
`num_items` int(11) NOT NULL DEFAULT '0',
`num_subscribers` int(11) NOT NULL DEFAULT '0',
PRIMARY KEY (`id`),
KEY `owner_userid` (`owner_userid`),
KEY `vis_index` (`visibility`),
KEY `vis_sub_item` (`num_subscribers`,`num_items`)
) ENGINE=InnoDB