Zastanawiam się, czy jest jakaś różnica w wydajności między następującymi
SELECT ... FROM ... WHERE someFIELD IN(1,2,3,4)
SELECT ... FROM ... WHERE someFIELD between 0 AND 5
SELECT ... FROM ... WHERE someFIELD = 1 OR someFIELD = 2 OR someFIELD = 3 ...
czy MySQL zoptymalizuje SQL w ten sam sposób, w jaki kompilatory zoptymalizują kod?
EDYCJA: Zmieniono AND
„na OR
” z powodu podanego w komentarzach.
mysql
sql
performance
optimization
Scott
źródło
źródło
s I could say that it can also be converted to UNION
który jest zalecany do zastąpienia OR w celu optymalizacji zapytania.Odpowiedzi:
Musiałem to wiedzieć na pewno, więc porównałem obie metody. Konsekwentnie uważam,
IN
że jest znacznie szybszy niż używanieOR
.Nie wierz ludziom, którzy wyrażają swoją „opinię”, nauka polega na testowaniu i dowodach.
Uruchomiłem pętlę 1000x równoważnych zapytań (dla spójności użyłem
sql_no_cache
):IN
: 2,34969592094sOR
: 5.83781504631sAktualizacja:
(Nie mam kodu źródłowego dla oryginalnego testu, tak jak to było 6 lat temu, chociaż zwraca wynik w tym samym zakresie co ten test)
W przypadku prośby o przykładowy kod do przetestowania tego, oto najprostszy możliwy przypadek użycia. Używając Eloquent dla uproszczenia składni, surowy odpowiednik SQL wykonuje to samo.
źródło
IN
oświadczenie było około 30% szybsze niż anOR
.Do not believe people who give their "opinion"
Masz 100% racji, Stack Overflow jest niestety pełenReturns 1 if expr is equal to any of the values in the IN list, else returns 0. If all values are constants, they are evaluated according to the type of expr and sorted. The search for the item then is done using a binary search. This means
IN is very quick if the IN value list consists entirely of constants
. Otherwise, type conversion takes place according to the rules described at Type Conversion, but applied to all the arguments.
IN
Zrobiłem również test dla przyszłych pracowników Google. Całkowita liczba zwróconych wyników wynosi 7264 na 10000
To zapytanie zajęło
0.1239
kilka sekundTo zapytanie zajęło
0.0433
kilka sekundIN
jest 3 razy szybszy niżOR
źródło
OR
: najlepiej użyć możliwie najbardziej zwartego wyrażenia.Przyjęta odpowiedź nie wyjaśnia przyczyny.
Poniżej cytowano z High Performance MySQL, wydanie trzecie.
źródło
Myślę, że BETWEEN będzie szybszy, ponieważ należy go przekonwertować na:
Rozumiem, że IN i tak zostanie przekonwertowany na kilka instrukcji OR. Wartością IN jest łatwość użycia. (Oszczędzając konieczności wielokrotnego wpisywania nazwy każdej kolumny, a także ułatwia korzystanie z istniejącej logiki - nie musisz się martwić o pierwszeństwo AND / OR, ponieważ IN jest jedną instrukcją. Dzięki wielu instrukcjom OR masz aby upewnić się, że otaczasz je nawiasami, aby upewnić się, że są oceniane jako jeden warunek).
Jedyną prawdziwą odpowiedzią na twoje pytanie jest PROFILOWANIE SWOICH PYTAŃ . Wtedy będziesz wiedział, co działa najlepiej w twojej konkretnej sytuacji.
źródło
To zależy od tego, co robisz; jak szeroki jest zakres, jaki jest typ danych (wiem, że twój przykład używa liczbowego typu danych, ale twoje pytanie może dotyczyć również wielu różnych typów danych).
Jest to instancja, w której chcesz napisać zapytanie w obie strony; uruchom go, a następnie użyj EXPLAIN, aby dowiedzieć się o różnicach w wykonaniu.
Jestem pewien, że istnieje konkretna odpowiedź na to pytanie, ale w ten sposób praktycznie wymyśliłbym odpowiedź na zadane pytanie.
Może to być pomocne: http://forge.mysql.com/wiki/Top10SQLPerformanceTips
Pozdrawiam,
Frank
źródło
Myślę, że jednym z wyjaśnień dla obserwacji osoby poszukującej słońca jest to, że MySQL faktycznie sortuje wartości w instrukcji IN, jeśli wszystkie są wartościami statycznymi i wykorzystują wyszukiwanie binarne, które jest bardziej wydajne niż zwykła alternatywa OR. Nie pamiętam, gdzie to przeczytałem, ale wynik poszukiwacza słońca wydaje się dowodem.
źródło
Właśnie wtedy, gdy myślałeś, że to bezpieczne ...
Jaka jest twoja wartość
eq_range_index_dive_limit
? W szczególności, czy wIN
klauzuli jest więcej lub mniej pozycji ?Nie będzie to obejmowało testu porównawczego, ale trochę zagłębi się w wewnętrzne funkcjonowanie. Użyjmy narzędzia, aby zobaczyć, co się dzieje - Optymalizator Śledzenie.
Zapytanie:
SELECT * FROM canada WHERE id ...
Przy
OR
3 wartościach część śledzenia wygląda następująco:...
...
Zwróć uwagę, jak podaje się ICP
ORs
. To oznacza, żeOR
nie zmieniła sięIN
, a InnoDB będzie wykonanie pęczek=
testów przez ICP. (Nie sądzę, że warto rozważyć MyISAM.)(Jest to dziennik 5.6.22-71.0-Percona;
id
jest to indeks wtórny.)Teraz dla IN () z kilkoma wartościami
eq_range_index_dive_limit
= 10; jest 8 wartości....
...
Zauważ, że
IN
nie wydaje się, aby zostało zamienioneOR
.Uwaga dodatkowa: zauważ, że wartości stałe zostały posortowane . Może to być korzystne na dwa sposoby:
Na koniec IN () z dużą ilością wartości
...
...
Uwaga dodatkowa: Potrzebowałem tego ze względu na dużą objętość śladu:
źródło
LUB będzie najwolniejszy. To, czy IN lub BETWEEN jest szybsze, będzie zależeć od twoich danych, ale spodziewam się, że BETWEEN będzie normalnie szybszy, ponieważ może po prostu wziąć zakres z indeksu (zakładając, że someField jest indeksowany).
źródło
Poniżej znajdują się szczegóły 6 zapytań wykorzystujących MySQL 5.6 @SQLFiddle
Podsumowując, 6 zapytań obejmuje niezależnie indeksowane kolumny i zastosowano 2 zapytania dla każdego typu danych. Wszystkie zapytania skutkowały użyciem indeksu niezależnie od użytej IN () lub OR.
Naprawdę chciałem po prostu obalić stwierdzenia, że OR oznacza, że nie można użyć indeksu. To nie jest prawda. Indeksów można używać w zapytaniach wykorzystujących OR jako 6 zapytań w poniższych przykładach.
Wydaje mi się również, że wielu zignorowało fakt, że IN () jest skrótem składni zestawu OR. W małej skali różnice w wydajności między użyciem IN () -v- OR są niezwykle (nieintesencjonalnie) marginalne.
Podczas gdy na większą skalę IN () jest z pewnością wygodniejszy, ale logicznie odpowiada zestawowi warunków OR. Zmiana okoliczności dla każdego zapytania, więc testowanie zapytania na tabelach jest zawsze najlepsze.
Podsumowanie 6 planów wyjaśniania, wszystkie „Korzystanie z warunku indeksu” (przewiń w prawo)
SQL Fiddle
Konfiguracja schematu MySQL 5.6 :
.
Zapytanie 1 :
Wyniki :
Zapytanie 2 :
Wyniki :
Zapytanie 3 :
Wyniki :
Zapytanie 4 :
Wyniki :
Zapytanie 5 :
Wyniki :
Zapytanie 6 :
Wyniki :
źródło
Założę się, że są takie same, możesz uruchomić test, wykonując następujące czynności:
przeskocz 500 razy „in (1,2,3,4)” i zobacz, jak długo to potrwa. 500 razy obejrzyj wersję „= 1 lub = 2 lub = 3 ...” i zobacz, jak długo ona działa.
możesz również wypróbować sposób łączenia, jeśli someField jest indeksem, a twoja tabela jest duża, może być szybszy ...
Wypróbowałem powyższą metodę łączenia na moim SQL Server i jest ona prawie taka sama jak w (1,2,3,4), i oba powodują przeszukiwanie indeksów klastrowych. Nie jestem pewien, jak MySQL sobie z nimi poradzi.
źródło
2018 : IN (...) jest szybszy. Ale > = i& <= jest nawet szybszy niż IN .
Oto mój punkt odniesienia .
źródło
Z tego, co rozumiem na temat sposobu, w jaki kompilator optymalizuje tego rodzaju zapytania, użycie klauzuli IN jest bardziej wydajne niż wielu klauzul OR. Jeśli masz wartości, w których można zastosować klauzulę BETWEEN, jest to jeszcze bardziej wydajne.
źródło
Wiem, że dopóki masz indeks na polu, BETWEEN użyje go do szybkiego znalezienia jednego końca, a następnie przejdzie do drugiego. To jest najbardziej wydajne.
Każde WYJAŚNIENIE pokazuje, że „IN (...)” i „… OR…” są wymienne i równie (nie) skuteczne. Czego byś się spodziewał, ponieważ optymalizator nie ma możliwości sprawdzenia, czy zawierają one interwał. Jest to również równoważne z UNION ALL SELECT dla poszczególnych wartości.
źródło
Jak wyjaśniają inni, IN jest lepiej wybierany niż OR pod względem wydajności zapytania.
W poniższych przypadkach zapytania z warunkiem LUB mogą zająć więcej czasu.
źródło