sql >> Database teknologi >  >> RDS >> Mysql

Mysql underforespørgsel laver altid filersortering

Using filesort er ikke nødvendigvis en dårlig ting. Navnet er lidt misvisende. Selvom det indeholder "fil", betyder det ikke, at dataene er skrevet hvor som helst på harddisken. Det er stadig bare behandlet i hukommelsen.

Fra manualen :

Du forstår hvorfor dette sker i din forespørgsel, ikke? Brug af denne form for underforespørgsler er dårlig stil, da det er en afhængig underforespørgsel. For hver række i din app tabel udføres underforespørgslen. Meget dårligt. Omskriv forespørgslen med en join .

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)
;
 

Dette bruger stadig en afhængig underforespørgsel, men explain ser meget bedre ud:

| 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 |

En anden måde at omskrive det på ville være denne:

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
;
 

Forklaringen ser endnu bedre ud:

| 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 |

Og her er en version, hvor du slet ikke har nogen afhængig underforespørgsel:

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
;
 

Det fungerer sådan her:Når gp.dateup er på sit maksimum, er der ingen gp2.dateup .



  1. Skal jeg gemme prisen som decimal eller heltal i Mysql?

  2. Får ikke det ønskede output efter at have udført en QoQ

  3. Hvordan kan jeg hente data fra to tabeller

  4. pgpredict – Prædiktiv analyse i PostgreSQL