Une table MySQL contient les deux tables de tableau suivant (simplifié):utilisant plage avec clé composite
(~13000) (~7000000 rows)
--------------- --------------------
| packages | | packages_prices |
--------------- --------------------
| id (int) |<- ->| package_id (int) |
| state (int) | | variant_id (int) |
- - - - - - - | for_date (date) |
| price (float) |
- - - - - - - - -
Chaque package_id
/for_date
combinaison a seulement quelques (moyenne 3) variantes. Et state
est 0 (inactif) ou 1 (actif). Environ 4000 des 13000 sont actifs.
D'abord, je veux juste savoir quels paquets ont un ensemble de prix (quelle que soit la variation), donc j'ajouter une clé composite couvrant (1) for_date
et (2) pid
et je recherche:
select distinct package_id from packages_prices where for_date > date(now())
Cette La requête prend 1 secondes pour renvoyer 3500 lignes, ce qui est trop. Un Explain m'indique que la clé composite est utilisée avec key_len 3, et 2000000 lignes sont examinées avec 100% filtré avec la plage de types. Using where; Using index; Using temporary
. Le distinct le ramène à 3500 lignes.
Si je supprime distinct
, le Using temporary
n'est plus mentionné, mais la requête renvoie alors 1000000 lignes et prend encore 1 secondes.
question 1: pourquoi cette requête est-elle si lente et comment puis-je accélérer sans avoir à ajouter ou modifier les colonnes de la table? Je m'attends à ce que, compte tenu de la clé composite, cette requête devrait être en mesure de coûter moins de 0,01s.
Maintenant, je veux savoir quels actifs paquets qui ont un ensemble de prix.
Donc j'ajoute une clé sur state
et j'ajoute une nouvelle clé composite comme ci-dessus, mais dans l'ordre inverse. Et j'écris ma requête comme ceci:
select distinct packages.id from packages
inner join packages_prices on id = package_id and for_date > date(now())
where state = 1
La requête prend maintenant 2 secondes. Une explication me dit pour la table packages
la clé sur state
est utilisée avec key_len 4, examine 4000 lignes et filtre 100% type type ref. Using index; Using temporary
. Et pour la table packages_prices
, la nouvelle clé composite est utilisée avec key_len 4, examine 1000 lignes et filtre 33.33% avec le type ref. Using where; Using index; Distinct
. Le distinct le ramène à 3000 lignes.
Si je supprime distinct
, les Using temporary
et Distinct
ne sont plus mentionnés, mais la requête renvoie 850000 lignes et prend 3 secondes.
question 2: Pourquoi la requête est-elle beaucoup plus lente maintenant? Pourquoi la plage n'est plus utilisée selon l'Explain? Et pourquoi le filtrage avec la nouvelle clé composite a-t-il chuté à 33,33%? Je m'attendais à ce que la clé composite filtre de nouveau 100% procent.
Tout cela semble très basique et trivial, mais cela m'a coûté des heures et des heures et je ne comprends toujours pas ce qui se passe vraiment sous le capot.
D'abord vous devriez probablement faire deux questions séparées. Alors s'il vous plaît inclure créer une table, créer un index, et nous montrer le plan d'explication complet. –
quand vous avez dit 'variants' vous voulez dire différent' packages_prices'? –
@HoneyBadger Ce sont deux tables séparées. Mais il l'a mis côte à côte. –