2013-08-05 8 views
7

Jaki jest najszybszy sposób sprawdzenia, czy tabela SQLite ma więcej niż 100 000 wierszy?SQLite: najszybszy sposób sprawdzenia, czy tabela ma więcej niż x wierszy


Tabela testowa ma 26 kolumn i 200 000 000 wierszy.

SELECT COUNT(*) FROM (SELECT * FROM table LIMIT 100001) 

zajęło 0,27 sekundy.

następujące trzy potrzebne 12 i pół minuty

SELECT COUNT(*) FROM table 
SELECT COUNT(*) FROM table LIMIT 100001 
SELECT CASE WHEN COUNT(Id) >= 100000 THEN 1 ELSE 0 END FROM table 
+5

wybierz liczbę (*) ze stołu? –

+3

SELECT * nie jest dobrym pomysłem, aby uzyskać liczbę wierszy, użyj pola indeksowanego. – ChrisBint

+3

@ChrisBint: potrzebny jest indeks na kolumnie ** not null ** (np. PK) nie tylko "* jakiś indeks *". Większość DBMS, które znam, automatycznie używa takiego indeksu dla 'count (*)'. Czy twój komentarz sugeruje, że SQLite nie jest tak inteligentny? –

Odpowiedz

3
select count(*) from (
select top 100001 ID from T 
) x 

Musimy zeskanować indeks, aby odpowiedzieć na zapytanie. To przynajmniej ogranicza skanowanie indeksu do pierwszych 100001 wierszy. Jeśli tabela ma 1m wierszy, oszczędza to 90% pracy.

(Używając tutaj składni SQL Server - przetłumacz proszę, ponieważ nie mogę tego zrobić).

Zamiast identyfikatora można wybrać kolumnę indeksowaną. Nie wiem, czy sam optymalizator może to zrobić.

Należy zauważyć, że sprytne sztuczki, takie jak sprawdzanie wartości identyfikacyjnych lub wartości kolumny ID, nie działają ogólnie.

Aby wesprzeć powyższe zapytanie, utwórz manekinową kolumnę typu bit i zindeksuj ją. Indeks będzie bardzo kompaktowy i najszybszy do skanowania.

0
SELECT COUNT (Column) FROM TABLE 

Zapewnienie, że kolumna wybrany jest indeksowany, korzystnie INT.

+0

Jak już wskazano w innych odpowiedziach i komentarzach, 'Column' nie może być zniesiony. –

1
SELECT COUNT(indexed_column) FROM TableName 

Teraz indeksowane część kolumny jest ważną rzeczą, że nie chcesz zrobić coś jak liczenie *, chcesz być jak najbardziej konkretny zmuszając SQL w użyciu indeks, który jest istniejący dla każdego wiersza na ten stół.

0
SELECT CASE WHEN COUNT(indexed_column) >= 100000 THEN 1 ELSE 0 END FROM table 

Czy nie powinien tego robić? Raporty 1, jeśli jest ich więcej niż 100 000 i 0 w przeciwnym razie

1

Cię ugryzą, gdy masz dużo wierszy. Działa - ale pytasz o najszybszy sposób w sqlite.

Zastosowanie:

SELECT max(rowid) AS rowcount

Jak NoLifeKing wskazał to tylko działa prawidłowo, jeśli nie masz żadnych skreśleń. W przeciwnym razie będzie to niespójne i będziesz mieć wyższy poziom wierszy, jak jest w rzeczywistości.

Zapoznaj się z http://www.sqlite.org/autoinc.html o zasadach, jak Sqlite tworzy rowid.

+4

Problem z tym może być, jeśli jest to tabela, w której znajdują się 'DELETE' wiersze. – NoLifeKing

+0

co, jeśli zdecyduję się umieścić moje wiersze w tabeli uporządkowane według malejących identyfikatorów? co jeśli maksymalny id rzędu jest ujemny;) – DrCopyPaste

0
select count(*) from table  
select max(id) from table 

jeśli tabela ma klucz podstawowy identyfikator, drugi na

+2

count (*) nie jest dobry (jak wspomniano powyżej przez ChrisaBinta), ponieważ nie jest w stanie efektywnie korzystać z indeksów; max (id) nie jest dobry, ponieważ tabele mogą być pofragmentowane i nie można założyć dla wszystkich tabel, które mają inkrementujące id – DrCopyPaste

1

Jeśli nie ma żadnego indeksowanej kolumny, myślę, że najszybszym sposobem byłoby (dla N = 100000)

select 1 from test1 limit 1 offset 100000; 

Dzieje się tak, ponieważ dostaniesz tylko N + 1 wierszy. Bez liczenia, bez maks.

można spróbować tutaj sqlfiddle

+0

Zwrócenie wszystkich wierszy byłoby znacznie wolniejsze niż zliczanie ich w silniku. Bardzo wolniej. – usr

+1

Nie mam tutaj zainstalowanego SQLite, ale sqlfiddle (SQLite.js) pokazuje, że przesunięcie jest znacznie szybsze niż liczenie. Nie jestem ekspertem od SQLite, byłoby wspaniale, gdyby ktoś przetestował to na stole z całkowitą liczbą znacznie większą niż N. Mógłbym to zrobić później, jeśli nikt nie będzie –

+1

Przeoczyłem, że nie wracasz wszystkie wiersze, tylko liczba. W takim przypadku twoja odpowiedź jest dobra, ponieważ mieliśmy ten sam pomysł :) – usr

0
select count(*) from table 

- optymalizator kwerendy automatycznie wybiera kolumny indeksowanej.

Powiązane problemy