Próbuję dowiedzieć się, czy wiersz istnieje w tabeli. Korzystając z MySQL, lepiej wykonać takie zapytanie:
SELECT COUNT(*) AS total FROM table1 WHERE ...
i sprawdź, czy suma jest różna od zera, czy lepiej jest wykonać takie zapytanie:
SELECT * FROM table1 WHERE ... LIMIT 1
i sprawdź, czy zostały zwrócone jakieś wiersze?
W obu zapytaniach klauzula WHERE używa indeksu.
sql
mysql
performance
exists
Bernard Chen
źródło
źródło
...EXISTS( SELECT 1/0 FROM someothertable)
. W przypadku SQL Server i Oracle - użycie *, 1 lub NULL nie ma znaczenia, ponieważ ISTNIEJE testuje tylko wartość logiczną na podstawie 1+ zgodnych kryteriów WHERE.SELECT 1 FROM table1 WHERE col = $var LIMIT 1
jest szybsze niż twoje zapytanie. Jaka jest zatem zaleta twojego zapytania?Ostatnio przeprowadziłem kilka badań na ten temat. Sposób implementacji musi być inny, jeśli pole jest polem TEXT, polem nie unikalnym.
Zrobiłem kilka testów z polem TEXT. Biorąc pod uwagę fakt, że mamy tabelę z wpisami 1M. 37 wpisów jest równych „coś”:
SELECT * FROM test WHERE texte LIKE '%something%' LIMIT 1
zmysql_num_rows()
: 0,039061069488525s. (SZYBCIEJ)SELECT count(*) as count FROM test WHERE text LIKE '%something%
: 16,028197050095s.SELECT EXISTS(SELECT 1 FROM test WHERE text LIKE '%something%')
: 0,87045907974243s.SELECT EXISTS(SELECT 1 FROM test WHERE text LIKE '%something%' LIMIT 1)
: 0,044898986816406s.Ale teraz, z polem BIGINT PK, tylko jeden wpis jest równy „321321”:
SELECT * FROM test2 WHERE id ='321321' LIMIT 1
zmysql_num_rows()
: 0,0089840888977051s.SELECT count(*) as count FROM test2 WHERE id ='321321'
: 0,00033879280090332s.SELECT EXISTS(SELECT 1 FROM test2 WHERE id ='321321')
: 0,00023889541625977s.SELECT EXISTS(SELECT 1 FROM test2 WHERE id ='321321' LIMIT 1)
: 0,00020313262939453s. (SZYBCIEJ)źródło
SELECT 1 FROM test WHERE texte LIKE '%something%' LIMIT 1
select 1 ... limit 1
, nie ma sensu otaczać go za pomocą selectSELECT 1 FROM test WHERE ...
, bezSELECT EXISTS
tego. Prawdopodobnie w ten sposób włosy są szybsze.Krótki przykład odpowiedzi @ ChrisThompson
Przykład:
Korzystanie z aliasu:
źródło
W moich badaniach mogę znaleźć wynik postępujący z prędkością.
źródło
Wydaje mi się, że warto zwrócić uwagę, choć poruszono to w komentarzach, że w tej sytuacji:
Jest lepszy od:
Wynika to z faktu, że pierwsze zapytanie może być spełnione przez indeks, podczas gdy drugie wymaga wyszukiwania wiersza w górę (chyba że wszystkie kolumny tabeli znajdują się w użytym indeksie).
Dodanie
LIMIT
klauzuli pozwala zatrzymać silnik po znalezieniu dowolnego wiersza.Pierwsze zapytanie powinno być porównywalne z:
Który wysyła te same sygnały do silnika (1 / * nie ma tutaj znaczenia), ale nadal zapisałbym 1, aby wzmocnić nawyk podczas używania
EXISTS
:Sensowne może być dodanie
EXISTS
opakowania, jeśli wymagany jest wyraźny zwrot, gdy żadne wiersze nie pasują.źródło
Sugeruj, abyś nie używał,
Count
ponieważ count zawsze powoduje dodatkowe obciążenia dla użycia bazy danychSELECT 1
i zwraca 1, jeśli twój rekord w tym miejscu zwraca wartość null i możesz to obsłużyć.źródło
COUNT zapytania jest szybsza, choć może nie zauważalnie, ale jeśli chodzi o uzyskanie pożądanego rezultatu, oba powinny być wystarczające.
źródło
Czasami bardzo przydatne jest uzyskanie klucza podstawowego automatycznego przyrostu (
id
) wiersza, jeśli istnieje i0
jeśli nie.Oto, jak można to zrobić za pomocą jednego zapytania:
źródło
IFNULL(id, 0)
tutaj zamiastCOUNT(*)
?W przypadku tabel innych niż InnoDB można również użyć tabel schematów informacyjnych:
http://dev.mysql.com/doc/refman/5.1/en/tables-table.html
źródło
Poszedłbym z
COUNT(1)
. Jest szybszy niżCOUNT(*)
ponieważCOUNT(*)
testy sprawdzają, czy przynajmniej jedna kolumna w tym wierszu ma wartość! = NULL. Nie potrzebujesz tego, zwłaszcza że masz już warunek (WHERE
klauzula).COUNT(1)
zamiast tego testuje ważność1
, która jest zawsze ważna i zajmuje dużo mniej czasu na testowanie.źródło
Lub możesz wstawić surową część sql do warunków, więc mam „warunki” => tablica („Member.id NOT IN (SELECT Membership.member_id Z członkostwa AS Członkostwo)”)
źródło
COUNT(*)
są zoptymalizowane w MySQL, więc poprzednie zapytanie prawdopodobnie będzie szybsze.źródło