Mysql
 sql >> Baza danych >  >> RDS >> Mysql

Podzapytanie Mysql zawsze robi sortowanie plików

Using filesort niekoniecznie jest złą rzeczą. Nazwa jest nieco myląca. Chociaż zawiera "plik", nie oznacza to, że dane są zapisywane w dowolnym miejscu na dysku twardym. Nadal jest tylko przetwarzany w pamięci.

Z podręcznika :

Rozumiesz, dlaczego tak się dzieje w Twoim zapytaniu, prawda? Używanie tego rodzaju podzapytań jest złym stylem, ponieważ jest zależne podzapytanie. Dla każdego wiersza w Twojej app tabela podzapytanie jest wykonywane. Bardzo źle. Przepisz zapytanie z 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)
;

To nadal używa zależnego podzapytania, ale explain wygląda znacznie lepiej:

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

Innym sposobem na przepisanie tego byłoby to:

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
;

Wyjaśnienie wygląda jeszcze lepiej:

| 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 oto wersja, w której nie masz żadnego zależnego podzapytania:

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
;

Działa to tak:Kiedy gp.dateup osiąga maksimum, nie ma gp2.dateup .



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Czy w MySQL istnieje funkcja, która skompresuje wyniki zwrócone przez zapytanie?

  2. Zapytanie wyboru Mysql oparte na wielu danych wprowadzonych przez użytkownika

  3. Pola znaczników czasu w django

  4. mysql_fetch_array() zwraca „dostarczony argument nie jest prawidłowym zasobem wynikowym MySQL”

  5. MySQL InnoDB blokuje tylko dotknięte wiersze?