Tags

Konkurs książkowy

by Marcin Goł on August 19th, 2009

Nie wiem czy wiecie ale właśnie jestem w trakcie przeprowadzki z Warszawy do Torunia – w związku z tym robię małą inwentaryzację książek jakie mam na półkach. Kilka z nich postanowiłem oddać osobom którym się bardziej przydadzą. Książki dotyczą SQL Server 2005 – jest to seria Step-by-Step oraz kilka innych pozycji (chyba Programming SQL Server, Applied Techniques i coś tam jeszcze – nie pamiętam dokładnie).

Zasady konkursu są jasne – 1 pytanie tygodniowo – jedna książka tygodniowo. Kto pierwszy udzieli satysfakcjonującej odpowiedzi ten wybiera sobie książkę z tych co są do wybrania. Odpowiedzi udzielamy tutaj w komentarzach. Myślę że o ewentualnych odpowiedziach możemy dyskutować na forum WSS.pl. Jeśli nie określono inaczej odpowiedzi będa weryfikowane na SQL Server 2008 SP1.

Pytanie pierwsze:

Jaka jest różnica pomiędzy predykatami IN/EXISTS (NOT IN/NOT EXISTS) – odpowiedź powinna zawierać informację o tym czy występują jakieś (jakie?) różnice w logice, wydajności działania?

Czas  na odpowiedzi: poniedziałek, 24 sierpnia 2009 – 20:00.

EDIT:
Komentarze są moderowane – tzn. że muszę je zaakceptować żeby były widoczne. Plan jest taki że będę akceptował jak leci wszystkie odpowiedzi – być może wywiąże się dyskusja np. jeśli jakaś odpowiedź będzie niepełna to tu na blogu padnie wyjaśnienie osoby, która ma inne zdanie. Po zakończeniu każdego pytania – czyli w poniedziałek wieczorem wybiorę odpowiedź, która była najszybsza i najlepsza.

Powodzenia!!!

From → Bazy danych, Konkurs

9 Comments
  1. marecki permalink

    IN sprawdza czy to czego szukamy znajduje się w podzbiorze zwracanym przez podzapytanie, wiec trzeba wyrzucić i sprawdzić
    cały podzbiór, żeby spasować dokładnie.
    EXISTS sprawdza czy podzbiór z podzapytania w ogóle istnieje, więc wystarczy że zostanie zwrócony pierwszy dowolny wiersz.
    Wniosek jest taki, że EXISTS jest zdecydowanie wydajniejsze, z tym, że jego działanie jest ciut inne niż IN, więc trzeba uważać …

  2. Krzysztof Stachyra permalink

    IN:
    Zwraca prawde jeśli podana wartość pasuje do dowolnej wartości w zapytaniu lub liście
    przyjmuje listę lub listę pochodzącą z podzapytania
    może być dużo mniej wydajne i wywalić się z błędami przy dużej ilości danych
    Exists:
    zwraca prawde jeśli podzapytanie zawiera jakieś rekordy
    przyjmuje podzapytanie

  3. IN /EXISTS nic ponad to co napiasał kolega marecki
    NOT IN/NOT EXISTS – NOT IN nie może używać indexów tylko skany
    poza tym w NOT IN jest kwestia nulli – nie zostanie zwrócony żaden wiersz jeśli w tabeli ‘drugiej’ wystąpi null.
    P.S. Fajnie że komentarze są moderwane i dostępne po akceptacji ale IMHO powinny byc ujawnione dopiero po zakończeniu konkursu .
    Pozdrawiam

  4. Marcin Goł permalink

    Nie przeczytałem jeszcze wśród komentarzy poprawnej (wg mnie) odpowiedzi – proszę o poparcie waszych tez zapytaniami, które potwierdzą to co mówicie. Pracujemy na bazie AdventureWorks2008.

  5. Luk permalink

    To i ja swoje dorzucę:
    1. Plany wykonania zapytań już chyba od wersji SS2000 a na pewno od wersji 2005 są generowane przez optrymalizator w identyczny sposób zarówno dla EXISTS jak i IN pod warunkiem, iż “zdania są logicznie tożsame – równoważne”.

    2. Zasadnicza różnica polega na tym iż predykat IN opiera się na logice trójwartościowej, więc poza wartościami prawda i fałsz, występuje również wartość “nieznana”. W przypadku EXISTS występują jedynie wartości prawda i fałsz.

    3. Dla logiki normalnej nie ma to znaczenia czy używamy logiki dwuwartościowej czy trzywartościowej,w przypadku odwróconej logiki mamy do czynienia z faktem iż coś nie jest prawdą a po za negowaniu ją nadal nie jest! Dlatego działanie NOT EXISTS i NOT IN mogą przyjmować inne wartości dla wydawałoby się równoważnych zdań.

    Chyba wyjaśniłem starając się nie pisać językiem matematycznym :)

  6. p.kulczynski permalink

    Witam, muszę przyznać iż pytanie nie należy do najłatwiejszych, ponieważ większość programistów nie widzi różnicy pomiędzy predykatami IN/EXISTS. Myślę, że znam odpowiedź na to pytanie, poniżej wymieniam różnice:

    IN / EXISTS:

    – Zaczynając od historii, przed ukazaniem się SQL Server 2000 była istotna różnica pomiędzy generowaniem planu wykonania dla predykatów EXISTS i IN. Zapytania z predykatem EXISTS były bardziej wydajne. (Teraz raczej takiej różnicy nie zauważymy)
    – Predykat EXISTS może zwrócić tylko wartość TRUE lub FALSE. Nie rozróżnia wartości UNKNOWN. Natomiast Predykat IN może zwrócić wartości o logicznej wartości UNKNOWN. (Mimo tej różnicy, wartość UNKNOWN jest traktowana przez optymalizator jako wartość FALSE, dlatego też w planach wykonania nie zauważymy różnicy)
    – Użycie symbolu „*” np.: … AND EXISTS (SELECT * FROM Tabela as T2 WHERE T1.ID=T2.ID) jest w tym przypadku prawidłowe (mimo iż nie zaleca się stosowania znaku „*”), ponieważ dla predykatu EXISTS tylko odnalezienie jakiegokolwiek istniejącego wiersza jest istotne. Natomiast Predykat IN odwołuje się do konkretnej wartości kolumny z tabeli np.: … AND ID T1.IN (SELECT T2.ID FROM Tabela as T2)

    NOT IN / NOT EXISTS:

    – Główną różnicą pomiędzy predykatami widać w planach wykonania, otóż predykat NOT EXISTS w planie zapytania będzie posiadał operatora TOP, ponieważ odnalezienie chociażby jednego pasującego wiersza daje wynik FALSE (który w naszym przypadku będzie TRUE). Natomiast predykat NOT IN musi przeskanować całą kolumnę.
    – Również różnicę możemy zobaczyć, gdy w kolumnie jest wartość NULL. Dla predykatu NOT EXISTS wartość NULL w kolumnie nie ma żadnego wpływu na rezultat. Natomiast dla predykatu NOT IN w równoważnym zapytaniu, gdzie wystąpi wartość NULL, zwróci zbiór pusty. (Gdy dla tabeli jest dopuszczona wartość NULL, należy uważać. Jeżeli używamy predykatu NOT IN, aby zapobiec złym rezultatom i ulepszyć plan zapytania, należy umieścić filtr, który odrzuca wartości NULL)

    Nie mogę zaprzeczyć, iż po części musiałem sobie przypomnieć jak wygląda sytuacja z planami wykonywania, ale kto z nas nie korzysta z innych pomocy naukowych (chociażby BOOKS ONLINE). Na co dzień mam do czynienia z predykatami IN/EXISTS stąd też większość różnić znam. Mam nadzieję, iż moja odpowiedź była satysfakcjonująca.

  7. p.kulczynski permalink

    Niestety na komputerze z którego piszę nie mam silnika SQL, stąd też nie przedstawiłem konkretnych przykładów opartych o bazę AdventureWorks2008. Jeżeli byłaby taka potrzeba mogę postarać się jutro przedstawić kilka przykładów, chociaż niewiem czy będę miał trochę wolnego czasu w pracy. Mama nadzieję, że i tak, odpowiedź jest wystarczająca.

  8. Paweł Kruczkowski (kruczkop) permalink

    dodam jeszcze od siebie, że IN oraz EXISTS, (jak również ‘=‘, ‘’, ‘=‘ oraz BETWEEN i warunkowo LIKE) są akroninami SARG (search arguments), co oznacza, że są silnie wspierane przez qoptimiazer. Zaś zaprzeczenia powyższego, tj. NOT EXISTS, NOT IN nie są akroninami SARG, a więc na ogół zapytanie z ich użyciem nie zostanie prawidłowo (wydajnie, poprzez nie użycie prawidłowo indeksów etc.) wykonane przez silnik SQL.

  9. p.kulczynski permalink

    Przedstawiam przykłady równoważnych zapytań w których, w pierwszym z nich (NOT IN) otrzymamy zbiór pusty, natomiast w drugim (NOT EXISTS) otrzymamy prawidłowy rezultat.

    SELECT DISTINCT City FROM Person.Address O1
    WHERE O1.AddressLine2 NOT IN (SELECT O2.AddressLine2 From Person.Address O2)

    –W tym przykładzie widać również użycie “*” (gwiazdki)
    SELECT DISTINCT City FROM Person.Address O1
    WHERE NOT Exists (SELECT * FROM Person.Address O2 WHERE O1.AddressLine2=O2.AddressLine2)

    Aby zapobiec tego typu sytuacji należy dla predykatu NOT IN dodać filtr, który wyrzuci NULL’e.

Comments are closed.