sql >> Databasteknik >  >> RDS >> Mysql

Mysql-underfrågan gör alltid filsortering

Using filesort är inte nödvändigtvis en dålig sak. Namnet är lite missvisande. Även om den innehåller "fil", betyder det inte att data skrivs någonstans på hårddisken. Det är fortfarande bara bearbetat i minnet.

Från manualen :

Du förstår varför detta händer i din fråga, eller hur? Att använda den här typen av underfrågor är dålig stil eftersom det är beroende underfråga. För varje rad i din app tabell underfrågan exekveras. Väldigt dåligt. Skriv om frågan 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)
;

Detta använder fortfarande en beroende underfråga, men explain ser mycket bättre ut:

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

Ett annat sätt att skriva om det är detta:

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
;

Förklaringen ser ännu bättre ut:

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

Och här är en version där du inte har någon beroende underfråga alls:

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 fungerar så här:När gp.dateup är maximalt finns det ingen gp2.dateup .



  1. SQL Server Active Sessions and Status

  2. FEL 2013 (HY000):Förlorade anslutningen till MySQL-servern vid 'läsning av auktoriseringspaket', systemfel:0

  3. Hur man får en lista över alla materialiserade vyer i Oracle

  4. Hur man visar kommentarer för en kolumn med desc-operation