Performance base de données SQLite

Vous débutez et vous avez besoin d'aide ? N'hésitez pas à poser vos questions
Cls
Messages : 620
Inscription : mer. 22/juin/2005 8:51
Localisation : Nantes

Message par Cls »

J'ai trouvé un peu de temps pour tester ":memory:" (toujours assez superficiellement, il faudrait approfondir en testant SELECT / UPDATE / INSERT... :roll:).

Les fichiers générés font la même taille que lors du test précédent (voir post précédent).

Ce temps correspond au test complet, c'est à dire :
- création de la base / ouverture [1]
- remplissage en mémoire [2]
- écriture sur le disque [3]
- fermeture [4]
(voir code ci dessous)

30k INSERT : 1812 ms
300k INSERT : 17281 ms
3000k INSERT : 175234 ms


Voici le détails du remplissage en mémoire (étape [2]) :


30k INSERT : 750 ms
300k INSERT : 7828 ms
3000k INSERT : 79704 ms


On peut donc en déduire le temps pour écrire sur le disque

30k INSERT : 1062 ms environ
300k INSERT : 9453 ms environ
3000k INSERT : 95530 ms environ


Voici le code utilisé. Une partie est reprise de Amnesty sur le forum anglais
http://www.purebasic.fr/english/viewtopic.php?t=32639

Code : Tout sélectionner

; Création du fichier de test
Procedure CreateTestFile(file.s, line.l)
  If CreateFile(0, file)
    
    i.l
    While i <= line
      req.s = "INSERT INTO test (id, x, y) VALUES (" + Str(i) + ", 'atr', 100)"
      WriteStringN(0, req)
      i + 1
    Wend
    CloseFile(0)
  
  EndIf

EndProcedure

Procedure CreateDatabase(databaseMem.l)

    ; Création de la table principal
    OpenDatabase(databaseMem, ":memory:", "", "", #PB_Database_SQLite)
   
    req.s = "CREATE TABLE test (id Int(9), x varchar(3), y int(3))"
    DatabaseUpdate(databaseMem, req)

EndProcedure 

Procedure RemplirDatabase(databaseMem.l, file.s)
  
  If OpenFile(2, file + ".log.txt")
    
    WriteStringN(2,"[Debut LOG : " + FormatDate("%hh:%ii:%ss", Date()) + "]")
    
    If ReadFile(1, file)
     
      Debug_A = ElapsedMilliseconds()
      
      ; TEST TRANSACTION
      DatabaseUpdate(databaseMem, "BEGIN")
      
      While Eof(1) = 0           
        Debug_C = ElapsedMilliseconds()
        line.s = ReadString(1)     
       
        DatabaseUpdate(databaseMem, line)
        Debug_D = ElapsedMilliseconds()

      Wend
      
      ; TEST TRANSACTION
      DatabaseUpdate(databaseMem, "COMMIT")
      
      Debug_B = ElapsedMilliseconds()
     
      DatabaseQuery(databaseMem, "SELECT COUNT(*) FROM test")
      NextDatabaseRow(databaseMem)

     
      WriteStringN(2, "Temps d'éxécution total : " + Str(Debug_B - Debug_A) + " ms ")
      WriteStringN(2, "Nombre de lignes en mémoire : " + StrU(GetDatabaseLong(databaseMem, 0), #Long))
      CloseFile(1)
     
    Else
      MessageRequester("Erreur lors de l'import", "Impossible de lire le fichier à importer : " + #CRLF$ + file)
    EndIf
 
    WriteStringN(2,"[Fin LOG]")
    CloseFile(2)
  EndIf
 
EndProcedure 

; - Code de Amnesty 
; A voir ici : http://www.purebasic.fr/english/viewtopic.php?t=32639
Structure table
  sql.s
  name.s
EndStructure 

Procedure WriteSQLiteDatabase2Disk(source.l, File.s)
  NewList createStatement.table()

  destinationFile = CreateFile(#PB_Any, File.s)
  If file
    CloseFile(destinationFile)
  Else
      MessageRequester("Error","Can't write DB.",0)
      ProcedureReturn
  EndIf
 
  destinationDB = OpenDatabase(#PB_Any, File, "", "", #PB_Database_SQLite)
  If destinationDB
    
    DatabaseQuery(source, "Select sql, name FROM sqlite_master WHERE type='table'")
   
    While NextDatabaseRow(source)
      AddElement(createStatement())
      createStatement()\sql  = GetDatabaseString(source, 0)
      createStatement()\name = GetDatabaseString(source, 1)
    Wend
    
    DatabaseUpdate(destinationDB, "BEGIN") ; TRANSACTION
    
    ForEach createStatement()  
      
      DatabaseUpdate(destinationDB, createStatement()\sql)
      DatabaseQuery(source, "select * from " + createStatement()\name) 
      columns = DatabaseColumns(source)

      While NextDatabaseRow(source)
        values.s = ""
        For columnNr = 0 To columns - 1
          If DatabaseColumnType(source, columnNr) = #PB_Database_String Or DatabaseColumnType(source, columnNr) = 0
            values+ "'" + GetDatabaseString(source,columnNr) + "'"
          Else
            values+ GetDatabaseString(source,columnNr)
          EndIf
          If columnNr < columns -1
            values+ ","
          EndIf
        Next
        DatabaseUpdate(destinationDB, "insert into " + createStatement()\name + " values(" + values + ")")
      Wend

    Next
    
    DatabaseUpdate(destinationDB, "COMMIT") ; TRANSACTION
    
    CloseDatabase(destinationDB)
  Else
      MessageRequester("Error","Can't open DB.",0)
      ProcedureReturn
  EndIf
EndProcedure 


SetCurrentDirectory("C:\")


;- Librairies
UseSQLiteDatabase() 

; La génération des fichiers de tests n'est pas inclue dans le temps d'éxécution
CreateTestFile("test_1.sql", 30000)
CreateTestFile("test_2.sql", 300000)
CreateTestFile("test_3.sql", 3000000)


; TEST 1 30k
Debug_1_A = ElapsedMilliseconds()

CreateDatabase(1) 
RemplirDatabase(1, "C:\test_1.sql")
WriteSQLiteDatabase2Disk(1, "C:\database_1.db")
CloseDatabase(1)
Debug_1_B = ElapsedMilliseconds()

MessageRequester("Temps total TEST 1", Str(Debug_1_B - Debug_1_A) + " ms ")


; TEST 2 300k
Debug_2_A = ElapsedMilliseconds()

CreateDatabase(2)
RemplirDatabase(2, "C:\test_2.sql")
WriteSQLiteDatabase2Disk(2, "C:\database_2.db")
CloseDatabase(2)
Debug_2_B = ElapsedMilliseconds()

MessageRequester("Temps total TEST 1", Str(Debug_2_B - Debug_2_A) + " ms ")

; TEST 3 3000k
Debug_3_A = ElapsedMilliseconds()

CreateDatabase(3)
RemplirDatabase(3, "C:\test_3.sql")
WriteSQLiteDatabase2Disk(3, "C:\database_3.db")
CloseDatabase(3)
Debug_3_B = ElapsedMilliseconds()

MessageRequester("Temps total TEST 1", Str(Debug_3_B - Debug_3_A) + " ms ")
Répondre