Szybkość wykonywania poleceń SQLite

0

Piszę w C# prosty program obsługujący bazę danych SQLite. Do połączenia wykorzystuję darmową bibliotekę System.Data.SQLite.dll.

Program działa tak, że jak się na wejściu poda pewien tekst, to program rozdziela go na poszczególne linie i uruchamia każdą linię osobno w pętli, ponieważ w odróżnieniu od MS SQL, SQLite nie umie przetworzyć serii poleceń za jednym zamachem.

Testowa seria:

create table TestTable (Brand varchar(100), BOX int, Begin varchar(100), End varchar(100))
insert into TestTable values ('ALFA',1,'0','210')
insert into TestTable values ('ALFA',2,'211','349')
insert into TestTable values ('ALFA',3,'350','460')
insert into TestTable values ('ALFA',4,'461','590')
insert into TestTable values ('ALFA',5,'591','715')
insert into TestTable values ('ALFA',6,'716','<')
insert into TestTable values ('AST',1,'0','<')
insert into TestTable values ('BENT',1,'0','<')
insert into TestTable values ('BLMC',1,'0','JQ')
insert into TestTable values ('BLMC',2,'JR','<')
insert into TestTable values ('BMW',1,'0','3')
insert into TestTable values ('BMW',2,'4','A49')
insert into TestTable values ('BMW',3,'A50','<')
insert into TestTable values ('CHRY',1,'0','G')
insert into TestTable values ('CHRY',2,'H','PR')
insert into TestTable values ('CHRY',3,'PS','<')
insert into TestTable values ('CITR',1,'0','EX')
insert into TestTable values ('CITR',2,'EY','KJ')
insert into TestTable values ('CITR',3,'KK','KP')
insert into TestTable values ('CITR',4,'KQ','<')
insert into TestTable values ('DAEW',1,'0','49')
insert into TestTable values ('DAEW',2,'50','<')
insert into TestTable values ('DAI',1,'0','G')
insert into TestTable values ('DAI',2,'H','<')
insert into TestTable values ('FAUS',1,'0','<')
insert into TestTable values ('FER',1,'0','<')
insert into TestTable values ('FIAT',1,'0','210')
insert into TestTable values ('FIAT',2,'211','349')
insert into TestTable values ('FIAT',3,'350','460')
insert into TestTable values ('FIAT',4,'461','590')
insert into TestTable values ('FIAT',5,'591','715')
insert into TestTable values ('FIAT',6,'716','<')
insert into TestTable values ('FORD',1,'0','590')
insert into TestTable values ('FORD',2,'591','680')
insert into TestTable values ('FORD',3,'681','<')
insert into TestTable values ('FUSA',1,'0','D')
insert into TestTable values ('FUSA',2,'E','J')
insert into TestTable values ('FUSA',3,'K','SN')
insert into TestTable values ('FUSA',4,'SO','<')
insert into TestTable values ('GM',1,'0','25')
insert into TestTable values ('GM',2,'26','44')
insert into TestTable values ('GM',3,'45','70')
insert into TestTable values ('GM',4,'71','89')
insert into TestTable values ('GM',5,'90','<')
insert into TestTable values ('GMH',1,'0','<')
insert into TestTable values ('HON',1,'0','BG4')
insert into TestTable values ('HON',2,'BG5','NH630')
insert into TestTable values ('HON',3,'NH631','R5')
insert into TestTable values ('HON',4,'R6','<')
insert into TestTable values ('HYU',1,'0','G')
insert into TestTable values ('HYU',2,'H','O')
insert into TestTable values ('HYU',3,'P','U')
insert into TestTable values ('HYU',4,'V','<')
insert into TestTable values ('ISU',1,'0','<')
insert into TestTable values ('JAG',1,'0','<')
insert into TestTable values ('KIA',1,'0','E')
insert into TestTable values ('KIA',2,'F','<')
insert into TestTable values ('LADA',1,'0','<')
insert into TestTable values ('LAM',1,'0','<')
insert into TestTable values ('LOT',1,'0','<')
insert into TestTable values ('LRR',1,'0','JQ')
insert into TestTable values ('LRR',2,'JR','<')
insert into TestTable values ('MAS',1,'0','<')
insert into TestTable values ('MAZ',1,'0','29')
insert into TestTable values ('MAZ',2,'30','<')
insert into TestTable values ('MER',1,'0','52')
insert into TestTable values ('MER',2,'53','<')
insert into TestTable values ('MINI',1,'0','3')
insert into TestTable values ('MINI',2,'4','A49')
insert into TestTable values ('MINI',3,'A50','<')
insert into TestTable values ('MIT',1,'0','E')
insert into TestTable values ('MIT',2,'F','S')
insert into TestTable values ('MIT',3,'T','<')
insert into TestTable values ('NIS',1,'0','BS')
insert into TestTable values ('NIS',2,'BT','D')
insert into TestTable values ('NIS',3,'E','KK')
insert into TestTable values ('NIS',4,'KL','<')
insert into TestTable values ('OPEL',1,'0','20')
insert into TestTable values ('OPEL',2,'21','369')
insert into TestTable values ('OPEL',3,'370','<')
insert into TestTable values ('PEU',1,'0','EX')
insert into TestTable values ('PEU',2,'EY','KJ')
insert into TestTable values ('PEU',3,'KK','KP')
insert into TestTable values ('PEU',4,'KQ','<')
insert into TestTable values ('POR',1,'0','<')
insert into TestTable values ('PROT',1,'0','<')
insert into TestTable values ('REN',1,'0','6')
insert into TestTable values ('REN',2,'7','D')
insert into TestTable values ('REN',3,'E','<')
insert into TestTable values ('RR',1,'0','<')
insert into TestTable values ('SAAB',1,'0','<')
insert into TestTable values ('SEAT',1,'0','<')
insert into TestTable values ('SKO',1,'0','<')
insert into TestTable values ('SMAR',1,'0','<')
insert into TestTable values ('SSA',1,'0','<')
insert into TestTable values ('SUB',1,'0','4')
insert into TestTable values ('SUB',2,'5','<')
insert into TestTable values ('SUZ',1,'0','Z6')
insert into TestTable values ('SUZ',2,'Z7','ZJ9')
insert into TestTable values ('SUZ',3,'ZJA','<')
insert into TestTable values ('TOY',1,'0','1D')
insert into TestTable values ('TOY',2,'1E','3N')
insert into TestTable values ('TOY',3,'3O','6L')
insert into TestTable values ('TOY',4,'6M','750')
insert into TestTable values ('TOY',5,'751','8P')
insert into TestTable values ('TOY',6,'8Q','<')
insert into TestTable values ('UC',1,'1','<')
insert into TestTable values ('VOL',1,'0','3')
insert into TestTable values ('VOL',2,'4','<')
insert into TestTable values ('VW',1,'0','C3')
insert into TestTable values ('VW',2,'C4','K')
insert into TestTable values ('VW',3,'L','Y3')
insert into TestTable values ('VW',4,'Y4','<')
insert into TestTable values ('WHEEL',1,'0','<')

Wykonanie serii w transakcji i poza transakcją w tym programie wygląda tak samo, jedyna różnica, to taka, że przed pętlą jest otwarcie transakcji, po pętli jej zamknięcie (commit lub rollback), a przy generowaniu polecenia, przd jego wykonaniem jest ono wiązane z daną transakcją. W takim razie różnica w szybkości wynika na pewno z pracy bazy danych a nie z mojego kodu (czas przetwarzania i wykonania od strony programu jest praktycznie taki sam w obu przypadkach).

W tym wszystkim zadziwiający jest fakt, że jak się wykona powyższą serię poza transakcją, to trwa to kilka sekund, a jak się wykona w transakcji, to wykonanie trwa ułamek sekundy. Sprawdzałem i w obu przypadkach tabela jest prawidłowo zbudowana i wypełniona danymi.

Tak na chłopski rozum, to wykonanie w transakcji powinno być wolniejsze niz poza transakcją, bo w transakcji system bazodanowy oprócz zapisu danych musi gdzieś zapisywać co i gdzie zmienić, żeby mógł wszystko odwrócić przy wykonaniu rollback, a tutaj jest dokładnie na odwrót. Dlaczego?

1

Nie wiem jak to robi sqlite, ale może po prostu nie objęcie instrukcji transakcją powoduje automatyczne obejmowanie każdego polecenia osobno w transakcje?

0

Gdy wykonujesz serię insertów poza transakcją to SQLite musi dla każdej takiej operacji znaleźć tę tabelę, sprawdzić gdzie się kończy (jakie id nadać) czy zapytanie nie narusza PK, FK itd. Gdy wykonujesz serię insertów w transakcji to SQLite pamięta po wykonaniu pierwszego INSERT gdzie jest tabela, gdzie się kończy itd. nie musi wykonywać szeregu operacji osobno dla każdego inserta.

0

Oczywiście ze SQLite potrafi wykonać duża liczbę poleceń za jednym razem. Tu kłania się wrapper.
Ja zapisuje do bazy SQLite ponad 15000 rekordów ( transakcji )ktore odczytuje z pliku tekstowego w niecałe 3 sekundy.

0
lechk napisał(a):

Oczywiście ze SQLite potrafi wykonać duża liczbę poleceń za jednym razem. Tu kłania się wrapper.
Ja zapisuje do bazy SQLite ponad 15000 rekordów ( transakcji )ktore odczytuje z pliku tekstowego w niecałe 3 sekundy.

Czy ten projekt i wrapper jest w C#?

Jeżeli tak, to czy łączysz się przez interfejs IDbConnection, a polecenie wykonujesz przez IDbCommand, tylko, że z użyciem innej biblioteki niż System.Data.Sqlite (działa tylko w Windows) lub Mono.Data.SqliteClient (działa tylko w Linux), która zawiera w sobie ten wrapper, który przetwarza zapytanie, jak się poda na wejściu serię? Jeżeli tak, to jaka to biblioteka i w jakim systemie działą? Jeżeli nie, to w jaki sposób można to zrobić?

0

Ja pisze w c++ wxWingets + SQLite

1 użytkowników online, w tym zalogowanych: 0, gości: 1