Mam kilka duplikatów w bazie danych, które chcę sprawdzić, więc co zrobiłem, aby zobaczyć, które są duplikatami, zrobiłem to:
SELECT relevant_field
FROM some_table
GROUP BY relevant_field
HAVING COUNT(*) > 1
W ten sposób otrzymam wszystkie wiersze z odpowiednim_polem występującym więcej niż raz. Wykonanie tego zapytania zajmuje milisekundy.
Teraz chciałem sprawdzić każdy z duplikatów, więc pomyślałem, że mogę WYBRAĆ każdy wiersz w some_table z odpowiednim_polem w powyższym zapytaniu, więc zrobiłem tak:
SELECT *
FROM some_table
WHERE relevant_field IN
(
SELECT relevant_field
FROM some_table
GROUP BY relevant_field
HAVING COUNT(*) > 1
)
Z jakiegoś powodu okazuje się to niezwykle powolne (zajmuje to kilka minut). Co dokładnie się tu dzieje, że jest tak powolny? odpowiednie_field jest indeksowane.
Ostatecznie spróbowałem utworzyć widok „temp_view” na podstawie pierwszego zapytania (SELECT relevant_field FROM some_table GROUP BY relevant_field HAVING COUNT(*) > 1)
, a następnie wykonałem drugie zapytanie w ten sposób:
SELECT *
FROM some_table
WHERE relevant_field IN
(
SELECT relevant_field
FROM temp_view
)
I to działa dobrze. MySQL robi to w kilka milisekund.
Czy są tu jacyś eksperci SQL, którzy mogą wyjaśnić, co się dzieje?
Odpowiedzi:
Przepisz zapytanie do tego
Myślę, że
st2.relevant_field
musi być w selekcji, bo inaczejhaving
klauzula da błąd, ale nie jestem w 100% pewienNigdy nie używaj
IN
z podzapytaniem; jest to notorycznie powolne.Używaj tylko
IN
ze stałą listą wartości.Więcej podpowiedzi
SELECT *
wybieraj tylko tych pól, których naprawdę potrzebujesz.relevant_field
aby przyspieszyć sprzężenie równe.group by
klucz podstawowy.Ogólne rozwiązanie dla 90% Twoich
IN (select
zapytańUżyj tego kodu
źródło
HAVING COUNT(*) > 1
. W MySQL jest to zwykle szybsze.st2.relevant_field
nie jestNULL
(jest już zawarty wON
klauzuli), nie zmieni to wyniku.afield
nigdy nie będzienull
, rozumiem . Dziękigroup by
jest włączonast1.id
, a nie włączonast1.relevant_field
.Podzapytanie jest uruchamiane dla każdego wiersza, ponieważ jest to zapytanie skorelowane. Można przekształcić zapytanie skorelowane w zapytanie nieskorelowane, wybierając wszystko z podzapytania, na przykład:
Ostateczne zapytanie wyglądałoby następująco:
źródło
SELECT *
opakowanie jest potrzebne.Podzapytania a sprzężenia
http://www.scribd.com/doc/2546837/New-Subquery-Optimizations-In-MySQL-6
źródło
Wypróbowałem zapytanie w jednej z moich baz danych, a także przepisałem je jako sprzężenie z zapytaniem podrzędnym.
To działało dużo szybciej, spróbuj!
źródło
Spróbuj tego
źródło
Sformatowałem Twoje powolne zapytanie sql z adresem www.prettysql.net
Używając tabeli zarówno w zapytaniu, jak i podzapytaniu, należy zawsze używać aliasów do obu, na przykład:
To pomaga?
źródło
Po pierwsze, możesz znaleźć zduplikowane wiersze i znaleźć liczbę wierszy używaną ile razy i uporządkować według liczby w ten sposób;
następnie utwórz tabelę i wstaw do niej wynik.
Na koniec usuń wiersze do opublikowania. Numer zaczyna się od 0. Z wyjątkiem pierwszego numeru każdej grupy usuń wszystkie wiersze do opublikowania.
źródło
czasami, gdy dane rosną, mysql WHERE IN może działać dość wolno z powodu optymalizacji zapytań. Spróbuj użyć STRAIGHT_JOIN, aby powiedzieć mysql, aby wykonywał zapytanie tak, jak jest, np
ale uwaga: w większości przypadków optymalizator mysql działa całkiem nieźle, więc polecam go używać tylko wtedy, gdy masz tego rodzaju problem
źródło
Jest to podobne do mojego przypadku, w którym mam tabelę o nazwie
tabel_buku_besar
. To, czego potrzebuję, toPatrząc na zapis, że mają
account_code='101.100'
wtabel_buku_besar
którychcompanyarea='20000'
a takżeIDR
jakocurrency
Muszę pobrać wszystkie rekordy, z
tabel_buku_besar
których kod_konta jest taki sam jak w kroku 1, aletransaction_number
wynik w kroku 1podczas używania
select ... from...where....transaction_number in (select transaction_number from ....)
moje zapytanie działa bardzo wolno i czasami powoduje przekroczenie limitu czasu żądania lub powoduje, że moja aplikacja nie odpowiada ...Próbuję tej kombinacji i efekt ... nieźle ...
źródło
Uważam, że jest to najbardziej efektywne w wyszukiwaniu, czy wartość istnieje, logikę można łatwo odwrócić, aby znaleźć, czy wartość nie istnieje (tj. JEST NULL);
* Zastąp odpowiednie_pole nazwą wartości, którą chcesz sprawdzić, czy istnieje w Twojej tabeli
* Zastąp primaryKey nazwą kolumny klucza podstawowego w tabeli porównawczej.
źródło