WinFuture-Forum.de: Smalltalk - WinFuture-Forum.de

Zum Inhalt wechseln

Beiträge in diesem Forum erhöhen euren Beitragszähler nicht.
  • 11892 Seiten +
  • « Erste
  • 11803
  • 11804
  • 11805
  • 11806
  • 11807
  • Letzte »

Smalltalk Guten Morgen, Guten Tag, Guten Abend Kaffeeklatsch

#177061 Mitglied ist offline   Holger_N 

  • Gruppe: aktive Mitglieder
  • Beiträge: 5.009
  • Beigetreten: 11. September 10
  • Reputation: 459
  • Geschlecht:Männlich

geschrieben 06. Juli 2017 - 20:36

YYYYYEEEEEEEAAAAAAHHHHHHH - jetzt habe ich das Problem gelöst, also nicht selbst aber ich habe die Lösung im Netz gefunden, wie man die benötigten DLLs rauskriegt.

Einfach den Ordner mit der Qt-Installation umbenennen, damit das System »denkt«, die gibt es nicht. (und sich die DLLs nicht aus der Qt-Umgebung holt)
dann einen Ordner anlegen,
die Anwendung rein,
ALLE in Frage kommenden DLLs rein,
ALLE Unterordner aus dem Plugins-Ordner rein,

die Anwendung starten und bei laufender Anwendung alle DLLs und Ordner löschen, wobei alle die sich nicht löschen lassen zu überspringen sind.

Alles was benötigt wird bleibt übrig - fertig.
Bauernregel: Regnets mächtig im April, passiert irgendwas, was sich auf April reimt.

Anzeige



#177062 Mitglied ist offline   RalphS 

  • Gruppe: aktive Mitglieder
  • Beiträge: 8.810
  • Beigetreten: 20. Juli 07
  • Reputation: 1.126
  • Geschlecht:Männlich
  • Wohnort:Zuhause
  • Interessen:Ja

geschrieben 06. Juli 2017 - 20:42

Eigentlich auch nur, wenn nicht eine DLL zur Laufzeit nachgeladen wird :unsure:

Sollte erstmal funktionieren, könnte aber ggf trotzdem noch irgendwo hängen. Besonders, wenn Du erst irgendwo im Programm selber irgendwelche DLLs nachladen läßt oder ggf auf dynamisch bereitgestellte Funktionalität zugreifen solltest.

Halt also ggf noch ein Auge drauf. Oder sag den Benutzern, daß sie das an Dich zurückmelden sollen, fals irgendwas nicht hinhaut.
"If you give a man a fish he is hungry again in an hour. If you teach him to catch a fish you do him a good turn."-- Anne Isabella Thackeray Ritchie

Eingefügtes Bild
Eingefügtes Bild

#177063 Mitglied ist offline   Holger_N 

  • Gruppe: aktive Mitglieder
  • Beiträge: 5.009
  • Beigetreten: 11. September 10
  • Reputation: 459
  • Geschlecht:Männlich

geschrieben 06. Juli 2017 - 21:03

Ja wenn man dann alles Unnötige gelöscht hat, macht es natürlich Sinn, das Programm nochmal durchzuspielen. Es erspart aber schonmal eine Menge Arbeit, als wenn man von Anfang an aufs Blaue probieren würde und hat schonmal eine Auswahl an DLLs, die man auf jeden Fall braucht oder wenn man eine Version schonmal hat, kriegt man die Zweite schneller raus. Also man hat beispielsweise eine MinGW-Version die funktioniert und sucht jetzt, was man für die MSVC austauschen muß.

Ansonsten habe ich zum Testen ja meine beiden blanken Systeme, seit ich das mit der VM endlich hingekriegt habe. Da prüfe ich auch immer nochmal gegen.

Dieser Beitrag wurde von Holger_N bearbeitet: 06. Juli 2017 - 21:04

Bauernregel: Regnets mächtig im April, passiert irgendwas, was sich auf April reimt.

#177064 Mitglied ist offline   Holger_N 

  • Gruppe: aktive Mitglieder
  • Beiträge: 5.009
  • Beigetreten: 11. September 10
  • Reputation: 459
  • Geschlecht:Männlich

geschrieben 07. Juli 2017 - 08:39

Was macht eigentlich bei einer Datenbankabfrage mehr Sinn wenn man zwei Bedingungen hat? Also beispielsweise hat man einen Obstkorb mit Äpfel und Birnen und jeweils in mehreren unterschiedlichen Farben.

Nun sucht man hellgrüne Äpfel. Macht es mehr Sinn zuerst nach Äpfeln zu suchen und dann nach der Farbe, also:

SELECT * FROM obstkorb WHERE obst=apfel AND farbe=hellgruen ;

weil es nur zwei Obstsorten gibt und man dann grob vorselektiert und in der kleineren Menge der Äpfel nach Farben sucht oder macht es mehr Sinn erst nach der Farbe zu suchen und dann nach dem Obst, also


SELECT * FROM obstkorb WHERE farbe=hellgruen AND obst=apfel ;

weil man dann bei der zweiten Bedingung nur noch einen ganz kleinen Pool hat oder ist die Reihenfolge für die Abfrage egal?




In dem Beispiel ist es vielleicht nicht ganz so relevant, aber mal angenommen es gäbe ganz wenige Obstsorten und ganz viele Farben.
Bauernregel: Regnets mächtig im April, passiert irgendwas, was sich auf April reimt.

#177065 Mitglied ist offline   RalphS 

  • Gruppe: aktive Mitglieder
  • Beiträge: 8.810
  • Beigetreten: 20. Juli 07
  • Reputation: 1.126
  • Geschlecht:Männlich
  • Wohnort:Zuhause
  • Interessen:Ja

geschrieben 07. Juli 2017 - 10:31

SQL sollte sich da selber drum kümmern. Hier ist das per Design egal. Das DBMS soll die Abfrage auflösen und optimieren, nicht der Abfragebauer.

SQLite... da ist das immer so ne Sache.

Du kannst mit SQLite vor eine Abfrage immer "EXPLAIN QUERY PLAN" davorschreiben. Also in dem Fall
EXPLAIN QUERY PLAN SELECT * FROM obstkorb WHERE farbe=hellgruen AND obst=apfel;
(plus andersrum).

Normal wäre zu erwarten, daß beide Abfragen denselben Abfrageplan haben. Da spielt unter anderem mit rein, wieviele Datensätze jeweils die Tabellen haben, aber auch, ob ggf ein Index da ist und verwendet werden kann.

Ich geh mal davon aus, daß das bei Dir relativ wenig Datensätze sind. Wenn es aber viele sind (oder werden können) und Abfragen nach Obst auf Obsttyp und Farbe üblich sind, dann kannst Du einen Index erstellen, entweder über eine der beiden Spalten oder über beide zusammen.

Mehrspaltige Indices sind dann geordnet in der Reihenfolge der definierten Spalten und Du kannst Deine Abfrage danach ausrichten. Ein Index (obst, farbe) ist nicht dasselbe wie ein Index (farbe, obst). Für ein "WHERE farbe = X" kann die erste Variante nicht verwendet werden, weil "obst" nicht bekannt ist und obst aber den Index primär bestimmt.

Entsprechend sind wenigerspaltige Indices flexibler, mehrspaltige Indices performanter für eine spezifische Abfrage. Demgegenüber sind letztere größer als erstere. Außerdem werden durch Indices Einfügeoperationen gebremst und alle Schreibvorgänge (INSERT,UPDATE,DELETE) lassen einen Index verkümmern, sodaß dieser immer mal neu erstellt werden muß.

Weniger ist hier also mehr. Je weniger Datensätze in einer Tabelle, desto alberner wird ein Index dafür. Dasselbe gilt auch für nicht-eindeutige Spalten: Wenn man in seinem Obstkorb 100 Obst hat und 99 davon sind Äpfel, dann bringt ein Index auf die Spalte "obst" überhaupt nichts; andersherum, wenn von 100 Obst 99 verschiedene Obstsorten sind, dann wäre das für einen Index mehr oder weniger perfekt. Für die Farben gilt das analog. Wenn die sich auf "rot", "grün" und "schweinchenrosa" beschränken, ist ein Index dafür nutzlos.

Hinweis, für so eine Zuordnung sind ggf drei Tabellen sinnvoll: eine Tabelle Obst mit (oid, name, <obstinfospalten>), eine Tabelle Farbe mit (fid, name, <farbinfospalten>) und eine Tabelle Obstkorb mit (oid, fid, <korbinfospalten>).

Dieser Beitrag wurde von RalphS bearbeitet: 07. Juli 2017 - 10:36

"If you give a man a fish he is hungry again in an hour. If you teach him to catch a fish you do him a good turn."-- Anne Isabella Thackeray Ritchie

Eingefügtes Bild
Eingefügtes Bild

#177066 Mitglied ist offline   Holger_N 

  • Gruppe: aktive Mitglieder
  • Beiträge: 5.009
  • Beigetreten: 11. September 10
  • Reputation: 459
  • Geschlecht:Männlich

geschrieben 07. Juli 2017 - 11:46

Bei mir gehts natürlich um was Anderes, aber mit dem Obstkorb kann man das schön verbildlichen. Ich habe – umgemünzt auf das Obstbeispiel – 4 Tabellen. In einer stehen alle Obstsorten: Apfel, Birne, Pflaume, Kirsche…
in der zweiten Tabelle die konkreten Einzelnamen aller Früchtchen
in der dritten alle möglichen Farben
und in der vierten Tabelle ist der tatsächliche Bestand nur über die IDs der anderen drei Tabellen zusammengstellt.

Das war das, wo ich neulich mit den Fremdschlüsseln experimentierte, dass ich beispielsweise sagen kann, alle Birnen fliegen aus dem Programm und ich lösche »Birne« aus der Obstsortentabelle und aus den Tabellen der Früchtchen und aus der Zusammenstellung fliegen alle Birnen automatisch raus. Allerdings verliert man da schnell den Überblick und wenn ich dann drei Wochen später den Fremdschlüssel wieder vergessen habe, sehe ich am Code nicht mehr was gelöscht wird.
Bauernregel: Regnets mächtig im April, passiert irgendwas, was sich auf April reimt.

#177067 Mitglied ist offline   RalphS 

  • Gruppe: aktive Mitglieder
  • Beiträge: 8.810
  • Beigetreten: 20. Juli 07
  • Reputation: 1.126
  • Geschlecht:Männlich
  • Wohnort:Zuhause
  • Interessen:Ja

geschrieben 07. Juli 2017 - 12:41

Kommentieren. :imao:

Da würd ich einen VIEW drauf setzen. Dann geht das einfacher abzufragen.

ZB so:
CREATE VIEW v_obstkorb AS 
 SELECT n.name AS obst_name, s.name AS sorte, f.name AS farbe FROM
  obstkorb AS k
 JOIN
  obstname  AS n ON k.name_id = n.id
 JOIN
  obstsorte AS s ON k.sorte_id = s.id
 JOIN
  obstfarbe AS f ON k.farbe_id = f.id;



Wenn Du was anderes als SQLITE verwendest - zB Access -- müßtest Du schauen, ob Funktionen unterstützt werden. SQLITE kann das noch nicht (wenn sich das nicht inzwischen geändert haben sollte). Dann könntest Du mit sowas wie CREATE FUNCTION get_obst(varchar, varchar) RETURNS TABLE eine Funktion definieren, die Farbe und Obstsorte übergeben kriegt und die dann eine Tabelle zurückgibt mit den passenden Einträgen.

Wenn Du jetzt viele Datensätze haben solltest, könntest Du in den jeweiligen Tabellen für jede Spalte "name" einen Index draufsetzen. Die JOINs laufen über den Primärschlüssel; der ist automatisch indiziert.

Auch dann ist am Ende völlig egal, wie rum Du Die Abfrage bastelst. Note: Schreiboperationen gehen auf VIEWs nicht, nur SELECTs. Einfügeoperationen müßtest Du per Transaktion über alle beteiligten Tabellen direkt anweisen.
"If you give a man a fish he is hungry again in an hour. If you teach him to catch a fish you do him a good turn."-- Anne Isabella Thackeray Ritchie

Eingefügtes Bild
Eingefügtes Bild

#177068 Mitglied ist offline   Holger_N 

  • Gruppe: aktive Mitglieder
  • Beiträge: 5.009
  • Beigetreten: 11. September 10
  • Reputation: 459
  • Geschlecht:Männlich

geschrieben 07. Juli 2017 - 15:54

Wieviel sind viele Datensätze? Also bei mir sind es schätzungsweise zwischen 500.000 und 1.000.0000 Datensätze. Da wird dann mit einer Abfrage genau ein Datensatz rausgefiltert. Für die kleine Tabelle sind es 450 solcher Abfragen (30 Abfragen in einer Schleife, die 15 mal durchlaufen wird) bzw. 4500 für die große Tabelle, die praktisch 10 der kleinen Tabellen enthält.

Da ist garantiert noch irgendwo Optimierungspotential.


und… während ich das Tippe habe ich schon eine Idee.

Wobei sich mir der Sinn von CREATE VIEW nicht erschließt.

Dieser Beitrag wurde von Holger_N bearbeitet: 07. Juli 2017 - 16:20

Bauernregel: Regnets mächtig im April, passiert irgendwas, was sich auf April reimt.

#177069 Mitglied ist offline   RalphS 

  • Gruppe: aktive Mitglieder
  • Beiträge: 8.810
  • Beigetreten: 20. Juli 07
  • Reputation: 1.126
  • Geschlecht:Männlich
  • Wohnort:Zuhause
  • Interessen:Ja

geschrieben 07. Juli 2017 - 16:44

Das sind schon viele. Genügend für einen Index. :)

Index macht Binärsuche möglich. Ohne ist das linear. Bei einem ordentlichen Index und 1 Million Datensätzen und einer Prüfdauer von 1s pro Datensatz (ist natürlich weniger, nur der Anschaulichkeit halber:

- Ohne Index: 1'000'000 Records x 1s / Record => 1'000'000s / Abfrage <=> 277 Stunden (mehr oder weniger exakt)

- Mit Index: 1'000'000 Records bei log(2) 1'000'000 s => 20 Sekunden / Abfrage (exakt)

Ohne Index weiß die DB nicht, ob der Eintrag einmal oder X-mal da ist. Also müssen alle Datensätze angeschaut werden.

Mit Index ist die bewußte Spalte... eh... indiziert, hat also ein Inhaltsverzeichnis. Außerdem ist sie sortiert. Heißt, wenn man mit Index suchen kann, dann kann aus dem Index der Schlüssel in logaritmischer Zeit rausgefischt werden und weil der Index sortiert ist, ist auch bekannt, daß bestenfalls ein Fenster von n-k Ergebnisdatensätzen da sein KANN.

Schau mal nach, ob Du ggf Abfragen zusammenfassen kannst. Das beschleunigt.

VIEWs dienen einmal der Sicherheit, weil sie Tabellen vor dem Benutzer verstecken (und man dem VIEW andere Berechtigungen geben kann als den Tabellen) der Einschränkung (weil man im VIEW von X Spalten nur X-n Spalten reinnehmen muß) und der Bequemlichkeit (weil ein VIEW letztlich nichts als ein gespeichertes SELECT ist).

Im Beispiel oben würde man deshalb mit
 SELECT * FROM v_obstkorb WHERE obst_name = 'Fritzi' AND sorte = 'Apfel';



den Namen, die Sorte und die Farbe für alle Äpfel namens Fritzi bekommen, ohne irgendein JOIN und ohne sich überlegen zu müssen, was für Spalten in den drei Tabellen dahinter vielleicht dazugekommen sein könnten.

Dieser Beitrag wurde von RalphS bearbeitet: 07. Juli 2017 - 16:46

"If you give a man a fish he is hungry again in an hour. If you teach him to catch a fish you do him a good turn."-- Anne Isabella Thackeray Ritchie

Eingefügtes Bild
Eingefügtes Bild

#177070 Mitglied ist offline   Holger_N 

  • Gruppe: aktive Mitglieder
  • Beiträge: 5.009
  • Beigetreten: 11. September 10
  • Reputation: 459
  • Geschlecht:Männlich

geschrieben 07. Juli 2017 - 18:26

Achso, ich hatte das falsch verstanden. Ich dachte man muß diesen VIEW vor jeder Abfrage machen aber das ist nur einmal beim Erstellen der Datenbank. Das funktioniert auch wie gewollt.

Aber irgendwie scheint es kein Pedant zu »REPAIR table … « und »OPTIMIZE table …« für Access zu geben.
Bauernregel: Regnets mächtig im April, passiert irgendwas, was sich auf April reimt.

#177071 Mitglied ist offline   RalphS 

  • Gruppe: aktive Mitglieder
  • Beiträge: 8.810
  • Beigetreten: 20. Juli 07
  • Reputation: 1.126
  • Geschlecht:Männlich
  • Wohnort:Zuhause
  • Interessen:Ja

geschrieben 07. Juli 2017 - 21:35

Hast eine Tabelle kaputtgespielt? :unsure:

Müßtest Du mal in der MySQL-Doku schauen, was das Optimize macht. Gut möglich, daß das so für Access überhaupt nicht zutrifft. Ich hab das bisher noch nirgendwo gebraucht.
"If you give a man a fish he is hungry again in an hour. If you teach him to catch a fish you do him a good turn."-- Anne Isabella Thackeray Ritchie

Eingefügtes Bild
Eingefügtes Bild

#177072 Mitglied ist offline   Holger_N 

  • Gruppe: aktive Mitglieder
  • Beiträge: 5.009
  • Beigetreten: 11. September 10
  • Reputation: 459
  • Geschlecht:Männlich

geschrieben 07. Juli 2017 - 22:00

Nee nur vorsichtshalber. Da ist eine Tabelle, da werden es pro Jahr knapp ne halbe Million Datensätze. Drei Jahre lang und dann kommen zwar auch weiter ne halbe Million dazu aber die halbe Million vom ersten Jahr wird gelöscht usw. Da kannte ich das bei MySQL Tabellen, dass sich da so ein Überhang gebildet hat und den wollte ich eigentlich nur regelmäßig löschen, bzw. wird die Datenbank ja immer größer wenn neue Datensätze dazukommen, aber nicht kleiner, wenn man welche löscht, bzw. kann man dazu ja in Access die Datenbank komprimieren, aber per sql finde ich da nix.

Dieser Beitrag wurde von Holger_N bearbeitet: 07. Juli 2017 - 22:01

Bauernregel: Regnets mächtig im April, passiert irgendwas, was sich auf April reimt.

#177073 Mitglied ist offline   RalphS 

  • Gruppe: aktive Mitglieder
  • Beiträge: 8.810
  • Beigetreten: 20. Juli 07
  • Reputation: 1.126
  • Geschlecht:Männlich
  • Wohnort:Zuhause
  • Interessen:Ja

geschrieben 07. Juli 2017 - 22:12

Schau mal in Richtung VACUUM. Gibts da bei Access sowas? Das ist sozusagen der SQL-Staubsauger für die Bereinigung.

Indices müssen immer mal neu erstellt werden in einer ruhigen Minute. Je nachdem wieviel in die DB geschrieben wird vielleicht einmal im Monat oder so, oder wenn das spürbar langsam wird. IIRC ging das mit TSQL als ALTER INDEX WITH REBUILD, bin aber nicht sicher, und auch nicht, was Access dazu sagt.

Wenn die Daten nicht geändert werden, müssen die Indices auch nicht erneuert werden.
"If you give a man a fish he is hungry again in an hour. If you teach him to catch a fish you do him a good turn."-- Anne Isabella Thackeray Ritchie

Eingefügtes Bild
Eingefügtes Bild

#177074 Mitglied ist offline   RalphS 

  • Gruppe: aktive Mitglieder
  • Beiträge: 8.810
  • Beigetreten: 20. Juli 07
  • Reputation: 1.126
  • Geschlecht:Männlich
  • Wohnort:Zuhause
  • Interessen:Ja

geschrieben 08. Juli 2017 - 09:31

Jetzt kommen die auch noch mit Wildcard-Zertifikaten. :huh:

Lange überfällig, aber:

- GPO geändert und LE-Root-CAs nach "Untrusted" verschoben. :ph34r:
"If you give a man a fish he is hungry again in an hour. If you teach him to catch a fish you do him a good turn."-- Anne Isabella Thackeray Ritchie

Eingefügtes Bild
Eingefügtes Bild

#177075 Mitglied ist offline   Holger_N 

  • Gruppe: aktive Mitglieder
  • Beiträge: 5.009
  • Beigetreten: 11. September 10
  • Reputation: 459
  • Geschlecht:Männlich

geschrieben 08. Juli 2017 - 11:48

Hmm, man kann in Access einstellen, dass eine Datenbank beim Schließen komprimiert wird. Ich dachte das wäre eine Funktion, die zu Access gehört und Access macht das dann mit der entsprechenden Datenbank. Einige Forenbeiträge, die ich so gefunden habe lassen aber darauf schließen, dass es sich um eine Eigenschaft handelt, die man der Datenbank mitgibt. Mein Programm funktioniert übrigens so, dass ich im Installationspaket eine komplett leere Accessdatei mitgebe. Beim ersten Start wird dann eine Kopie davon nach AppData/Roaming kopiert, die Tabellen werden dann dort erstellt und der User kann sie dann hinkopieren wo er will. Ich versuche mal der Rohdatei, die ich mit einpacke diese Eigenschaft mitzugeben.

Wobei ja insgesamt die Zeiten für die Abfrage vernachlässigbar klein ist im Vergleich zu dem, was das Programm zum Aufbau der Tabelle braucht. Jetzt wollte ich mir die abstrakten Modeldinger mal angucken aber ist alles wieder in auswärts geschrieben und wenn man sich das übersetzen lässt, übersetzt her Google die Befehle mit. Und dann ist es auch wieder so blöd beschrieben, dass man es nur versteht, wenn man es ohnehin schon weiß. Werd ich mal ne Weile suchen. Am Ende gibts dann meist doch irgendwo mal ein einzelnes Beispiel, wo es jemand verständlich beschrieben hat und das auch bei mir funktioniert.

Dieser Beitrag wurde von Holger_N bearbeitet: 08. Juli 2017 - 18:17

Bauernregel: Regnets mächtig im April, passiert irgendwas, was sich auf April reimt.

Thema verteilen:



14 Besucher lesen dieses Thema
Mitglieder: 0, Gäste: 14, unsichtbare Mitglieder: 0