Kleines Verständnisproblem!

Anfängerfragen zum Programmieren mit PureBasic.
Benutzeravatar
PureBasic4.0
Beiträge: 785
Registriert: 29.10.2006 17:26
Wohnort: 127.0.0.1

Kleines Verständnisproblem!

Beitrag von PureBasic4.0 »

Hi, Leute

Ich habe hier den folgenden Code (der mit Sicherheit falsch ist):

Code: Alles auswählen

          SqlString$ = "SELECT ID FROM Shortcuts"
          SQLiteGetTable(DBHandle,SqlString$,Table)
          If Table
            SQLiteNextCol(DBHandle)
            While SQLiteNextRow(DBHandle)
              Ergebnis$ = SQLiteValue(Table)
              AddElement(Verknuepfungszahlen())
              Verknuepfungszahlen() = Val(Ergebnis$)
            Wend
            ResetList(Verknuepfungszahlen())
            ok = 0
            Anzahl = 0
            Repeat
              Anzahl + 1
              ForEach Verknuepfungszahlen()
                If Anzahl <> Verknuepfungszahlen()
                  ok = 1
                EndIf
              Next
            Until ok = 1
          EndIf
Ich möchte alle IDs aus der DB auslesen und eine freie finden. Das mache ich, indem ich alle IDs in eine LinkedList schreibe und versuche, alles mit der einen Zahl (Variable Anzahl) zu vergleichen. Leider ist mir das Codemäßig nicht wirklich gelungen. Habt ihr vielleicht einen besseren Code?

Des Weiteren ist der Code wirklich langsam. Das Auslesen aller IDs dauert bei einer leeren Datenbank ca. 5 Sek. Ich denke, dass kann man Performancemaßig auch noch aufpolieren, oder?

BITTE HELFT MIR!

Danke,

PureBasic4.0
PB 4.50 RC1 + Ubuntu 10.04 LTS + Windows 7 x64
Kaeru Gaman
Beiträge: 17389
Registriert: 10.11.2004 03:22

Beitrag von Kaeru Gaman »

wie groß ist denn der zahlenraum der IDs?
wenn der überschaubar ist (z.b. 0 - 65536) könntest du ein array mit der ID als Index zum "mitschreiben" benutzen.

Code: Alles auswählen

Dim Liste.b(65535)
;...
    SQLiteNextCol(DBHandle)
    While SQLiteNextRow(DBHandle)
      Ergebnis$ = SQLiteValue(Table)
      Verknuepfungszahl = Val(Ergebnis$)
      Liste(Verknuepfungszahl) = 1
    Wend 

  TestCount = 0
  While Liste(TestCount)  And TestCount < 65536
      TestCount +1
  Wend
Zuletzt geändert von Kaeru Gaman am 29.05.2007 10:29, insgesamt 1-mal geändert.
Der Narr denkt er sei ein weiser Mann.
Der Weise weiß, dass er ein Narr ist.
Benutzeravatar
PureBasic4.0
Beiträge: 785
Registriert: 29.10.2006 17:26
Wohnort: 127.0.0.1

Beitrag von PureBasic4.0 »

Hi, Kaeru

Die Anzahl sollte sich schon dynamisch entfalten können. Ich möchte daher auch eher bei LinkedLists bleiben (um einen Buffer Overflow zu vermeiden).

Ich habe zurzeit eher Probleme mit der Überprüfung, ob es eine bestimmte ID bereits gibt. Ich glaube, da sind etliche Fehler drin
PB 4.50 RC1 + Ubuntu 10.04 LTS + Windows 7 x64
Kaeru Gaman
Beiträge: 17389
Registriert: 10.11.2004 03:22

Beitrag von Kaeru Gaman »

> um einen Buffer Overflow zu vermeiden
:? hu?
das versteh ich nicht...

> Die Anzahl sollte sich schon dynamisch entfalten können.
kann sie ja auch.
das Array ist auch nicht dafür da, irgendetwas zu zählen,
nur die vergebenen IDs zu notieren.
der klare vorteil dabei ist:
du gehst die "notizenliste" und gleichzeitig die zahlenschleife nur ein einziges mal durch.
bei einer LL lösung musst du ja die zahlenschleife durchgehen,
und jede einzelne zahl mit allen listenelementen vergleichen.

falls du dir sorgen um deinen speicherbereich machst,
das Array oben braucht nur 64K des hauptspeichers,
und du hast damit für die IDs einen Zahlenraum von 65536.
du kannst also mit einem 1MB großen Array einen zahlenraum von 1048576 verwalten.
das genügt für eine 6-stellige ID 0-999999 ... ;)

man kann das ganze noch verschlanken:
du brauchst ja eigentlich nur ein einziges Bit als flag,
also könntest du in dem byte eines Arrayfeldes ganze 8 flags halten.

Code: Alles auswählen

Dim Liste.b(65535)
;...
    SQLiteNextCol(DBHandle)
    While SQLiteNextRow(DBHandle)
      Ergebnis$ = SQLiteValue(Table)
      Verknuepfungsbyte = Val(Ergebnis$)
      Verknuepfungsbit = Verknuepfungsbyte & 7  ; Modulo 8
      Verknuepfungsbyte / 8
      Liste(Verknuepfungsbyte) | (1 << Verknuepfungsbit) ; Bit setzen
    Wend 

  TestByte = 0
  While Liste(TestByte) = 255 And TestCount < 65536
    TestByte +1
  Wend
  TestBit = 0
  While Liste(TestByte) & (1 << TestBit)
    TestBit +1
  Wend
  FoundID = 8* TestByte + TestBit
hier genügen die 64K jetzt für einen zahlenraum von 524288.

deine lösung wäre mir einfach zu langsam.
außerdem sparst du auch nicht SO viel speicherplatz, weil du 12byte für jedes listenelement benötigst.
d.h., sobald du mehr als 5461 datensätze hast, wird deine liste auch größer als 64K.

...aber ich schau mir deinen logigfehler trotzdem mal an...

[edit] so, hab ich..
so müsste es laufen....

Code: Alles auswählen

TestCount = #LowestPossibleID -1
Repeat
  TestCount + 1
  ok = 1
  ForEach Verknuepfungszahlen()
    If TestCount = Verknuepfungszahlen()
      ok = 0 : Break
    EndIf
  Next
Until ok = 1
Der Narr denkt er sei ein weiser Mann.
Der Weise weiß, dass er ein Narr ist.
Benutzeravatar
PureBasic4.0
Beiträge: 785
Registriert: 29.10.2006 17:26
Wohnort: 127.0.0.1

Beitrag von PureBasic4.0 »

@Kaeru: Danke, habe deinen letzten Code übernommen. Allerdings habe ich folgendes Problem: Die LinkedList wird riesig!!! (3370620), obwohl in der Datenbank überhaupt keine (0) vorhanden sind. Hier ein Screenshot:

Bild

Wie kann man das verbessern?
PB 4.50 RC1 + Ubuntu 10.04 LTS + Windows 7 x64
Benutzeravatar
Kiffi
Beiträge: 10714
Registriert: 08.09.2004 08:21
Wohnort: Amphibios 9

Re: Kleines Verständnisproblem!

Beitrag von Kiffi »

PureBasic4.0 hat geschrieben:

Code: Alles auswählen

If Table 
  SQLiteNextCol(DBHandle)
  While SQLiteNextRow(DBHandle)

Code: Alles auswählen

If Table 
  SQLiteNextCol(Table)
  While SQLiteNextRow(Table)
Grüße ... Kiffi
a²+b²=mc²
Benutzeravatar
Thorsten1867
Beiträge: 1360
Registriert: 04.02.2005 15:40
Computerausstattung: [Windows 10 x64] [PB V5.7x]
Wohnort: Kaufbeuren
Kontaktdaten:

Beitrag von Thorsten1867 »

Zur Beschleunigung solltest du zu Beginn "BEGIN TRANSACTION;"
und zum Schluss "COMMIT;" mit SQLiteExecute() ausführen.
Download of PureBasic - Module
Download of PureBasic - Programmes

[Windows 11 x64] [PB V6]

Bild
Benutzeravatar
PureBasic4.0
Beiträge: 785
Registriert: 29.10.2006 17:26
Wohnort: 127.0.0.1

Beitrag von PureBasic4.0 »

@Kiffi: Danke!

@Thorsten1867: Ich denke, Transactions kann ich später mal einfügen. Es geht jetzt nach dem Bugfix von Kiffi schon ziemlich schnell.


@all: Hier ist der verbesserte Code:

Code: Alles auswählen

          SqlString$ = "SELECT ID FROM Shortcuts"
          SQLiteGetTable(DBHandle,SqlString$,Table)
          If Table
            SQLiteNextCol(Table)
            While SQLiteNextRow(Table)
              Ergebnis$ = SQLiteValue(Table)
              AddElement(Verknuepfungszahlen())
              Verknuepfungszahlen() = Val(Ergebnis$)
            Wend
            ResetList(Verknuepfungszahlen())
            ok = 0
            Anzahl = -1
            Repeat
              Anzahl + 1
              ok = 1
              ForEach Verknuepfungszahlen()
                If Anzahl = Verknuepfungszahlen()
                  ok = 0
                  Break
                EndIf
              Next
            Until ok = 1
            Debug Anzahl
Funktioniert soweit alles. Danke an alle! :mrgreen:
PB 4.50 RC1 + Ubuntu 10.04 LTS + Windows 7 x64
Benutzeravatar
Kiffi
Beiträge: 10714
Registriert: 08.09.2004 08:21
Wohnort: Amphibios 9

Beitrag von Kiffi »

@Thorsten1867:

Transaktionen bringen nur was, wenn man Daten schreibt. ;-)

Grüße ... Kiffi
a²+b²=mc²
Benutzeravatar
Thorsten1867
Beiträge: 1360
Registriert: 04.02.2005 15:40
Computerausstattung: [Windows 10 x64] [PB V5.7x]
Wohnort: Kaufbeuren
Kontaktdaten:

Beitrag von Thorsten1867 »

Kiffi hat geschrieben:@Thorsten1867:

Transaktionen bringen nur was, wenn man Daten schreibt. ;-)

Grüße ... Kiffi
Dann aber eine Menge! :D
Download of PureBasic - Module
Download of PureBasic - Programmes

[Windows 11 x64] [PB V6]

Bild
Antworten