Który sposób liczenia wierszy powinien być szybszy w MySQL?
To:
SELECT COUNT(*) FROM ... WHERE ...
Lub alternatywą:
SELECT 1 FROM ... WHERE ...
// and then count the results with a built-in function, e.g. in PHP mysql_num_rows()
Można by pomyśleć, że pierwsza metoda powinna być szybsza, ponieważ jest to wyraźnie terytorium bazy danych, a silnik bazy danych powinien być szybszy niż ktokolwiek inny podczas określania takich rzeczy wewnętrznie.
mysql
performance
Franz
źródło
źródło
SELECT 1
i nieSELECT *
. Czy jest jakaś różnica?mysql_query()
, na przykład, cały zestaw wyników jest wysyłany do PHP z MySQL, niezależnie od tego zrobić z tymi danymi.Odpowiedzi:
Kiedy weźmiesz
COUNT(*)
zliczanie indeksów kolumn, to będzie to najlepszy wynik. MySQL z silnikiem MyISAM faktycznie przechowuje liczbę wierszy, nie liczy wszystkich wierszy za każdym razem, gdy próbujesz policzyć wszystkie wiersze. (na podstawie kolumny klucza podstawowego)Używanie PHP do liczenia wierszy nie jest zbyt inteligentne, ponieważ musisz przesyłać dane z mysql do php. Po co to robić, skoro możesz osiągnąć to samo po stronie mysql?
Jeśli
COUNT(*)
działa wolno, należy uruchomićEXPLAIN
zapytanie i sprawdzić, czy indeksy są rzeczywiście używane i gdzie należy je dodać.Poniższe nie jest najszybszym sposobem, ale jest przypadek, w którym
COUNT(*)
tak naprawdę nie pasuje - kiedy zaczynasz grupować wyniki, możesz napotkać problem, w którymCOUNT
tak naprawdę nie liczy się wszystkich wierszy.Rozwiązaniem jest
SQL_CALC_FOUND_ROWS
. Jest to zwykle używane podczas wybierania wierszy, ale nadal musisz znać całkowitą liczbę wierszy (na przykład do stronicowania). Gdy wybierzesz wiersze danych, po prostu dołączSQL_CALC_FOUND_ROWS
słowo kluczowe po SELECT:Po wybraniu potrzebnych wierszy możesz uzyskać liczbę za pomocą tego pojedynczego zapytania:
FOUND_ROWS()
należy wywołać natychmiast po zapytaniu wybierającym dane.Podsumowując, wszystko sprowadza się do tego, ile masz wpisów i co znajduje się w instrukcji WHERE. Naprawdę powinieneś zwrócić uwagę na to, jak używane są indeksy, gdy jest dużo wierszy (dziesiątki tysięcy, miliony i więcej).
źródło
MyISAM
przechowuje liczbę wierszy. Inne mechanizmy przechowywania danych, takie jakInnoDB
nie przechowują liczby wierszy i za każdym razem zliczają wszystkie wiersze .SELECT 1 FROM ... LIMIT 1
czySELECT COUNT(*) FROM ...
?WHERE
klauzula.SELECT COUNT(*) FROM ...
może zająć dużo czasu, w zależności od tego, co ma zostać zeskanowane (np. Bardzo duża tabela lub indeks milionów / miliardów / bilionów wierszy).SELECT 1 FROM ... LIMIT 1
wraca natychmiast, ponieważ ograniczasz go do pierwszego wiersza.Po rozmowie z kolegami z zespołu Ricardo powiedział nam, że najszybszym sposobem jest:
Musisz jednak pamiętać, że wynik może nie być dokładny.
Możesz go również użyć z wiersza poleceń:
Więcej informacji: http://dev.mysql.com/doc/refman/5.7/en/show-table-status.html
Pełną dyskusję można znaleźć na blogu mysqlperformanceblog
źródło
SHOW TABLE STATUS
(lub odpowiednikSELECT
winformation_schema
) jest szybkie, ale nie obsługujeWHERE
klauzuli. Jest dokładny dla MyISAM, ale nieprecyzyjny (czasami o współczynnik 2) dla InnoDB.Świetne pytanie, świetne odpowiedzi. Oto szybki sposób na powtórzenie wyników, jeśli ktoś czyta tę stronę i brakuje jej części:
źródło
as count
?id
jest zagmatwany na pierwszy rzut oka.To zapytanie (podobne do tego, które opublikował Bayuah ) pokazuje ładne podsumowanie wszystkich tabel w bazie danych: (uproszczona wersja procedury składowanej autorstwa Ivana Cachicatari, którą bardzo polecam).
Przykład:
źródło
information_schema
nie jest taka sama, jak wartość zwracana przezSELECT count(*) FROM
InnoDB. Jeśli potrzebujesz ścisłej wartości, pamiętaj, że ta metoda daje ścisłą wartość tylko w przypadku tabel MyISAM. W przypadku InnoDB liczba wierszy jest przybliżona.Zawsze rozumiałem, że poniższe informacje dają mi najszybsze czasy odpowiedzi.
źródło
SELECT 1 ...
powróci w wielu rzędach jak osobyWHERE
iLIMIT
poprosić, a oni wszystko będzie „1”.show table status like '<TABLE NAME>'
To będzie znacznie szybsze.WHERE
klauzulę. A dla InnoDB to tylko szacunki.Jeśli chcesz uzyskać zliczenie całego zestawu wyników, możesz zastosować następujące podejście:
Zwykle nie jest to szybsze niż używanie,
COUNT
chociaż można by pomyśleć, że jest odwrotnie, ponieważ wykonuje obliczenia wewnętrznie i nie wysyła danych z powrotem do użytkownika, dlatego podejrzewa się poprawę wydajności.Wykonanie tych dwóch zapytań jest dobre do paginacji w celu uzyskania sum, ale nie jest szczególnie przydatne w przypadku używania
WHERE
klauzul.źródło
Zrobiłem kilka testów porównawczych, aby porównać czas wykonania
COUNT(*)
vsCOUNT(id)
(id jest kluczem podstawowym tabeli - indeksowany).Liczba prób: 10 * 1000 zapytań
Rezultat:
COUNT(*)
jest szybszy 7%WIDOK GRAPH: benchmarkgraph
Radzę użyć:
SELECT COUNT(*) FROM table
źródło
COUNT(1)
, byłoby interesujące zobaczyć tam kilka testów ...Spróbuj tego:
źródło
select count(*) from table_name
lub coś innego. dba.stackexchange.com/questions/151769/…Być może warto rozważyć wykonanie
SELECT max(Id) - min(Id) + 1
. To zadziała tylko wtedy, gdy twoje identyfikatory są sekwencyjne, a wiersze nie zostaną usunięte. Jest jednak bardzo szybki.źródło
EXPLAIN SELECT id FROM ....
załatwił sprawę dla mnie. i mogłem zobaczyć liczbę wierszy podrows
kolumną wyniku.źródło
Obsługiwałem tabele dla rządu niemieckiego z czasami 60 milionami rekordów.
I musieliśmy znać wiele razy sumę wierszy.
Tak więc my, programiści baz danych, zdecydowaliśmy, że w każdej tabeli jest rekord jeden zawsze taki rekord, w którym przechowywana jest całkowita liczba rekordów. Zaktualizowaliśmy tę liczbę w zależności od wierszy INSERT lub DELETE.
Próbowaliśmy wszystkich innych sposobów. To zdecydowanie najszybszy sposób.
źródło
Instrukcja count (*) z warunkiem gdzie na kluczu podstawowym zwróciła liczbę wierszy znacznie szybciej, dzięki czemu uniknąłem pełnego skanowania tabeli.
To było dla mnie znacznie szybsze niż
źródło