Using filesort
không nhất thiết là một điều xấu. Tên là một chút sai lầm. Mặc dù nó chứa "tệp", nhưng điều đó không có nghĩa là dữ liệu được ghi ở bất kỳ đâu trên đĩa cứng. Nó vẫn chỉ được xử lý trong bộ nhớ.
Từ hướng dẫn sử dụng :
Bạn hiểu tại sao điều này xảy ra trong truy vấn của bạn, phải không? Sử dụng loại truy vấn phụ này là kiểu không hợp lệ vì nó là một phụ thuộc truy vấn con. Đối với mọi hàng trong ứng dụng app
của bạn bảng truy vấn con được thực thi. Rất tệ. Viết lại truy vấn bằng 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)
;
Điều này vẫn sử dụng một truy vấn phụ phụ thuộc, nhưng explain
trông đẹp hơn nhiều:
| 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 |
Một cách khác để viết lại nó, sẽ là thế này:
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
;
Giải thích thậm chí còn tốt hơn:
| 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 |
Và đây là phiên bản mà bạn không có truy vấn phụ phụ thuộc nào:
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
;
Nó hoạt động như thế này:Khi gp.dateup
ở mức tối đa, không có gp2.dateup
.