Using filesort
ist nicht unbedingt schlecht. Der Name ist etwas irreführend. Obwohl es "Datei" enthält, bedeutet dies nicht, dass die Daten irgendwo auf die Festplatte geschrieben werden. Es wird immer noch nur im Speicher verarbeitet.
Aus dem Handbuch :
Sie verstehen, warum dies in Ihrer Abfrage passiert, oder? Die Verwendung dieser Art von Unterabfragen ist schlechter Stil, da sie abhängig sind Unterabfrage. Für jede Zeile in Ihrer app
Tabelle wird die Unterabfrage ausgeführt. Sehr schlecht. Schreiben Sie die Abfrage mit einem join
neu .
select app.id,
gp.dateup
from app
join gamesplatform_pricehistory gp on gp.id_app = app.id
where app.id > 0
and gp.country = 1
and gp.dateup = (SELECT MAX(dateup) FROM gamesplatform_pricehistory smgp WHERE smgp.id_app = gp.id_app AND smgp.country = 1)
;
Dies verwendet immer noch eine abhängige Unterabfrage, aber die explain
sieht viel besser aus:
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
|----|--------------------|-------|-------|---------------|---------|---------|----------------------------|------|--------------------------|
| 1 | PRIMARY | app | index | PRIMARY | PRIMARY | 4 | (null) | 2 | Using where; Using index |
| 1 | PRIMARY | gp | ref | id_app | id_app | 5 | db_2_034bc.app.id,const | 1 | Using where; Using index |
| 2 | DEPENDENT SUBQUERY | smgp | ref | id_app | id_app | 5 | db_2_034bc.gp.id_app,const | 1 | Using index |
Eine andere Möglichkeit, es umzuschreiben, wäre dies:
select app.id,
gp.dateup
from app
LEFT join
(SELECT id_app, MAX(dateup) AS dateup
FROM gamesplatform_pricehistory
WHERE country = 1
GROUP BY id_app
)gp on gp.id_app = app.id
where app.id > 0
;
Die Erklärung sieht noch besser aus:
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
|----|-------------|----------------------------|-------|---------------|---------|---------|--------|------|--------------------------|
| 1 | PRIMARY | app | index | PRIMARY | PRIMARY | 4 | (null) | 2 | Using where; Using index |
| 1 | PRIMARY | <derived2> | ALL | (null) | (null) | (null) | (null) | 2 | |
| 2 | DERIVED | gamesplatform_pricehistory | index | (null) | id_app | 13 | (null) | 2 | Using where; Using index |
Und hier ist eine Version, in der Sie überhaupt keine abhängige Unterabfrage haben:
select app.id,
gp.dateup
from app
left join gamesplatform_pricehistory gp on gp.id_app = app.id and country = 1
left join gamesplatform_pricehistory gp2 on gp.id_app = app.id and country = 1 and gp.dateup < gp2.dateup
where app.id > 0
and gp2.dateup is null
;
Es funktioniert so:Wenn gp.dateup
maximal ist, gibt es kein gp2.dateup
.