Rozważ tabelę wartości i skrótów, takie jak:
+------------+----------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+------------+----------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| val | char(9) | NO | | NULL | |
| val_hashed | char(50) | YES | | NULL | |
+------------+----------+------+-----+---------+----------------+
Następujące zapytanie kończy się za 0,00 sekundy:
SELECT * FROM hashes ORDER BY 1 DESC LIMIT 1;
Jednak to zapytanie zajmuje 3 min 17 sekund:
SELECT val FROM hashes ORDER BY 1 DESC LIMIT 1;
Widzę, że podczas działania zapytania lista procesów pokazuje go jako status Sorting result
. Sytuacja jest całkowicie powtarzalna. Zauważ, że istnieje inny proces wykonujący INSERT
operacje na stole w sposób ciągły.
Dlaczego uruchomienie bardziej szczegółowego zapytania trwa dłużej niż *
zapytanie? Zawsze uważałem, że *
należy unikać zapytań specjalnie ze względu na wydajność.
mysql
performance
select
dotancohen
źródło
źródło
id
do znalezienia pierwszego wiersza. Drugi musi posortować pełny wynik wval
kolumnie (nieindeksowanej) .ORDER BY NUMBER
Składnia jest dość podatny na błędy.SELECT *
połączeniu z indeksem kolumny wORDER BY
powoduje zaciemnienie sortowanej kolumny - kolejny powód, dla którego należy unikać*
...*
nie jest jednoznaczne. Zatem powiedzenie „daj mi wszystkie kolumny i posortuj według trzeciego” jest tak samo deterministyczne jak powiedzenie „idź do supermarketu i powiedz, ile świateł minąłeś”Odpowiedzi:
Wyrażenie
ORDER BY 1
odnosi się do różnych kolumn; w pierwszym będzieid
, w drugimval
. Odid
jest to klucz, zostanie zindeksowany iorder by
będzie to trywialna ilość pracy. Abyorder by val
jednak system musiał pobrać każdy wiersz, posortuj całą tabelę wedługval
, a następnie wybierz tylko jeden z tych wierszy.Zmień oba zapytania na
order by id
i myślę, że czasy wykonania będą prawie identyczne.źródło
Różnica wydajności w zapytaniu jest dobrze wyjaśniona przez MG. Zajmę się tym:
select *
nie wiąże się z żadnymi konkretnymi karami, jest problematyczne w przypadku niewłaściwego użycia. W zapytaniu z jedną tabelą działa dobrze. teraz połącz tę tabelę z inną z 20 kolumnami, a następnie dodaj połączenia do 5 innych tabel z wieloma kolumnami każda. TERAZ to problem. Podobnie są ludzie, którzy uczą szerokiej pomocy zespołu „nigdy nie rób X” bez wyjaśnienia dlaczego.źródło
SELECT *
może być problemem nawet dla zapytania z jedną tabelą. Na przykład,SELECT * FROM hashes ORDER BY val;
prawdopodobnie wykona pełne skanowanie tabeli, a następnie sortowanie, podczas gdySELECT val FROM hashes ORDER BY val;
wykona tylko pełne skanowanie indeksu i żadne sortowanie (zakładając, że indeks istnieje dla val). Tak więc nigdy nie boli wybrać tylko te wyniki, których potrzebujemy.select(*)
służy jedynie jako sub -Wybierz? Ponieważ jest to osadzony wybór, czy MySQL nie byłby wystarczająco inteligentny, aby dowiedzieć się, które kolumny należy wybrać?