Någon som har ett förslag på hur man kan effektivisera inläsningen av rader från en databas till en FlexGrid? Det tar ca 30 min att fylla FlexGrid'en med 60 000 rader från databasen med nedanstående kod. Har provat med DataMatrix med den stödjer bara Integer vilket innebär att man bara kan läsa in 32000 rader. Jag har tyvärr inget förslag på effektivisering av själva inläsningen men dock ett förslag på helhetslösning. I det system jag jobbar med har vi ofta griddar som presenterar uppslag från stora register. Att fylla girdden med alla poster tar tid, det har vi inte hittat något sätt att komma runt utan vi har löst det på ett annat sätt. Jag vet inte varför, men jag fyller en MSHFlexgrid med 90 000 poster på ca 20 skeunder. Urvalssökning från dessa 90K poster tar mellan 5-10 sekunder. Jag använder an Adodc som datakälla till griden. Källan i sin tur hämtar info genom select från en Access-databas. Min dator är numer ingen värsting heller, processor på 1,3 Ghz och ram på 750 MB. Vid sämre prestanda ökaas laddningstiden något, men inte mer än proportionellt. Jag såg att du i sql satsen har ORDER BY, det är inget sånt som spökar? Du kan testa följande kod. Vilket gör samma sak som din kod. Men betydligt effektivare skulle jag gissa. Jag ska prova denna kod så fort som möjligt! Bowmore > Jag såg att du i sql satsen har ORDER BY, det är inget sånt som spökar? kon2 > Jag vet inte varför, men jag fyller en MSHFlexgrid med 90 000 poster på ca 20 skeunder. En sak du skall testa är att göra FlexGriden Visible = False under inläsning. Enkelt. Han fyller den inte. Han databinder den. Då laddar den bar det synliga posterna. SvenPon > En sak du skall testa är att göra FlexGriden Visible = False under inläsning. Frasse! Här kommer den kod jag använder under Form_Load event för att fylla min MSHFlexgrid. Det tar som jag nämnde tidigare knappt 20 sekunder vid uppstart av programmet. Hela databasen är på ca 60 MB. Programmet skrivet i VB6SP6 Andreas Hillqvist tipsade om att använda en TextMatrix till gridden. Detta fungerar alldeles utmärk!Effektivisering av inläsning till FlexGrid...
/Frasse
'Subrutin för att fylla FlexGrid'en med värden från databasen som innehåller Log-Variabler
Public Sub UpdateGrid()
'Deklarera Temporära varibler för denna subrutin
Dim con As ADODB.Connection
Dim rst As ADODB.Recordset
Dim objGetData As Object
Dim strSQL As String
Dim I As Integer, RowPos As Integer
'Vid fel fortsätt till felhanteringen
On Local Error GoTo ErrHandler
'Skapa nya object för databasen
Set con = New ADODB.Connection
Set rst = New ADODB.Recordset
'Definiera anslutningssträngen mot databasen BroK241_Default som innehåller Log-variabler
con.ConnectionString = "driver={SQL Server};server=" & Main.ThisSystem.ComputerName & ";database=BroK241_Default"
'Rensa Grid bestäm antalet rader till 1 st och kolumner till 5 st
dbGrid.Clear
dbGrid.Rows = 1
dbGrid.Cols = 5
'Centrera texten i raderna
For I = 0 To 3
dbGrid.ColAlignment(I) = flexAlignCenterCenter
Next I
'Gör raden där den fasta texten skall placeras aktuell
dbGrid.Row = 0
'Bestäm den fasta raden i dbGrid
dbGrid.Col = 0: dbGrid.Text = "Date/Time": dbGrid.ColWidth(0) = 2000 'Fast text för Kolumn 0
dbGrid.Col = 1: dbGrid.Text = "Händelse": dbGrid.ColWidth(1) = 2000 'Fast text för Kolumn 1
dbGrid.Col = 2: dbGrid.Text = "Variabel": dbGrid.ColWidth(2) = 3000 'Fast text för Kolumn 2
dbGrid.Col = 3: dbGrid.Text = "Larmnivå": dbGrid.ColWidth(3) = 2000 'Fast text för Kolumn 3
dbGrid.Col = 4: dbGrid.Text = "Kommentar": dbGrid.ColWidth(4) = 6500 'Fast text för Kolumn 4
'Gör startraden aktuell i Grid
RowPos = 1
'Öppna anslutningen mot databasen
con.Open
'Fråga efter innehållet i Databasen och lägg svaret i objGetdata
Set objGetData = con.Execute("SELECT * FROM lgDefault WHERE ALARMLEVEL = 1 ORDER BY TS DESC")
'Så länge objGetData inte tar slut så loopa igenom innehållet
While objGetData.EOF <> True
'Lägg till en rad i Grid
dbGrid.Rows = RowPos + 1
'Aktuell Kolumn 0: Aktuell Rad: Infoga Texten
dbGrid.Col = 0: dbGrid.Row = RowPos: dbGrid.Text = objGetData("TS")
'Aktuell Kolumn 1: Aktuell Rad: Infoga Texten
dbGrid.Col = 1: dbGrid.Row = RowPos: dbGrid.Text = objGetData("EVTTITLE")
'Aktuell Kolumn 2: Aktuell Rad: Infoga Texten
dbGrid.Col = 2: dbGrid.Row = RowPos: dbGrid.Text = objGetData("NAME")
'Aktuell Kolumn 3: Aktuell Rad: Infoga Texten
dbGrid.Col = 3: dbGrid.Row = RowPos: dbGrid.Text = objGetData("ALARMLEVEL")
'Aktuell Kolumn 4: Aktuell Rad: Infoga Texten
dbGrid.Col = 4: dbGrid.Row = RowPos: dbGrid.Text = objGetData("KOMMENTAR")
'Räkna fram nästa rad
RowPos = RowPos + 1
'Flytta fram en post i objGetData
objGetData.MoveNext
Wend
'Stäng anslutningen till Databasen
con.Close
Set con = Nothing
Set rst = Nothing
'Avlsuta sub om inga fel uppstår
Exit Sub
ErrHandler:
Select Case Err.Number
Case 1
MsgBox Err.Description & " Nr: " & Err.Number
Case Else
MsgBox Err.Description & " Nr: " & Err.Number
End Select
End SubSv: Effektivisering av inläsning till FlexGrid...
Vi läser in valda delar av databasen. När användaren sedan blädrar så sker automatisk påfyllnad när så behövs. Görs sökningar sker detta i databasen och inte gridden och resultatet hämtas från databasen. Det krävs en del kodande för att få till denna logik. Dock är det troligen det enda sättet att komma runt problemet, att läsa in 60 000 poster tar tid.
T ex de databasbundna griddar som vi jobbar med (INTE de som är med i exemplet ovan) använder samma teknik som vi själva har gjort. Dom läser in data eftersom den efterfrågas. Det sker inga batch inläsningar på grund av prestandan.Sv: Effektivisering av inläsning till FlexGrid...
Sv: Effektivisering av inläsning till FlexGrid...
Sv: Effektivisering av inläsning till FlexGrid...
<code>
Public Sub UpdateGrid()
'Deklarera varibler för denna subrutin
Dim con As ADODB.Connection
Dim rst As ADODB.Recordset
Dim fldTS As ADODB.Field
Dim fldEVTTITLE As ADODB.Field
Dim fldNAME As ADODB.Field
Dim fldALARMLEVEL As ADODB.Field
Dim fldKOMMENTAR As ADODB.Field
Dim strSQL As String
Dim I As Long
'Vid fel fortsätt till felhanteringen
On Local Error GoTo ErrHandler
'Rensa Grid bestäm antalet rader till 1 st och kolumner till 5 st
dbGrid.Clear
dbGrid.Rows = 1
dbGrid.Cols = 5
'Centrera texten i raderna
For I = 0 To 3
dbGrid.ColAlignment(I) = flexAlignCenterCenter
Next
'Gör raden där den fasta texten skall placeras aktuell
dbGrid.Row = 0
'Bestäm den fasta raden i dbGrid
dbGrid.Col = 0
dbGrid.Text = "Date/Time"
dbGrid.ColWidth(0) = 2000 'Fast text för Kolumn 0
dbGrid.Col = 1
dbGrid.Text = "Händelse"
dbGrid.ColWidth(1) = 2000 'Fast text för Kolumn 1
dbGrid.Col = 2
dbGrid.Text = "Variabel"
dbGrid.ColWidth(2) = 3000 'Fast text för Kolumn 2
dbGrid.Col = 3
dbGrid.Text = "Larmnivå"
dbGrid.ColWidth(3) = 2000 'Fast text för Kolumn 3
dbGrid.Col = 4
dbGrid.Text = "Kommentar"
dbGrid.ColWidth(4) = 6500 'Fast text för Kolumn 4
'Gör startraden aktuell i Grid
RowPos = 1
'Skapa nya object för databasen
Set con = New ADODB.Connection
'Definiera anslutningssträngen mot databasen BroK241_Default som innehåller Log-variabler
con.ConnectionString = "driver={SQL Server};" & _
"server=" & Main.ThisSystem.ComputerName & ";" & _
"database=BroK241_Default"
'Öppna anslutningen mot databasen
con.Open
'Skapa instans av recordset
Set rst = New ADODB.Recordset
'För att göra det möjligt att ta reda på antalet poster
rst.CursorLocation = adUseClient
'Stäler fråga mot Databasen
strSQL = "SELECT *" & vbCrLf & _
"FROM lgDefault" & vbCrLf & _
"WHERE ALARMLEVEL = 1" & vbCrLf & _
"ORDER BY TS DESC"
rst.Open , con, db
'Tilldelar fältvariabler
Set fldTS = rst("TS")
Set fldEVTTITLE = rst("EVTTITLE")
Set fldNAME = rst("NAME")
Set fldALARMLEVEL = rst("ALARMLEVEL")
Set fldKOMMENTAR = rst("KOMMENTAR")
'Lägger till raderna
dbGrid.Rows = 1 + rst.RecordCount
'Går igenom alla postrer
For I = 1 to rst.RecordCount
'Aktuell Kolumn 0: Aktuell Rad: Infoga Texten
dbGrid.TextMatrix(0, I) = fldTS.Value
'Aktuell Kolumn 1: Aktuell Rad: Infoga Texten
dbGrid.TextMatrix(1, I) = fldEVTTITLE.Value
'Aktuell Kolumn 2: Aktuell Rad: Infoga Texten
dbGrid.TextMatrix(1, I) = fldNAME.Value
'Aktuell Kolumn 3: Aktuell Rad: Infoga Texten
dbGrid.TextMatrix(1, I) = fldALARMLEVEL.Value
'Aktuell Kolumn 4: Aktuell Rad: Infoga Texten
dbGrid.TextMatrix(1, I) = fldKOMMENTAR.Value
'Flytta fram en post
rst.MoveNext
Next
'Frigör fältvariabler
Set fldTS = Nothing
Set fldEVTTITLE = Nothing
Set fldNAME = Nothing
Set fldALARMLEVEL = Nothing
Set fldKOMMENTAR = Nothing
'Stäng recordset
rst.Close
'Frigör referens till Recordset
Set rst = Nothing
'Stäng anslutningen till Databasen
con.Close
'Frigör referens till Connection
Set con = Nothing
'Avlsuta sub om inga fel uppstår
Exit Sub
ErrHandler:
Select Case Err.Number
Case 1
MsgBox Err.Description & " Nr: " & Err.Number
Case Else
MsgBox Err.Description & " Nr: " & Err.Number
End Select
End Sub
</code>
Annars Kan du göra så att du skapar bara så många rader i din grid som syns och lägger till en egen scroolbar. Detta är mycket effektivare.
Som tidigare nämts är det så det flesta databundna grid fungerar. För att det är snabbt och mycket effektivt.Sv: Effektivisering av inläsning till FlexGrid...
Men en sak som jag tänkte på. Stödjer TextMatrix datatypen Long?
Har ett vagt minne att TextMatrix endast stöder Integer för row och column...
/FrasseSv: Effektivisering av inläsning till FlexGrid...
Jag tror inte det. Jag kör samma sql-sats i en annan subrutin och den fungerar mycket snabbare.
/FrasseSv: Effektivisering av inläsning till FlexGrid...
Du har inget exempel på din kod som du kan dela med dig av?
/FrasseSv: Effektivisering av inläsning till FlexGrid...
Sv: Effektivisering av inläsning till FlexGrid...
Sv: Effektivisering av inläsning till FlexGrid...
Oki, det ska jag prova. Tack för tipset.Sv: Effektivisering av inläsning till FlexGrid...
' Här öppnas connection till databasen
strAp = App.Path
strCR = (Chr(13) & Chr(10))
Set cn = New ADODB.Connection
If Right$(strAp, 1) = "\" Then
cn.Open "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" & strAp & "MyDatabas.mdb;Persist Security Info=False"
Else
cn.Open "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" & strAp & "\MyDatabas.mdb;Persist Security Info=False"
End If
' Här fylls Adodc1 och Adodc2
With Adodc1
If Right$(strAp, 1) = "\" Then
.ConnectionString = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" & strAp & "MyDatabas.mdb;Persist Security Info=False"
.CommandType = adCmdText
.RecordSource = "SELECT * FROM Tabell ORDER BY Dag"
Else
.ConnectionString = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" & strAp & "\MyDatabas.mdb;Persist Security Info=False"
.CommandType = adCmdText
.RecordSource = "SELECT * FROM Tabell ORDER BY Dag"
End If
End With
Adodc1.Refresh
With Adodc2
If Right$(strAp, 1) = "\" Then
.ConnectionString = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" & strAp & "MyDatabas.mdb;Persist Security Info=False"
Else
.ConnectionString = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" & strAp & "\MyDatabas.mdb;Persist Security Info=False"
End If
End With
' Här anpassas MSHFlexgrid1 och MSHFlexgrid2
MSHFlexGrid1.ColWidth(0) = 0
MSHFlexGrid1.ColWidth(1) = 4000
MSHFlexGrid1.ColWidth(2) = 3000
MSHFlexGrid1.ColWidth(3) = 0
MSHFlexGrid1.ColWidth(4) = 0
MSHFlexGrid1.ColWidth(5) = 0
MSHFlexGrid1.ColWidth(6) = 0
MSHFlexGrid1.ColWidth(7) = 0
MSHFlexGrid1.ColWidth(8) = 0
MSHFlexGrid1.ColWidth(9) = 0
MSHFlexGrid1.ColWidth(10) = 0
MSHFlexGrid1.ColWidth(11) = 0
MSHFlexGrid1.ColWidth(12) = 0
MSHFlexGrid1.ColWidth(13) = 1000
MSHFlexGrid1.ColWidth(14) = 500
MSHFlexGrid1.ColWidth(15) = 500
MSHFlexGrid1.ColWidth(16) = 1500
MSHFlexGrid1.ColWidth(17) = 0
MSHFlexGrid1.ColWidth(18) = 0
MSHFlexGrid2.ColWidth(0) = 0
MSHFlexGrid2.ColWidth(1) = 3500
MSHFlexGrid2.ColWidth(2) = 2500
MSHFlexGrid2.ColWidth(3) = 0
MSHFlexGrid2.ColWidth(4) = 0
MSHFlexGrid2.ColWidth(5) = 0
MSHFlexGrid2.ColWidth(6) = 0
MSHFlexGrid2.ColWidth(7) = 0
MSHFlexGrid2.ColWidth(8) = 0
MSHFlexGrid2.ColWidth(9) = 0
MSHFlexGrid2.ColWidth(10) = 0
MSHFlexGrid2.ColWidth(11) = 0
MSHFlexGrid2.ColWidth(12) = 0
MSHFlexGrid2.ColWidth(13) = 0
MSHFlexGrid2.ColWidth(14) = 0
MSHFlexGrid2.ColWidth(15) = 0
MSHFlexGrid2.ColWidth(16) = 0
MSHFlexGrid2.ColWidth(17) = 0
MSHFlexGrid2.ColWidth(18) = 0
HDHSv: Effektivisering av inläsning till FlexGrid...
Det tar 12 sekunder att läsa in 105315 rader numera! Tack Andreas!