Jump to content

Fastest way to import data in SQLite DB


Recommended Posts

You can insert a number N of rows in a single insert statement (see the syntax here). Doing so you only invoke one SQLite call (*) and this is much faster than doing N individual inserts. N is bounded by the size of the whole statement, say with your example content you can easily group 100 rows in one INSERT, but 1000 may exceed allowable statement string size (I don't know what the limit is exactly). Doing that in a loop placed inside a transaction speeds things up very signifcantly.

Yet AutoIt being slow and DllCall eating "some time", you benefit from using the standalone CLI (sqlite3.exe). In the example I ran and posted, 11k rows were inserted in under one second.

One thing though, it seems that the CLI doesn't like column names surrounded by double quotes.

I'll try to look why we get an error using _SQLite_SQLite3.exe().

 

(*) In fact the gain in runtime is because the statement is only "prepared" once and values for successive rows binded to this prepared statement. SQLite "prepares" statements fed to it by "compiling" them, turning them into a series of pseudo-executable bytecode ops. This requires checking the schema and the statement for validity and going thru the query optimizer. Doing that only once for N rows is a huge time gain.

Edited by jchd

This wonderful site allows debugging and testing regular expressions (many flavors available). An absolute must have in your bookmarks.
Another excellent RegExp tutorial. Don't forget downloading your copy of up-to-date pcretest.exe and pcregrep.exe here
RegExp tutorial: enough to get started
PCRE v8.33 regexp documentation latest available release and currently implemented in AutoIt beta.

SQLitespeed is another feature-rich premier SQLite manager (includes import/export). Well worth a try.
SQLite Expert (freeware Personal Edition or payware Pro version) is a very useful SQLite database manager.
An excellent eBook covering almost every aspect of SQLite3: a must-read for anyone doing serious work.
SQL tutorial (covers "generic" SQL, but most of it applies to SQLite as well)
A work-in-progress SQLite3 tutorial. Don't miss other LxyzTHW pages!
SQLite official website with full documentation (may be newer than the SQLite library that comes standard with AutoIt)

Link to comment
Share on other sites

Fransesco,

Example from proof of concept I did some time ago...note the library dataset name...

#include <FileConstants.au3>
#include <sqlite.au3>
#include <array.au3>

Local $sSQLiteMod = 'C:\Program Files (x86)\AutoIt3\install\Extras\SQLite\sqlite3.exe'

; do NOT use AutoIt macros for the next two file names

Local $sMasterFile = "fully.qualified.filename" ; your file with ALL entries
Local $sDetailFile = "fully.qualified.filename" ; your file with SOME entries

$st = TimerInit()

Local $sIn = 'create table if not exists mstr (c1);' & _
        'create table if not exists det (c1);' & _
        @CRLF & '.import ' & $sMasterFile & ' MSTR' & _
        @CRLF & '.import ' & $sDetailFile & ' DET' & _
        @CRLF & 'SELECT DISTINCT c1 FROM mstr WHERE c1 Not IN (SELECT DISTINCT c1 FROM det);'

Local $Out = _TempFile()
Local $in = _TempFile()

FileWrite($in, $sIn)

Local $sCmd = @ComSpec & ' /c "' & $sSQLiteMod & '" < ' & $in & ' > ' & $Out
Local $pid = RunWait($sCmd, @WorkingDir, @SW_HIDE)
ProcessWaitClose($pid)
ConsoleWrite('Time to find entries unique to mstr = ' & Round(TimerDiff($st) / 1000, 3) & ' seconds' & @CRLF)
ConsoleWrite(StdoutRead($pid) & @CRLF)
ConsoleWrite('! out ' & @CRLF & FileRead($Out) & @CRLF)

FileDelete($Out)
FileDelete($in)

kylomas

edit: How much time are we talking about if you use batched txns and chained inserts (what jchd cited earlier)?

Edited by kylomas

Forum Rules         Procedure for posting code

"I like pigs.  Dogs look up to us.  Cats look down on us.  Pigs treat us as equals."

- Sir Winston Churchill

Link to comment
Share on other sites

Guys, in the scenario that I have, what is the best solution, in terms of efficency?

I have a .txt file from which I retrieve some data. This file grows daily, and the information are divided from @TAB... But, some fields, are enclosed by double quotes...
This file is a "storical" log of some alarms in a system ( automation system, not something that I want to hack/violate ).

So, from this file, I have to create a report... 
The report tool I use is named Crystal Reports... It's a VB based tool that allows the user to create a report from a large variety of input files ( .txt, MySQL DB, ODBC and so on... ).

At the moment, the procedure that I've been using for create a report, is read from the source file, that is a .txt file, read the content of the file in an array with _FileReadToArray(), module the information in a For...Next loop, replacing @TABs with semi-colon, double quotes with nothing ( "" ), and splitting the line just moduled with StringSplit(), taking the semicolon as separator, in order to have the fields in an array. Then, I parse the field(s) of the array splitted with the user data, inserted in a GUI ( a date, for example ). If there is a match, I write all the fields of the splitted array in a file. When all the lines have been compared, I run an .exe that I've made through Crystal Reports, and so, I have my report.

Now, I'd like to do something like that, but, with SQLite this time, because the query I should do, are more easy to do through a database instead of a .txt file...
I have to select data between two timestamps, and this, is very easy to do with SQLite with instruction like BETWEEN or LIKE, with just a query, without split anything...

What is the best way to do all this stuff? 
I tried different approaches to this scenario, but I still can't find the fastest...

Don't post codes for now... I want to understand the functionality of what I'd like to develop.

Thanks a lot for everyone has read 'til here.

Have a good lunch :)

Francesco

EDIT: 

@jchd, I've seen that the best solution for fast inserts is group them and then, make a bulk insert ( as you suggested ).

What is the limit for the bulk insert, always in terms of efficiency? 

Thanks :D 

Edited by FrancescoDiMuro
Thanks jchd! :D

Click here to see my signature:

Spoiler

ALWAYS GOOD TO READ:

 

Link to comment
Share on other sites

Using sqlite3.exe for direct massive insert of large .tsv file is by far the fastest way. I believe I' have found the reason for the failure of _SQLite_SQLiteExe(). The return code of the RunWait call (variable $nErrorLevel) is 1 albeit the command ran successfully.

To fix, edit the UDF and change line 847:

If @error = 1 Or $nErrorLevel = 1 Then
to
        If @error = 1 And $nErrorLevel = 1 Then

Using this the test script I wrote builds an ALARMI table with 44735 rows in under a second on my prehistoric PC.

If you stick to AutoIt code to do the same, indeed looping insertion of multiple rows, all inside a transaction, is the next fastest way. The practical limit is to be determined as many factors play a role. Experimentation is your best advisor.

This wonderful site allows debugging and testing regular expressions (many flavors available). An absolute must have in your bookmarks.
Another excellent RegExp tutorial. Don't forget downloading your copy of up-to-date pcretest.exe and pcregrep.exe here
RegExp tutorial: enough to get started
PCRE v8.33 regexp documentation latest available release and currently implemented in AutoIt beta.

SQLitespeed is another feature-rich premier SQLite manager (includes import/export). Well worth a try.
SQLite Expert (freeware Personal Edition or payware Pro version) is a very useful SQLite database manager.
An excellent eBook covering almost every aspect of SQLite3: a must-read for anyone doing serious work.
SQL tutorial (covers "generic" SQL, but most of it applies to SQLite as well)
A work-in-progress SQLite3 tutorial. Don't miss other LxyzTHW pages!
SQLite official website with full documentation (may be newer than the SQLite library that comes standard with AutoIt)

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

×
×
  • Create New...