2016-06-15 18 views
43

Czym różnią się silniki SQL, gdy używamy znaku równości, a operator IN ma tę samą wartość? Czy czas realizacji się zmienia?Różnice w wydajności między wartościami równymi (=) i IN z jedną wartością

1. Jeden operator sprawdzić za pomocą równości

WHERE column_value = 'All' 

2 jeden stosując operator OR i pojedyncza wartość

WHERE column_value IN ('All') 

Czy SQL silnik zmienia IN do = jeśli tylko jedna wartość jest tam?

Czy jest jakaś różnica w MySQL i PostgreSQL?

+19

Nie próbuj uczyć się milionów zasad, które będą w jakiś sposób oznaczać, że zawsze napiszesz najlepszy możliwy kod. Napisz jasny, prosty, * zrozumiały * kod, który oczywiście daje prawidłowe wyniki. Ustaw cele wydajności. Następnie * zmień * wydajność swojego kodu. Jeśli działa poprawnie, przejdź dalej. Tylko jeśli nie osiąga dobrych wyników, poświęć temu więcej czasu. W tym czasie wypróbowanie drobnej zmiany, takiej jak w pytaniu, a następnie ponowne zmierzenie * jest proste.Może jeden jest szybszy od drugiego, ale * czy robi to znaczącą różnicę *? –

+3

Uzgodnione @Damien_The_Unbeliever. Ale czasami jestem bardziej zaniepokojony podczas pisania pojedynczej linii lub słowa z SQL –

+1

Są one 99,9999999% tak samo. Dopóki nie zrobisz czegoś takiego jak 'WHERE wartość_kolumny IN ((wybierz wartość z listy_wartości, gdzie wartość = 'Wszystkie' limit 1))' wtedy jesteś w porządku. Podkwerendy mają ogromny wpływ na wydajność klauzuli 'in()'. – MonkeyZeus

Odpowiedz

41

Nie ma różnicy między tymi dwoma instrukcjami, a optymalizator przekształci IN w =, gdy IN będzie zawierał tylko jeden element.

Chociaż, gdy masz takie pytanie, po prostu uruchom obie instrukcje, uruchom ich plan wykonania i zobacz różnice. Tutaj - nie znajdziesz żadnych.

Po wielkim wyszukiwania w internecie, znalazłem dokument na SQL w celu wspierania tego (zakładam, że odnosi się do wszystkich DBMS):

Jeśli jest tylko jedna wartość wewnątrz nawiasu, to Commend jest równoważna

GDZIE wartosc1 "COLUMN_NAME" =”

Here is the link to the document.

Oto plan wykonania obu zapytań w Oracle (większość DBMS rozpatrzy to samo):

EXPLAIN PLAN FOR 
select * from dim_employees t 
where t.identity_number = '123456789' 

Plan hash value: 2312174735 
----------------------------------------------------- 
| Id | Operation     | Name   | 
----------------------------------------------------- 
| 0 | SELECT STATEMENT   |    | 
| 1 | TABLE ACCESS BY INDEX ROWID| DIM_EMPLOYEES | 
| 2 | INDEX UNIQUE SCAN   | SYS_C0029838 | 
----------------------------------------------------- 

a dla IN():

EXPLAIN PLAN FOR 
select * from dim_employees t 
where t.identity_number in('123456789'); 

Plan hash value: 2312174735 
----------------------------------------------------- 
| Id | Operation     | Name   | 
----------------------------------------------------- 
| 0 | SELECT STATEMENT   |    | 
| 1 | TABLE ACCESS BY INDEX ROWID| DIM_EMPLOYEES | 
| 2 | INDEX UNIQUE SCAN   | SYS_C0029838 | 
----------------------------------------------------- 

Jak widać, oba są identyczne . To jest w indeksowanej kolumnie. To samo dotyczy kolumny bez indeksu (tylko pełne skanowanie tabeli).

+0

Czy masz jakieś oficjalne referencje dla dowolnej bazy danych? Próbowałem szukać, ale nie dostałem. –

+0

@SomnathMuluk Zaktualizowano odpowiedź – sagi

+0

@SomnathMuluk: - Nie sądzę, że istnieje jakiekolwiek oficjalne odniesienie z MySQL na ten temat. Możesz utworzyć test testowy i przetestować go samodzielnie, jeśli znajdziesz jakąkolwiek różnicę między wynikiem. –

8

Nie ma różnicy, gdy używasz go z jedną wartością. Jeśli sprawdzisz skanowanie tabeli, indeksowanie lub indeks wyszukiwania w poszukiwaniu powyższych dwóch zapytań, przekonasz się, że nie ma różnicy między tymi dwoma zapytaniami.

Czy są jakieś różnice w Mysql i PostgresSQL?

Nie, to nie miałoby żadnego znaczenia na dwóch silnikach (Rzeczywiście byłoby to samo dla większości baz danych w tym SQL Server, Oracle itp). Oba silniki skonwertują IN na =

4

Dla pojedynczej klauzuli IN, nie ma różnicy. Poniżej jest demonstracja przy użyciu tabeli EMPS.

select * from emps where empid in (1) 
select * from emps where empid=1 

Predicate dla pierwszego zapytania w planie wykonanie:

[PerformanceV3].[dbo].[Emps].[empID]=CONVERT_IMPLICIT(int,[@1],0) 

bazowych dla drugiego kwerendy w planie wykonanie:

[PerformanceV3].[dbo].[Emps].[empID]=CONVERT_IMPLICIT(int,[@1],0) 

Jeśli masz wiele wartości w w punkcie, lepiej jest przekonwertować je na łączenia

+3

Już wspomniałem tylko o jednej wartości. –

+0

@SnnathMuluk: zaktualizowano tylko dla jednej klauzuli – TheGameiswar

5

Naprawdę nie ma dużych różnic, ale jeśli twoja column_value jest indeksowana, operator IN może nie odczytać go jako indeksu.

Wystąpił ten problem raz, więc należy zachować ostrożność.

1

Będziesz musiał uruchomić plan wykonania na obu i zobaczyć wyniki.

Wydaje mi się, że będą one miały ten sam plan wykonania, który zostanie wykonany tak samo, jak normalny znak =, gdy tylko jedna wartość zostanie umieszczona wewnątrz instrukcji IN().

Nie ma powodu, aby optymalizator zachowywał się inaczej w takim zapytaniu.

5

uczyć człowieka do ryb, itd. Oto sposób, aby zobaczyć na własne oczy jak wariacje na zapytaniach zrobi:

mysql> EXPLAIN SELECT * FROM sentence WHERE sentence_lang_id = "AMH"\G 
*************************** 1. row *************************** 
      id: 1 
    select_type: SIMPLE 
     table: sentence 
     type: ref 
possible_keys: sentence_lang_id 
      key: sentence_lang_id 
     key_len: 153 
      ref: const 
     rows: 442 
     Extra: Using where 

I spróbujmy to w drugą stronę:

mysql> EXPLAIN SELECT * FROM sentence WHERE sentence_lang_id in ("AMH")\G 
*************************** 1. row *************************** 
      id: 1 
    select_type: SIMPLE 
     table: sentence 
     type: ref 
possible_keys: sentence_lang_id 
      key: sentence_lang_id 
     key_len: 153 
      ref: const 
     rows: 442 
     Extra: Using where 

Ty możliwe, Przeczytaj here o tym, jak interpretować wyniki zapytania mysql EXPLAIN. Na razie zauważ, że otrzymaliśmy identyczne dane wyjściowe dla obu zapytań: generowany jest dokładnie ten sam "plan wykonania". Wiersz type informuje, że zapytanie używa indeksu nieunikalnego (w tym przypadku klucza obcego), a wiersz ref informuje, że zapytanie jest wykonywane przez porównanie wartości stałej z tym indeksem.

2

Aby dodać inną perspektywę, jednym z głównych punktów systemów rdbms jest przepisanie twojego zapytania i wybór najlepszego planu wykonania dla tego zapytania i wszystkich równoważnych. Oznacza to, że tak długo, jak dwa zapytania są logicznie identyczne, powinny zawsze generować ten sam plan wykonania dla danego rdbms.

W związku z tym wiele zapytań jest równoważnych (ten sam zestaw wyników), ale tylko z powodu ograniczeń sama baza danych jest nieświadoma, więc należy zachować ostrożność w tych przypadkach (np. W przypadku pola flagi o numerach 1-6, db doesn 't know <3 jest taki sam jak in (1,2)). Ale na koniec dnia, jeśli myślisz o czytelności instrukcji and i or, nie będzie to miało wpływu na wydajność w jaki sposób je piszesz.