Per creare un indice in SQLite puoi leggere qui:
https://sqlite.org/lang_createindex.html
https://www.w3schools.com/sql/sql_create_index.asp
Gli indici vanno impostati su tabelle già create (e riempite).
Normalmente la/le colonne sono NOT NULL UNIQUE e quindi si usa la formula:
CREATE UNIQUE INDEX "nome-indice" ON nome-tabella (nome-colonna ASC o DESC);
Se i dati non sono univoci basta togliere UNIQUE.
Però visto che scrivi ...(complessivamente il DB è formato da circa 106000 record). Per la precisione, dalla schedulazione dell'evento, alla emissione della finestra contenenti i dati richiesti, passano circa 24". Mi sembrano veramente tanti. Rispetto a circa 2 anni fa il tempo d'attesa è più che raddoppiato...
credo che i dati siano veramente troppo pochi per causare un tale rallentamento e già due anni fa i tempi erano biblici.
A meno che tu non sia su un computer veramente lento in generale, non escluderei che le cause della lentezza siano dovute ad altri motivi, infatti poco più di 100.000 record sono una bazzecola anche per SQLite che può sopportare e trattare milioni di records.
Su questo attendo il parere degli esperti di DB.
Comunque se creando l'indice non cambia nulla..
Ti allego un piccolo progetto che filtra i record sulla colonna Data (usdat) non indicizzata, a me lo fa in pochi attimi.
Così puoi verificare su una base concreta.
Grazie Gianluigi. Sei sempre disponibile e ti sono grato.
La mia lettura scansionata della tabella movimgg (quella incriminata, contenente oltre 54000 record) è fatta attraverso il seguente codice
i_dataStamp = Int(Val($_DataStamp))
ApriDB = New OpenDB
$_TbParFrm.Add("0")
i_RgGriStamp = (-1)
RecMovgg = ApriDB.DBConnection.EXEC("SELECT * FROM movimgg WHERE DtCoMovgg = '" & i_dataStamp & "' ORDER BY NuProMovvgg")
For Each RecMovgg
$_LirEuro = RecMovgg!MonMovvggPuò darsi che esista DtCoMovgg
i_RgGriStamp += 1
GridStamp[i_RgGriStamp, 1].text = RecMovgg!DescrMovvgg
fImpMov = RecMovgg!ImpMovvgg
If fImpMov > 0 Then
i_CaselGriStamp = 3
Else
fImpMov *= (-1)
i_CaselGriStamp = 4
Endif
Riporto anche il codice relativo alla Open del DB
'------------------------------- OpenDB.Class ------------------------------------------------------------------------------------------
Public bSwOpErr As Boolean
Public DBConnection As New Connection 'inizializza la nuova connessione
'**************************--- la prossima riga vale per tutti ---***********************
Public $DbPath As String = user.home & "/mont/dativari/contabfam" 'Percorso di ricerca del Database ContabFam.db"
Public $IconPath As String = user.home & "/mont/dativari/contabfam/IconVar" 'Persocorso di ricerca delle picture utilizzate nel programma
'***********************************************************************************************
Public $DbNome As String = "ContabFamdb" 'Nome del Database
Public Sub _new()
'----------------------------------------
With
DBConnection
.Close
.Type = "sqlite3"
.Host = $DbPath
.Name = $DbNome
.OPEN 'Apro il DB
End With'------------------------------- OpenDB.Class ------------------------------------------------------------------------------------------
Public bSwOpErr As Boolean
Public DBConnection As New Connection 'inizializza la nuova connessione
'**************************--- la prossima riga vale per tutti ---**************************
'Public $_DbPath As String = user.home & "/contabfam" 'Percorso di ricerca del Database ContabFam.db"
Public $DbPath As String = user.home & "/mont/dativari/contabfam" 'Percorso di ricerca del Database ContabFam.db"
Public $IconPath As String = user.home & "/mont/dativari/contabfam/IconVar" 'Persocorso di ricerca delle picture utilizzate nel programma
'***********************************************************************************************
Public $DbNome As String = "ContabFamdb" 'Nome del Database
Public Sub _new()
'----------------------------------------
With
DBConnection
.Close
.Type = "sqlite3"
.Host = $DbPath
.Name = $DbNome
.OPEN 'Apro il DB
End With
bSwOpErr = False 'OPEN eseguita correttamente
Catch
bSwOpErr = True 'Errore nella Open
End
bSwOpErr = False 'OPEN eseguita correttamente
Catch
bSwOpErr = True 'Errore nella Open
End
Come puoi vedere l'istruzione di lettura della tabella, oggetto della mia sofferenza è quella di selezione dei record interessanti alla mia ricerca e del successivo caricamento in una GidView, attraverso l'istruzione for each:
RecMovgg = ApriDB.DBConnection.EXEC("SELECT * FROM movimgg WHERE DtCoMovgg = '" & i_dataStamp & "' ORDER BY NuProMovvgg")
For Each RecMovgg
L'istruzione SQL "EXEC" procede alla scansione dei record di tabella riportanti la stessa data contabile (DtCoMovgg), disponendoli altresìi in ordine di numero prograssivo di operazione.
Io ho visto che tu non hai adoperato istruzioni SQL. Che sia proprio l'istruzione SQL a provocare rallentamenti così esasperanti?
Non sono in grado di valutarlo. Ricordo che allora ho faticato non poco per mettere a punto l'orologio gestionale del mio DB attraverso i DB.EXEC.
Esiste un metodo più semplice? Non lo so. A me è venuto allora facile e comprensibile costruirlo così.
Comunque se si fa questa semplice prova:
Public Sub Form_Open()
With GridView1
.Header = 3
.Columns.Count = 4
.Columns[0].Width = 60
.Columns[0].Text = "ID"
.Columns[1].Width = 120
.Columns[1].Text = "Nome"
.Columns[2].Width = 120
.Columns[2].Text = "Cognome"
.Columns[3].Text = "DATA"
End With
End
Public Sub btnPopola_Click()
Dim i As Integer
Dim StartTime, DiffTime As Float
StartTime = Timer
For i = 0 To 179946
GridView1.Rows.Count = i + 1
GridView1[i, 0].Text = i + 1
GridView1[i, 1].Text = "Daphne"
GridView1[i, 2].Text = "Verdone"
GridView1[i, 3].Text = "01/04/2018"
Next
DiffTime = Round(Timer - StartTime, -2)
Message.Info(i & " record filtrati su 200.001 In " & DiffTime)
End
Si può constatare che ci mette più tempo del programma, la vedo dura ridurre i tempi...
:ot: Vedo che non hai il modulo canberra come hai installato?
Da repository PPA http://ppa.launchpad.net/gambas-team/gambas3/ubuntu bionic
Per installare in Ubuntu il modulo occorre dare questo comando:
sudo apt-get install libcanberra-gtk-module
Però non sono sicuro che possa servire installarlo a posteriori, provare non costa nulla.
Eccolo, mi scuso se non vi posto un programma di esempio ma solo il codice, ma purtroppo non ho avuto tempo,
se qualcuno ha la bontà di provarlo mi faccia sapere se ci sono errori, con MySql funziona benissimo non sò se è
adattabile anche a SqLite. :ciao:
Private $iMaxRows As Integer = 15 ' Nr. max righe per pagina
Private $iCurrentPage As Integer ' Pagina corrente
Private $iMaxPage As Integer ' Nr. max pagine
Public Sub Form_Open()
Me.Center()
Crea_Griglia() ' Avvia Sub creazione griglia
End
Private Sub Crea_Griglia() ' Creazione GridView dati
With grdDati
.Rows.Count = 0
.Columns.Count = 4
.Columns[0].Text = "Dato 1"
.Columns[1].Text = "Dato 2"
.Columns[2].Text = "Dato 3"
.Columns[3].Text = "Dato 4"
End With
End
Private Sub Conta_Record() ' Conteggio record
Dim rs As Result
Dim iTmp As Integer
rs = MGlobal.db.Exec("SELECT COUNT(campo1) FROM tabella") ' Query conteggio dati
iTmp = rs.Count Div $iMaxRows ' Suddivisione record per numero max righe (15) impostate per visualizzazione pagine in grdDati
If rs.Count Mod $iMaxRows > 0 Then ' Numerazione pagine
$iMaxPage = iTmp + 1
Else
$iMaxPage = iTmp
Endif
GeneratePaging(0) ' Avvia Sub selezione dati e generazione pagine
$iCurrentPage = 1
NrPagine($iCurrentPage) ' Avvia Sub visualizzazione Nr. pagine
End
Private Sub GeneratePaging(iPage As Integer) ' Selezione dati e generazione pagine
Dim sSql As String
Dim iStartOffset As Integer
If iPage <= 0 Then ' Impostazione numerazione pagine = 1 se pagine <= 0
iPage = 1
Endif
iStartOffset = (iPage - 1) * $iMaxRows ' Calcolo numero max pagine
sSql = "SELECT campo1"
sSql &= " FROM tabella"
sSql &= " ORDER BY campo1"
sSql &= " LIMIT "
sSql = sSql & iStartOffset & "," & $iMaxRows
grdDati.Clear()
Crea_Griglia() ' Avvia Sub creazione griglia
Vis_Dati(grdDati, sSql) ' Avvia Sub visualizzazione dati
End
Private Sub Vis_Dati(grd As GridView, sQuery As String) ' Visualizzazione dati
Dim i As Integer
Dim rs As Result
rs = MGlobal.db.Exec(sQuery)
With rs
grd.Rows.Count = 0
If .Count <> 0 Then
grd.Columns.Count = .Fields.Count
grd.Rows.Count = .Count
i = 0
While i < .Count
grd[i, 0].Text = rs!campo1
grd[i, 1].Text = rs!campo2
grd[i, 2].Text = rs!campo3
grd[i, 3].Text = rs!campo4
i = i + 1
.MoveNext
Wend
MGlobal.db.Close()
Else
MGlobal.db.Close()
Endif
End With
End
Public Sub tbnPgAvanti_Click() ' Pagina Avanti
$iCurrentPage = $iCurrentPage + 1
If $iCurrentPage >= $iMaxPage Then
$iCurrentPage = $iMaxPage
Endif
MGlobal.db.Open()
GeneratePaging($iCurrentPage) ' Avvia Sub generazione pagine
NrPagine($iCurrentPage) ' Avvia Sub Nr. Pagine
End
Public Sub tbnPgIndietro_Click() ' Pagina Indietro
$iCurrentPage = $iCurrentPage - 1
If $iCurrentPage <= 1 Then
$iCurrentPage = 1
Endif
MGlobal.db.Open()
GeneratePaging($iCurrentPage) ' Avvia Sub conteggio record
NrPagine($iCurrentPage) ' Avvia Sub visualizzazione Nr. pagine
End
Public Sub NrPagine(iPag As Integer) ' Numerazione pagine
txlNrPagine.Text = iPag & "<FONT color=black> di </FONT>" & $iMaxPage
End
Riprendo la discussione dal punto in cui l'avevo lasciata, relativamente all'esagerato impegno di tempo per la compilazione di alcuni movimenti del mio DB su una gridview.
Scusate la precisazione, ma il sopravvenuto difetto del cursore sulla barra di scorrimento verticale, ci ha portato un pò fuori dal tema della corrente discussione.
Prima di apportare una qualsiasi modifica al segmento di codice che estrae ed espone record dal DB, ho voluto rendermi meglio conto sui momenti in cui si verificano le lungaggini elaborative.
Devo anche dire che 'l'estrazione dei dati occorrenti non avviene in un solo momento, così come la compilazione della gridview. Piuttosto che descriverlo a parole, preferisco riportare qui sotto le righe di Debug con l'esposizione dell'orario rilevato di volta in volta con l'istruzione
Debug "---" & Time(Now) & " ---"
FormPrint01._new.111:
FormPrint01._new.112: -------------------------------------- Estrazione movimenti da DbContabFam ------------------------------
FormPrint01._new.113: --- inizio ore 16:53:33.288 ---
FormPrint01._new.177: --- fine ore 16:53:33.308 ---
FormPrint01._new.179: ----------------------------------------------------------------------------------------------------------------
FormPrint01._new.180:
FormPrint01._new.181: -------------------------------------- Formattazione Righe: totali, Riporto, a riptare ---------------------------
---
FormPrint01._new.244: --- fine ore 16:53:33.309 ---
FormPrint01._new.246: ----------------------------------------------------------------------------------------------------------------
FormPrint01._new.248:
FormPrint01._new.249: -------------------------------------- Compilazione Righe: Resta di Cassa ------------------------------
FormPrint01._new.324: --- fine ore 16:53:33.311 ---
FormPrint01._new.326: ----------------------------------------------------------------------------------------------------------------
FormPrint01._new.327:
FormPrint01._new.328: -------------------------------------- Estrazione Movimenti di Pretito Momentaneo ------------------------------
FormPrint01._new.331: --- fine ore 16:53:56.795 ---
FormPrint01._new.333: ----------------------------------------------------------------------------------------------------------------
FormPrint01._new.334:
FormPrint01._new.335: -------------------------------------- Compilazione Righe di Pretito Momentaneo ------------------------------
FormPrint01._new.380: --- fine ore 16:53:56.796 ---
Si vede chiaramente che dal momento in cui comincia l'estrazione, l'unico tratto di programma "stonato" è quello relativo all'estrazione dei movimenti di Prestito Momentaneo che comincia a h. 16:53:33.311 e finisce a h.16:53:56.795 con una durata di 23.484 secondi che risponde quasi in toto alla mia attesa dal momento in cui clicco il pulsante virtuale |Stampa|.
Quindi tutto il ragionamento fatto vari post fa su una diversa modalità di caricamento della gridview cade. Devo invece analizzare più approfonditamente il gruppo di istruzioni pertinenti l'estrazione di quei particolari record facenti capo ad concetto di "Movimenti per prestiti momentanei".
No intendevo dire, ammesso e non concesso che tu l'estrazione dei dati la faccia con una query, se fai girare la query direttamente in DB Browser for SQLite, quanto tempo impiega?
Ora ho capito.
Purtroppo non posso darti una risposta immediata perchè dovrei costruire la query in DB Browser, uguale alla mia nuova query:
sql = "SELECT * FROM prestmom,movimgg,piancont WHERE "
sql &= "prestmom.DtCoPriPrestMom >= '20111201' " 'Istruzione valida fino alla completa eliminazione dei sospesi antichi
sql &= "AND prestmom.DtCoUltPrestMom <= $DataStamp " 'in modo da considerare anche i movimenti estinti in data successiva a quella corrente
sql &= "AND prestmom.DtSolPrestMom = movimgg.DtSolMovgg "
sql &= "AND prestmom.OraSolPrestMom = movimgg.OraSolMovgg "
sql &= " ORDER BY prestmom.StaPrestMom, prestmom.DtCoPriPrestMom, movimgg.DtCoMovgg"
ApriDB = New OpenDB
RecStampMov = ApriDB.DBConnection.EXEC(sql)
For Each RecStampMov
iConta += 1
Next
Per ora non fa altro. Mi è servita solo per capire quanto tempo impiega ad estrarre i record pertinenti ai vincoli di estrazione.
FormPrint01._new.114: -------------------------------------- Estrazione movimenti da DbContabFam ------------------------------
FormPrint01._new.115: --- inizio ore 19:31:38.987 ---
FormPrint01._new.179: --- fine ore 19:31:39.028 ---
FormPrint01._new.181: ----------------------------------------------------------------------------------------------------------------
FormPrint01._new.182:
FormPrint01._new.183: -------------------------------------- Formattazione Righe: totali, Riporto, a riptare ---------------------------
---
FormPrint01._new.246: --- fine ore 19:31:39.03 ---
FormPrint01._new.248: ----------------------------------------------------------------------------------------------------------------
FormPrint01._new.250:
FormPrint01._new.251: -------------------------------------- Compilazione Righe: Resta di Cassa ------------------------------
FormPrint01._new.326: --- fine ore 19:31:39.032 ---
FormPrint01._new.328: ----------------------------------------------------------------------------------------------------------------
FormPrint01._new.329:
FormPrint01._new.330: -------------------------------------- Estrazione Movimenti ATTIVI di Pretito Momentaneo --------------------------
FormPrint01._new.343: --- fine ore 19:31:39.034 ---
La query che provocava inspiegabili lungaggini di tempo non esiste più ed i nuovi tempi di esecuzione sono assolutamente da primato.
Naturalmente, occorre aggiungere le istruzioni di compilazione righe nella gridview corrente, ma sono abbastanza fiducioso.
Infatti, mentre prima gestivo un numero imprecisato di query a seconda dei movimenti incontrati con la prima di quest'ultima estrazione, ora i dati occorrenti sono tutti già pronti per essere elaborati e caricati nella gridview.
Vi farò sapere,... magari non stasera o domani.
Purtroppo non posso darti una risposta immediata perchè dovrei costruire la query in DB Browser, uguale alla mia nuova query
Ma il database ce l'hai ti basta aprirlo con DB Browser for SQLite e interrogarlo dalla scheda Execute SQL :-\
Ti stavo scrivendo questo, ma vedo che tornu mi ha preceduto, lo posto ugualmente anche se rischio di ripetere quello che dice lui:
SELECT * /* Sei proprio sicuro che ti servano tutte le colonne? */
FROM prestmom,movimgg,piancont /* e piancont, perché selezioni tutta la tabella e non la usi? Sono un po tanto arrugginito con le query ma qui non manca qualcosa del tipo
FROM prestmom
INNER JOIN movimgg */
WHERE prestmom.DtCoPriPrestMom >= 20111201 /* <--- senza apostrofi (non sono integer?) */
AND prestmom.DtCoUltPrestMom <= $DataStamp /* <--- insisto non sono integer le tue date? */
AND prestmom.DtSolPrestMom = movimgg.DtSolMovgg
AND prestmom.OraSolPrestMom = movimgg.OraSolMovgg
ORDER BY prestmom.StaPrestMom, prestmom.DtCoPriPrestMom, movimgg.DtCoMovgg
@Tornu,
ho scaricato il file ora non ho tempo, domani pomeriggio lo guardo :ciao:
nella query, usi SELECT * che in parole povere
significa dammi tutti i campi delle tabelle richiamate in base alle condizioni impostate con gli AND, ma ti servono
tutti per visualizzare i dati che stai filtrando?
Domanda corretta. Hai fatto bene a ricordarmelo. Devo dire che non ci ho riflettuto molto sopra, infatti ho copiato e modificato una query precedente ed ho dimenticato di sostituire allo "*" l'elenco delle colonne che mi interessano.
In effetti la query andrebbe fatta così:
sql = "SELECT prestmom.DtCoPriPrestMom AS DtCoIniPreMom, prestmom.DtCoUltPrestMom AS DtCoUltimaPreMom, prestmom.DtSolPrestMom As DtSolPreMom,"
sql &= "prestmom.OraSolPrestMom AS OreSolPreMom, prestmom.CoVoPrestMom AS CoVocePreMom,prestmom.StaPrestMom AS StatusPreMm"
sql &= "movimgg.DtCoMovgg AS DtContMovvGG, movimgg.DtSolMovgg AS DtSoleMovvGG, movimgg.OraSolMovgg AS OraSoleMovvGG, "
sql &= "movimgg.ImpMovvgg AS ImpMovim. movimgg.MonMovvgg AS LirEurMovim, "
sql &= "piancont.NumVoce AS CoVoPiaConti, piancont.NomeVoce AS VocePiaConti"
sql &= "From prestmom, movimgg, piancont WHERE " ""
sql &= "DtCoIniPreMom >= '20111201' " 'Istruzione valida fino alla completa eliminazione dei sospesi antichi
sql &= "AND DtCoUltimaPreMom <= $DataStamp " 'in modo da considerare anche i movimenti estinti in data successiva a quella corrente
sql &= "AND DtSolPreMom = DtSoleMovvGG "
sql &= "AND OreSolPreMom = OraSoleMovvGG "
sql &= " ORDER BY StatusPreMm, CoVocePreMom, DtCoIniPreMom, DtContMovvGG"
ApriDB = New OpenDB
RecStampMov = ApriDB.DBConnection.EXEC(sql)
Credo infatti, se non, ricordo male, che vadano indicati prima di "FROM" tutte le colonne necessarie, non solo per il contenuto da estrarre, ma anche perchè sono citate nello "ORDER BY".
[quote author=Gianluigi link=topic=6644.msg44646#msg44646 date=1542404192]
Ma il database ce l'hai ti basta aprirlo con DB Browser for SQLite e interrogarlo dalla scheda Execute SQL :-\
Si, l'ho visto e l'ho anche eseguito, ma penso di avere sbagliato qualcosa, perchè, mentre la stessa query nel programma impiega pochissimi ms ed estra 343 record, quella eseguita in DB Browser ha impiegato poco più di 22 secondi ed estrae nientemeno che 103000 record. Quindi c'è qualcosa che non funziona. Non so ancora dove.
A proposito, sai se è possibile indirizzare, in DB Browser,il risultato della query in un file.text?