Wszyscy wiedzą, że w tabelach, które używają InnoDB jako silnika, zapytania takie SELECT COUNT(*) FROM mytable
są bardzo niedokładne i bardzo wolne, szczególnie gdy tabela staje się większa i ciągłe wstawianie / usuwanie wierszy podczas wykonywania tego zapytania.
Tak jak to rozumiem, InnoDB nie przechowuje liczby wierszy w zmiennej wewnętrznej, co jest przyczyną tego problemu.
Moje pytanie brzmi: dlaczego tak jest? Czy tak trudno byłoby przechowywać takie informacje? To ważna informacja, którą należy znać w tak wielu sytuacjach. Jedyną trudnością, jaką widzę, jeśli taki wewnętrzny licznik zostałby zaimplementowany, jest zaangażowanie transakcji: jeśli transakcja jest niezatwierdzona, czy liczycie wstawione wiersze, czy nie?
PS: Nie jestem ekspertem od DB, jestem po prostu kimś, kto ma MySQL jako proste hobby. Więc jeśli tylko zapytałem o coś głupiego, nie bądź zbyt krytyczny: D.
SELECT COUNT(*) FROM ...
zapytania są dokładne. Jeśli wolisz, phpMyAdmin można skonfigurować tak, aby zawsze używał dokładnej liczby wierszy kosztem szybkości. Więcej informacji: stackoverflow.com/questions/11926259/…Odpowiedzi:
Zgadzam się z @RemusRusanu (+1 za odpowiedź)
SELECT COUNT(*) FROM mydb.mytable
w InnoDB zachowuje się tak, jak powinien transakcyjny silnik pamięci. Porównaj to z MyISAM.MyISAM
W
mydb.mytable
przypadku tabeli MyISAM uruchamianieSELECT COUNT(*) FROM mydb.mytable;
jest jak uruchamianieSELECT table_rows FROM information_schema.table WHERE table_schema = 'mydb' AND table_name = 'mytable';
. To powoduje szybkie sprawdzenie liczby wierszy w nagłówku tabeli MyISAM.InnoDB
Jeśli
mydb.mytable
jest to stolik InnoDB, dostajesz mnóstwo rzeczy. Prowadzisz MVCC, regulując następujące kwestie:Pytanie InnoDB o liczbę tabel wymaga nawigacji przez te złowieszcze rzeczy. W rzeczywistości nigdy tak naprawdę nie wiadomo, czy
SELECT COUNT(*) from mydb.mytable
liczy się tylko odczyty powtarzalne, czy obejmuje odczyty, które zostały zatwierdzone i te, które nie zostały zatwierdzone.Możesz spróbować trochę ustabilizować sytuację, włączając innodb_stats_on_metadata .
Zgodnie z dokumentacją MySQL na temat danych innodb_stats_on_meta_data
Wyłączenie go może, ale nie musi, dać bardziej stabilną liczbę w zakresie konfigurowania planów EXPLAIN. Może to wpływać na wydajność
SELECT COUNT(*) from mydb.mytable
w dobry, zły sposób lub wcale. Spróbuj i zobacz !!!źródło
Na początek nie ma czegoś takiego jak „bieżąca liczba” do przechowywania w zmiennej. Podobne zapytanie
SELECT COUNT(*) FROM ...
jest zależne od bieżącego poziomu izolacji i wszystkich jednoczesnych oczekujących transakcji. W zależności od poziomu izolacji zapytanie może wyświetlać lub nie wyświetlać wierszy wstawianych lub usuwanych przez oczekujące niezatwierdzone transakcje. Jedynym sposobem na odpowiedź jest policzenie wierszy widocznych dla bieżącej transakcji.Zauważ, że nawet nie dotknąłem jeszcze bardziej drażliwego tematu współbieżnych transakcji, które zaczynają się lub kończą podczas liczenia. Nie wspominając już o wycofywaniu ...
źródło
COUNT(*)
zapytania są w rzeczywistości rzadko potrzebne i zwykle wynikają z braku doświadczenia programisty (policz wiersze, zanim je wybierzemy!) Lub złego projektu aplikacji.SELECT COUNT(*)
, dodaj niezoptymalizowanąWHERE
tabelę, a będziesz mieć kilku użytkowników rzucających db na kolana, aby uzyskać kilka wątpliwych użytecznych liczników statystyk.Chociaż teoretycznie byłoby możliwe utrzymanie dokładnej liczby wierszy dla danej tabeli za pomocą InnoDB, byłoby to kosztem dużej ilości blokowania, co negatywnie wpłynęłoby na wydajność. Różniłby się również w zależności od poziomu izolacji.
MyISAM już blokuje na poziomie stołu, więc nie ma tam dodatkowych kosztów.
Rzadko wymagam liczenia wierszy dla tabeli, chociaż dość często używam COUNT (*). Zasadniczo mam dołączoną klauzulę WHERE. Używając wydajnego indeksu dla małego zestawu wyników, stwierdzam, że są wystarczająco szybkie.
Nie zgadzam się, że liczby są niedokładne. Liczby reprezentują migawkę danych i zawsze uważałem, że są dokładne.
Krótko mówiąc, MySQL pozostawia Ci wdrożenie tego w InnoDB. Możesz przechowywać liczbę i zwiększać / zmniejszać ją po każdym zapytaniu. Jednak łatwiejszym rozwiązaniem jest prawdopodobnie przejście na MyISAM.
źródło