sql >> Databáze >  >> RDS >> Mysql

Poddotaz Mysql vždy provádí řazení souborů

Using filesort není nutně špatná věc. Název je trochu zavádějící. Přestože obsahuje "soubor", neznamená to, že jsou data zapsána kdekoli na pevném disku. Stále je zpracována v paměti.

Z příručky :

Chápete, proč se to ve vašem dotazu děje, že? Použití tohoto druhu poddotazů je špatný styl, protože je závislý poddotaz. Pro každý řádek ve vaší app tabulky se provede poddotaz. Velmi špatný. Přepište dotaz pomocí 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)
;

Toto stále používá závislý poddotaz, ale explain vypadá mnohem lépe:

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

Další způsob, jak to přepsat, by byl tento:

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
;

Vysvětlení vypadá ještě lépe:

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

A zde je verze, kde nemáte vůbec žádný závislý poddotaz:

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
;

Funguje to takto:Když gp.dateup je na svém maximu, neexistuje žádný gp2.dateup .



  1. Jak zašifrovat zálohy MySQL a MariaDB

  2. Kontrola ověření platnosti importu z databáze Oracle

  3. Jak používat spouštěče „for statement“ v postgresu?

  4. Chyba Postgress – instalace balíčku