Sehr großen Graph mit Verbindungen bauen und minimieren?

berndoa

Top Contributor
Hallo,
ich scheitere nach wie vor an der Größe meines Lottoproblems.
Und im Endeffekt ist es einfach folgende Situation:
Man stelle sich folgendes Bild vor:
Links sind 13 Millionen Knotenpunkte, die nicht untereinander verbunden sind.
Rechts sind um die 18000 Knoten, auch nicht untereinander verbunden.

Zu Beginn des Ganzen ist jede Node auf der linken Seite mit genau 20 Nodes auf der rechten Seite verbunden.
Mit wie vielen Nodes auf der linken Seite eine Node auf der rechten Seite verbunden ist, ist hingegen unbekannt.

Nun wollen wir hingehen und der Reihe nach auf der rechten Seite Nodes (und damit die zugehörigen verbindungen) entfernen,
solange noch auch ohne die entfernte Node auf der linken Seite jede Node "erreichbar" ist.

Also jede Node auf der linken Seite muss immer mit irgendwas verbunden bleiben, egal wie.

Wenn wir auf der rechten Seite alle Nodes entfernt haben und nichts mehr entfernt werden kann
ohne die Bedingung zu verletzen,
dann sind wir fertig und die auf der rechten Seite noch vorhandenen Nodes sind das, was mich interessiert.

So die Lage.

Mit verschiedenen Klassen, Hashmaps und so liesse sich das normalerweise auch recht gut lösen.
Problem nur:
Wir haben rechts wie erwähnt 18000 Nodes, links um die 13 Millionen Nodes.

Da wird ein Überprüfen "Können wir rechts Node 16354 entfernen ohne eine Node links abzuschotten" echt schwer weil abertausende (bzw. millionen) Vergleiche nötig.

Und ich habe einfahc noch keine gute Idee gefunden wie man das Alles lösen könnte.

Mathematisch ginge sowas auch über eine Adjazenzmatrix die man womöglich invertieren müsste.
Aber die hätte dann 13 Millionen mal 18tausend Einträge!

Also ich habe echt keine Idee mehr, das Problem ist einfahc zu groß vom benötigten Speicher und Zeitbedarf her :-/
 

berndoa

Top Contributor
Eine Option wäre, wie man es in der Automatentheorie auch macht, einfach alle Verbindungen aufzulisten und zu gucke
"Wenn ich alle Verbindungen (a,b) entferne bei denen b 12345 ist, gibt es dann eine Zahl 1-13millionen, die nicht als a wert mehr vorkommt"

Der Aufwand ist aber genauso abartig groß :-/
Und man müsste da mit 13 millionen mal 20 Verbindungen rumhantieren...
 
Y

yfons123

Gast
wie wäre es mit einer datenbank (wie vor 2 jahren auch schon vorgeschlagen)... 1milliarden einträge sind kein problemchen
 
Y

yfons123

Gast
also ich würde lokal einfach eine MSSQL Developer Edition installieren mit einer Instanz dazu, das ist kostenlos und dödel einfach
 

berndoa

Top Contributor
also ich würde lokal einfach eine MSSQL Developer Edition installieren mit einer Instanz dazu, das ist kostenlos und dödel einfach
Hm, also ich werkle jetzt mal gerade mit Sqlite und so rum.
Aber da mit Java die nötigen Einträge reinzumachen, dauert immer noch ewig.
Ich habe ja um die 14 Millionen Sechstupel und er schafft ca. 10 Einträge pro Sekunde.
Insofern würde es trotz Allem 16 Tage dauern bis er alle Einträge erstellt hat :-/
Was mir doch etwas zu lange dauert...
 

thecain

Top Contributor
Du machst wohl was falsch.

Z.B. keine Transaction starten Defaultmässig startet sqlite für jeden insert eine neue Transaction. Das dauert dann.
 

berndoa

Top Contributor
Ja, habe es jetzt mal abgeändert sodass er einen String mit 998 zusammengefügten insert statements baut und den dann execUpdated.
sind wir eher bei so 1000-2000 die Sekunde, also etwas schneller als vorher :-D
Sind wir mal schon bei 3 Stunden.
Wenn ich jetzt noch mehrere insert Befehle mit dem selben Statement und so benutze, wird es vermutlich noch schneller :)
 

berndoa

Top Contributor
Jemand eine Ahnung wie man dieses "try with ressources" Konstrukt...
naja, ohne Selbiges benutzen kann?
Habe gelesen dass muss so sein dmait Statement und Co. auch wieder zugemacht werden.

So sieht aktuell meine Funktion aus die einen x-beliebigen SQL Syntax String annimmt. eine SQLDatabase ds ist hinterlegt:

Java:
    public void execUpdate(String query) {
        try (Connection conn = ds.getConnection(); Statement stmt = conn.createStatement();) {
            int rv = stmt.executeUpdate(query);
            System.out.println("executeUpdate() returned " + rv);
        } catch (SQLException e) {
            e.printStackTrace();
            System.exit(0);
        }
        // System.out.println("Executed Code: " + query);

    }
 

mihe7

Top Contributor
Entweder schmeißt Du die Connection in eine Instanzvariable und lässt sie offen, oder aber Du verwendest einen Connection Pool.
 

berndoa

Top Contributor
Entweder schmeißt Du die Connection in eine Instanzvariable und lässt sie offen, oder aber Du verwendest einen Connection Pool.
Hm, habe jetzt zwar so ziemlich Alles als Instanzvariable hinterlegt sodass für Alles dieselbe Database, Statement und so benutzt wird.
AAber nennenswert schneller wurde das Ganze nicht mehr.
Und laut Google kann man ja maximal 1000 Reihe mit einem Insert Befehl einfügen, wo ich mit meinen 998/999 Einträgen pro Befehl auch shcon ah dran bin...

Will jetzt nicht wirklich 3 Stunden hier sitzen und warten bis alle Zahlenreihen eingebaut sind.
Mir fällt aber auf Anhieb auch nicht viel ein, wie man es noch verbessern könnte :-/
 

berndoa

Top Contributor
Also ich habe gerade sowas von keinen Plan wovon ihr beide redet (Die Begriffe sagen mir nur wenig gerade).

Mal mein kompletter Code bisher:

Java:
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

import org.sqlite.SQLiteDataSource;

public class Test1 {
    SQLiteDataSource ds = null;
    Connection conn = null;
    Statement stmt = null;

    public static void main(String[] args) {
        Test1 a = new Test1();

        a.fillDatabaseTuples();

        a.closeAll();
    }

    public Test1() {

        try {
            ds = new SQLiteDataSource();
            ds.setUrl("jdbc:sqlite:test.db");
            conn = ds.getConnection();
            stmt = conn.createStatement();
        } catch (Exception e) {
            e.printStackTrace();
        }
        System.out.println("Opened database successfully");

        String query = "CREATE TABLE IF NOT EXISTS Tuples (" + "Sixtuple STRING NOT NULL, "
                + "SixtupleId INTEGER NOT NULL," + "Triple STRING NOT NULL," + "TripleId INTEGER NOT NULL,"
                + "PRIMARY KEY(SixtupleID,TripleID)" + ");";
        execUpdate(query);
        query = "CREATE TABLE IF NOT EXISTS ConCount (" + "Triple INTEGER NOT NULL, " + "TripleID INTEGER NOT NULL,"
                + "Occurences INTEGER NOT NULL," + "PRIMARY KEY(TripleID)" + ")";
        execUpdate(query);

    }

    public void closeAll() {
        try {
            stmt.close();
        } catch (Exception e) {
        }
        try {
            conn.close();
        } catch (Exception e) {
        }
    }

    public void execUpdate(String query) {
        try {
            int rv = stmt.executeUpdate(query);
            System.out.println("executeUpdate() returned " + rv);
        } catch (SQLException e) {
            e.printStackTrace();
            System.exit(0);
        }
        // System.out.println("Executed Code: " + query);

    }

    public ResultSet execQuery(String query) {
        try {
            ResultSet rv = stmt.executeQuery(query);
            System.out.println("executeUpdate() returned " + rv);
            return rv;
        } catch (SQLException e) {
            e.printStackTrace();
            System.exit(0);
        }
        System.out.println("Error with Query!");
        return null;

    }

    public String toString(int[] xTupel) {
        String res = "";
        for (int i = 0; i < xTupel.length - 1; i++) {
            res = res + xTupel[i] + ".";
        }
        res = res + xTupel[xTupel.length - 1];
        return res;
    }

    public int hash3(int[] triple) {
        int res = triple[0];
        for (int i = 1; i < triple.length; i++) {
            res = 100 * res + triple[i];
        }
        return res;

    }

    public void fillDatabaseTuples() {
        execUpdate("DELETE FROM Tuples");
        String a1 = "INSERT INTO Tuples VALUES ";

        int count = 0;

        String temp = "";
        int sixtid = 0;

        NumberGenerator numg = new NumberGenerator(6, 1, 49);

        while (!(numg.endReachedb())) {

            // sixTupel
            int[] sixtupel = numg.getNumberb();
            for (byte i1 = 0; i1 < sixtupel.length - 2; i1++) {
                for (byte i2 = (byte) (i1 + 1); i2 < sixtupel.length - 1; i2++) {
                    for (byte i3 = (byte) (i2 + 1); i3 < sixtupel.length; i3++) {
                        int[] tripel = new int[] { sixtupel[i1], sixtupel[i2], sixtupel[i3] };
                        temp = temp + " (" + "\"" + toString(sixtupel) + "\"" + "," + sixtid + "," + "\""
                                + toString(tripel) + "\"" + "," + hash3(tripel) + ")";
                        if (((count % 998) != 0) || (count == 0)) {
                            temp = temp + ",";
                        } else {
                            temp = temp + ";";
                            execUpdate(a1 + temp);
                            System.out.println("count=" + count + "; Executed code:" + a1 + temp);
                            temp = "";
                            try {
                                Thread.sleep(300);
                            } catch (Exception e) {
                            }
                            // System.exit(0);
                        }
                        count++;
                    }
                }
            }
            sixtid++;

        }

    }

}

Ich habe noch eine NumberGenerator Klasse, die mittels .getNumberb() der Reihe nach alle Tupel mit bestimmten Eigenschaften ausgibt, ähnlich einem iterator oder sowas (Hier gibt er mir der Reihe nahc alle aufsteigend sortierten 6-Tupel, deren kleinste Zahl 1 und größte 49 ist, der Reihe nahc als int[6] zurück.

Details auch egal, jedenfalls kommt bei .getNumberb() immer ein int[6] raus, dessen Elemente zwischen 1 und 49 liegen.
 
Y

yfons123

Gast
Also ich nehme an dass Sicherheit komplett scheiß egal ist.

Jetzt von deinem Code sehe ich erstmal ein problem, du legst einen Primary Key beim erstellen der Tabelle an, der ist unique, um unique durch zu ziehen musst du einen Index anlegen ( machts automatisch ) der wird aber jedes mal überprüft

der index ist soweiso dann komplett fragmentiert nach dem einfügen des ganzen sschinkens also das bringt dir 0.
Es wäre klüger zuerst alles rein zu laden und dann den Primary Key im nachhinein anzulegen weil das überprüfen und index anlegen ewig dauert

eifnach im nachhienin ein add constraint und gut ist

dann willst du nicht jeden blöden insert einzeln absetzen.. ist doch kompletter quatsch.. sqlite muss jeden insert parsen, ist doch immer das gleiche

dabei willst du eigentlich ein "BULK INSERT" machen, sqlite hat das nicht "direkt" wie zb mssql transact sql hat den befehl "BULK INSERT" aber das ist nicht schlimm

du kannst vom jdbc treiber die prepared statements hernehmen und mit batches machen

oder den SQLITE bulk insert hernehmen, batches werden eifnacher sein

die sqlite syntax für bulk inserts wäre das da nur so nebenbei
Java:
INSERT INTO 'tablename' ('column1', 'column2') VALUES
  ('data1', 'data2'),
  ('data1', 'data2'),
  ('data1', 'data2'),
  ('data1', 'data2');

aber der jdbc weg wäre einfacher
Code:
int batchSize = 1000
int currentSize = 0
PreparedStatement pstmt = conn.prepareStatement("INSERT INTO customers (CustID, Last_Name, First_Name, Email, Phone_Number) VALUES(?,?,?,?,?)");
            for (int i = 0; i < deinblabla.length; i++) {
                //hier musst du halt deine  Zahlen vorbereiten
                pstmt.setInt(1, i + 1);
                pstmt.setString(2, lastNames[i]);
                pstmt.setString(3, firstNames[i]);
                pstmt.setString(4, emails[i]);
                pstmt.setString(5, phoneNumbers[i]);
                // das fügt das statement zu deiner batch hinzu
                pstmt.addBatch();
                currentSize++;
                if(currentSize = batchSize)
                {
                    // falls das batch voll ist führ es aus
                    // batches nicht zu groß machen, lieber öfter abschicken
                    pstmt.executeBatch();
                    currentSize = 0;
                }
            }
der vorteil hier ist dass sqlite nur 1 mal den query parsen muss

ich hab das mal in php ausprobiert und das ergibt ungefähr eine performance erhöhung von ungefähr faktor 10
habe 1milliarde einträge gemacht mit varchar und int
1. normales statement war bei 6 sekunden
2. prepared statement war bei 0,1 irgendwas sekunden

also prepared statements sind nicht nur für sicherheit gut sondern auch für performance

du musst glaub ich noch den auto commit ausschalten
Java:
conn.setAutoCommit(false);
 

berndoa

Top Contributor
Also ich nehme an dass Sicherheit komplett scheiß egal ist.

Jetzt von deinem Code sehe ich erstmal ein problem, du legst einen Primary Key beim erstellen der Tabelle an, der ist unique, um unique durch zu ziehen musst du einen Index anlegen ( machts automatisch ) der wird aber jedes mal überprüft

der index ist soweiso dann komplett fragmentiert nach dem einfügen des ganzen sschinkens also das bringt dir 0.
Es wäre klüger zuerst alles rein zu laden und dann den Primary Key im nachhinein anzulegen weil das überprüfen und index anlegen ewig dauert

eifnach im nachhienin ein add constraint und gut ist

dann willst du nicht jeden blöden insert einzeln absetzen.. ist doch kompletter quatsch.. sqlite muss jeden insert parsen, ist doch immer das gleiche

dabei willst du eigentlich ein "BULK INSERT" machen, sqlite hat das nicht "direkt" wie zb mssql transact sql hat den befehl "BULK INSERT" aber das ist nicht schlimm

du kannst vom jdbc treiber die prepared statements hernehmen und mit batches machen

oder den SQLITE bulk insert hernehmen, batches werden eifnacher sein

die sqlite syntax für bulk inserts wäre das da nur so nebenbei
Java:
INSERT INTO 'tablename' ('column1', 'column2') VALUES
  ('data1', 'data2'),
  ('data1', 'data2'),
  ('data1', 'data2'),
  ('data1', 'data2');

aber der jdbc weg wäre einfacher
Code:
int batchSize = 1000
int currentSize = 0
PreparedStatement pstmt = conn.prepareStatement("INSERT INTO customers (CustID, Last_Name, First_Name, Email, Phone_Number) VALUES(?,?,?,?,?)");
            for (int i = 0; i < deinblabla.length; i++) {
                //hier musst du halt deine  Zahlen vorbereiten
                pstmt.setInt(1, i + 1);
                pstmt.setString(2, lastNames[i]);
                pstmt.setString(3, firstNames[i]);
                pstmt.setString(4, emails[i]);
                pstmt.setString(5, phoneNumbers[i]);
                // das fügt das statement zu deiner batch hinzu
                pstmt.addBatch();
                currentSize++;
                if(currentSize = batchSize)
                {
                    // falls das batch voll ist führ es aus
                    // batches nicht zu groß machen, lieber öfter abschicken
                    pstmt.executeBatch();
                    currentSize = 0;
                }
            }
der vorteil hier ist dass sqlite nur 1 mal den query parsen muss

ich hab das mal in php ausprobiert und das ergibt ungefähr eine performance erhöhung von ungefähr faktor 10
habe 1milliarde einträge gemacht mit varchar und int
1. normales statement war bei 6 sekunden
2. prepared statement war bei 0,1 irgendwas sekunden

also prepared statements sind nicht nur für sicherheit gut sondern auch für performance

du musst glaub ich noch den auto commit ausschalten
Java:
conn.setAutoCommit(false);


Sicherheit ist völlig egal, stimmt.
Ich baue mir eine ellenlange Liste an Lottozahlen auf meinem Computer (kein Server oder so), da kann mitlesen wer will :)

So wie du es im 1. codeteil hast, habe ich im Prinzip es gemacht.
Einen ellenlangen String gebaut mit
insert befehl drin und 998 Reihen (wobei ich da 4 oder 5 spalten statt wie bei dir 2 habe).

Mehr als 1000 Reihen darf man da ja nicht pro Insert Befehl nutzen, schrieb mal ein kerl bei StackOverflow.


Und das dann halt mittels der execUpdate(...) Befehl geschickt.

Mit diesem Batch Insert, prepared Statement und generell statements, das muss ich mir mal angucken im Detail.
Habe von sql und diesem sqlite java teil wenig Ahnung, habe da sprichwörtlich gestern Mittag überhaupt das erste Mal reingeguckt.

Mein letztes Mal MySQL war irgendwie vor 15 Jahren in der Schule :-D
 

berndoa

Top Contributor
Primary Key brauche ich persölich gar nicht aber ich las dass jede Tabelle zwingend einen Primary Key braucht.

Wenn das Ganze ohne Primary Key geht, solls mir auch recht sein :)
 
Y

yfons123

Gast
Primary Key brauche ich persölich gar nicht aber ich las dass jede Tabelle zwingend einen Primary Key braucht.

Wenn das Ganze ohne Primary Key geht, solls mir auch recht sein
ja es geht immer ohne

eigentlich ist es schön dass du einen primary key hast.

Du hast nur ein problemchen... du musst einen reisen shcinken an sachen da rein pumpen, da stört der key am anfang nur ( durch die check constraints und indizes )

das mit prepared statements ist halt einfacher als selber einen string zusammen zu schustern und du nimmst da halt das zeug her was die jdbc typen mal gebaut haben und die haben mehr ahnung von dem zeug als du und ich , deswegen ist immer der weg das zeug von den profis her zu nehmen und nicht selber was zusammen zu schustern wenn man es eh schon auf dem silber tablett serviert hat


batch ist nur eine umschreibung für "ein haufen sql sachen" ... also du wrifst der db einfach mehrere sql statements auf einmal an den kopf
 

berndoa

Top Contributor
Also ich nehme an dass Sicherheit komplett scheiß egal ist.

Jetzt von deinem Code sehe ich erstmal ein problem, du legst einen Primary Key beim erstellen der Tabelle an, der ist unique, um unique durch zu ziehen musst du einen Index anlegen ( machts automatisch ) der wird aber jedes mal überprüft

der index ist soweiso dann komplett fragmentiert nach dem einfügen des ganzen sschinkens also das bringt dir 0.
Es wäre klüger zuerst alles rein zu laden und dann den Primary Key im nachhinein anzulegen weil das überprüfen und index anlegen ewig dauert

eifnach im nachhienin ein add constraint und gut ist

dann willst du nicht jeden blöden insert einzeln absetzen.. ist doch kompletter quatsch.. sqlite muss jeden insert parsen, ist doch immer das gleiche

dabei willst du eigentlich ein "BULK INSERT" machen, sqlite hat das nicht "direkt" wie zb mssql transact sql hat den befehl "BULK INSERT" aber das ist nicht schlimm

du kannst vom jdbc treiber die prepared statements hernehmen und mit batches machen

oder den SQLITE bulk insert hernehmen, batches werden eifnacher sein

die sqlite syntax für bulk inserts wäre das da nur so nebenbei
Java:
INSERT INTO 'tablename' ('column1', 'column2') VALUES
  ('data1', 'data2'),
  ('data1', 'data2'),
  ('data1', 'data2'),
  ('data1', 'data2');

aber der jdbc weg wäre einfacher
Code:
int batchSize = 1000
int currentSize = 0
PreparedStatement pstmt = conn.prepareStatement("INSERT INTO customers (CustID, Last_Name, First_Name, Email, Phone_Number) VALUES(?,?,?,?,?)");
            for (int i = 0; i < deinblabla.length; i++) {
                //hier musst du halt deine  Zahlen vorbereiten
                pstmt.setInt(1, i + 1);
                pstmt.setString(2, lastNames[i]);
                pstmt.setString(3, firstNames[i]);
                pstmt.setString(4, emails[i]);
                pstmt.setString(5, phoneNumbers[i]);
                // das fügt das statement zu deiner batch hinzu
                pstmt.addBatch();
                currentSize++;
                if(currentSize = batchSize)
                {
                    // falls das batch voll ist führ es aus
                    // batches nicht zu groß machen, lieber öfter abschicken
                    pstmt.executeBatch();
                    currentSize = 0;
                }
            }
der vorteil hier ist dass sqlite nur 1 mal den query parsen muss

ich hab das mal in php ausprobiert und das ergibt ungefähr eine performance erhöhung von ungefähr faktor 10
habe 1milliarde einträge gemacht mit varchar und int
1. normales statement war bei 6 sekunden
2. prepared statement war bei 0,1 irgendwas sekunden

also prepared statements sind nicht nur für sicherheit gut sondern auch für performance

du musst glaub ich noch den auto commit ausschalten
Java:
conn.setAutoCommit(false);
Cool,danke!

Habe es gebaut und am Anfang wollte ich fast shcon schreiben dass die batch variante bei mir rigendwie langsamer lief als das mit dem sql insert String, weil es rund 1000 einträge pro 3 Sekunden schafft vs. der ca 4500 pro sekunde vorher.

Aber dann las ich den Absatz mit dem Commit ausschalten.
Und bamm, schafft er so 1,5 Milliarden oder so die Sekunde.
Das ist krank wie viel schneller das geht! :O

Wenn ich dann irgendwann meine Querys (die nach auf mich warten. Die Grundtabelle zu bauen war erst der Anfang der Hölle) baue, hoffe ich doch dass man das genauso highspeed irgendwie machen kann :O
 
Y

yfons123

Gast
ja das kannst du so "high speed" machen

dafür sind indexe da , ein primary key hat automatisch einen index weil er den unique constraint hat

aber der index hilft was schneller zu finden, das problem ist dass manche leute nicht verstehen dass es bei einem index darauf ankommt was in der where klausel steht und auch was im select steht dass der optimal läuft

was ich mir noch vorstellen kann ist dass java out noch blockt, system.out.println bei so vielen ausgaben frisst schon.. vllt das ausschalten
 

mihe7

Top Contributor
also prepared statements sind nicht nur für sicherheit gut sondern auch für performance
Richtig, aber anders :)

Bevor das DBMS eine SQL-Anweisung ausführen kann, müssen ein paar Dinge passieren: parsen, Anfrageoptimierung, am Ende hat man also eine "kompilierte" und optimierte Version der SQL-Abfrage, ggf. wird auch schon der Execution Plan erstellt.

Jedenfalls müssen diese Schritte mit einem PreparedStatement nur einmal durchgeführt werden, wenn man es öfter verwendet. Die Sicherheit gibts gratis obendrauf: weil die Abfrage bereits vorkompiliert ist, kann es auch keine SQL-Injection mehr geben.

Der wirkliche Performance Boost kommt, wenn man keine automatischen Commits verwendet. SQL-Abfragen finden immer in einer Transaktion statt, beim Commit müssen auch die ACID-Eigenschaften durchgesetzt werden. Ist der Commit durchgegangen, muss z. B. sichergestellt sein, dass die Daten sich tatsächlich auf dem Datenträger befinden (ja, man kann das ggf. konfigurieren, aber dann riskiert man das D in ACID). Kurz: ein Commit ist meist sehr teuer.
 

berndoa

Top Contributor
Ich gucke mir gerade die erzeugte Datenbank mit SQliteStudio an. Ist es eigentlich normal dass man da nur um die 18000 Reihen maximal sieht?
Habe 19 Seiten dort und die eltzte einsehbare Reihe hat die id 18802.

Allerdings sollten da ja eher so um die 260 Milliarden Reihen drin sein.
Werden die nur nicht angezeigt oder sind die vielleicht wirklich nicht da?
 

berndoa

Top Contributor
Gibts eigentlich einen easy Weg um Alles nach einer bestimmten Spalte sortieren zu lassen?
Weil ich eine id Spalte habe mit int werten und hätte gerne die Zeilen nahc diesem id Wert aufsteigend sortiert
 
Y

yfons123

Gast
Java:
SELECT MAX(id)

FROM table_name

damit weist du die letzte id nummer
Code:
SELECT TOP 1000 *
FROM [SomeTable]
ORDER BY MySortColumn DESC
ich weis die sqlite syntax nicht für top ab3er irgend sowas in der art
 

KonradN

Super-Moderator
Mitarbeiter
Weil ich eine id Spalte habe mit int werten und hätte gerne die Zeilen nahc diesem id Wert aufsteigend sortiert
Wenn Du da so einen fortlaufenden Index haben willst, dann lass das die Datenbank machen. Das per Abfrage machen zu lassen ist extrem fehleranfällig. Man muss sich nur überlegen: Man holt sich die id und direkt danach kommt noch ein insert und schon ist das nicht mehr das Maximum ...

Dazu gibt es die Funktionalität in den Datenbanken.
 
Y

yfons123

Gast
du kannst nach dem einfügen übrigens den primary key wieder anlegen

du kannst dir auch einen clustered index anlegen um die sortierung zu haben
 

mihe7

Top Contributor
Man muss sich nur überlegen: Man holt sich die id und direkt danach kommt noch ein insert und schon ist das nicht mehr das Maximum ...
@berndoa genau! Für solch Scherze niemals mit MAX(), COUNT() etc. arbeiten. Fast jedes RDBMS kennt "auto increment" (identity, sogar Oracle kann das seit Version 12 - ROFL) Datentypen und wenn nicht, kann man SEQUENCEs verwenden, wobei man der Spalte dann den nächsten Wert aus der Sequence als Default gibt oder man schreibt einen Trigger.

Will man es unbedingt selbst abfragen (z. B. für vom Benutzer einstellbare Nummernkreise), dann legt man sich dafür eine Tabelle an und verwendet einen SELECT FOR UPDATE, damit der Satz gesperrt wird. Das macht z. B. JPA, wenn man für die ID-Erzeugung GenerationType.TABLE angibt, allerdings in der Regel in optimierter Form (heißt: es wird gleich ein ganzer Block weitergezählt und der Zähler im Speicher hochgezählt. Auf diese Weise braucht es die Abfrage + Sperre nur, wenn der Block aufgebraucht ist). Am besten ist es aber, die Möglichkeiten des DBMS zu nutzen. Das ist wesentlich performanter.
 

berndoa

Top Contributor
Wenn Du da so einen fortlaufenden Index haben willst, dann lass das die Datenbank machen. Das per Abfrage machen zu lassen ist extrem fehleranfällig. Man muss sich nur überlegen: Man holt sich die id und direkt danach kommt noch ein insert und schon ist das nicht mehr das Maximum ...

Dazu gibt es die Funktionalität in den Datenbanken.
Naja, die Tabelle ist ja fertig soweit.

Ich will sie nur mal passend sortiert haben weils für dne nächsten Schritt (den als sql Befehl hinzukriegen extrem nervig wird) sinnvoll ist.

So wie man im Internet oder wo auch bei einer Tabelle auf den namen eienr Spalte klickt und Alles nach jener Spalte auf oder absteigend sortiert wird.
 
Y

yfons123

Gast
eine Tabelle kann Absteigend oder Aufsteigend schon gespeichert werden

oder du legst dir einen Grouped index oder cluster index an , weis nimmer wie das heißt
das "klicki bunti" mit sortieren ist kein feature von sql

das macht die GUI. das data studio oder was auch immer du hernimmst
wenn du es sortiert und gruppiert haben willst musst du das in der tabellen definition festlegen oder halt durch abfragen steuern
 

KonradN

Super-Moderator
Mitarbeiter
eine Tabelle kann Absteigend oder Aufsteigend schon gespeichert werden

oder du legst dir einen Grouped index oder cluster index an , weis nimmer wie das heißt
das "klicki bunti" mit sortieren ist kein feature von sql
Ja, aber das sollte man genau verstehen, sonst verschlechterst Du die Performance massiv!

Stell Dir nur vor, dass Du eine Sequence hast, die aufsteigend ist und Du willst die Werte absteigend sortiert gesspeichert haben! Schön, wenn man der Datenbank schön viel IO Last aufbürdet!

Daher gilt auch hier - so wie immer:
  • erst einmal überlegen, was man wirklich braucht.
  • Dann gilt hier auch: einfache Lösungen, die das Ziel erreichen, sind zu bevorzugen.
  • Keine wilden Optimierungen! Auch bei Datenbanken gilt: Lass es. Und für Fortgeschrittene: Nach Analyse gerne.

Also bau eine Datenbank, nutze diese. Die Datenbanken merken sich intern:
a) welche Indices wurden überhaupt verwendet
b) Welche zusätzlichen Indices hätten bei den Abfragen geholfen.

==> Mit diesen Analysen lässt sich dann schon etwas anfangen, denn bei Punkt a hat man dann eine Liste von Indices, die man löschen könnte. Bezüglich b) ist das aber nur ein Ansatz, was evtl. in Frage kommen könnte. Hier wird halt nur einseitig die Abfrage-History betrachtet. Mit jedem Index mehr verzögert sich aber der Insert. Und bei #21 ging es ja um die Performance von Insert Operationen.

Das zeigt nur etwas die Komplexität. Es gibt dann natürlich auch weitergehende Methoden - wenn man also spezielle Insert Zeiten hat (z.B. Import Jobs), dann kann man die ohne Indizes und Checks laufen lassen um dann nach dem (Bulk) Insert die Checks zu aktivieren und er baut dann einmal die Indizes auf. Aber das setzt dann tatsächlich tieferes Wissen voraus.

Also um es noch einmal kurz zusammen zu fassen: Hier wirklich aufpassen, was man macht und auch was man anderen als Idee vorsetzt.
 
Y

yfons123

Gast
wenn man also spezielle Insert Zeiten hat (z.B. Import Jobs), dann kann man die ohne Indizes und Checks laufen lassen um dann nach dem (Bulk) Insert die Checks zu aktivieren und er baut dann einmal die Indizes auf. Aber das setzt dann tatsächlich tieferes Wissen voraus.
in seinem fall war ja klar dass ein Primary Key nicht doppelt vorkommt

also war der Primary Key vor dem Insert unnötig

mein Vorschlag ganz am anfang war es ja zuerst den Primary KEy weg zu lassen und dann erst nach dem Einfügen wieder hinzuzuüfgen
es war ja von seinem code her nicht möglich einen doppelten primary key zu haben
 

berndoa

Top Contributor
Mal eine Frage:
Sehe ich das richtig, dass man in Sqlite (und SQL generell) eine Tabelle shclciht nicht ordnen kann?
Also bspw. die Zeilen nicht so reaarangieren lassen kann dass Alees aufsteigend nach Spalte X, dnan nach Spalte Y sortiert ist?


Sondern nur Kram mittels SELECT raussuchen und diese Ergebnisliste sortiert erhalten kann?

Wäre dann sehr erbärmlich wo sowas sprichwörtlich jede halbwegs moderne Tabelle dieser Welt kann.
Zumindest mal nach einer bestimmten Spalte sortieren.
 
Y

yfons123

Gast
Java:
A table or view can contain the following types of indexes:

Clustered

Clustered indexes sort and store the data rows in the table or view based on their key values. These are the columns included in the index definition. There can be only one clustered index per table, because the data rows themselves can be stored in only one order. 

The only time the data rows in a table are stored in sorted order is when the table contains a clustered index. When a table has a clustered index, the table is called a clustered table. If a table has no clustered index, its data rows are stored in an unordered structure called a heap.
 
Ähnliche Java Themen
  Titel Forum Antworten Datum
N Bin to Dez und umgekehrt mit sehr großen Zahlen Allgemeine Java-Themen 2
nrg Arbeiten mit sehr großen CSV Dateien Allgemeine Java-Themen 20
K replaceAll bei sehr großen String Allgemeine Java-Themen 3
G Lesen von sehr großen dateien Allgemeine Java-Themen 8
E String.replace für (sehr) großen Text Allgemeine Java-Themen 9
javamax2000 Sehr sonderbares Verhalten Allgemeine Java-Themen 6
B Welcher Datentyp für sehr große Zahlenbereiche? Allgemeine Java-Themen 1
P Rechnen mit sehr kleinen Zahlen Allgemeine Java-Themen 5
R JDK installieren OpenJDK-Aufruf sehr langsam Allgemeine Java-Themen 4
Thallius String erzeugen sehr langsam Allgemeine Java-Themen 16
D Verwaltung von sehr vielen Objekten Allgemeine Java-Themen 12
S JNLP startet seit 1.8.0_31 sehr langsam + Windows-Systemverzeichnis Allgemeine Java-Themen 3
Creylon Java verursacht sehr starkes ruckeln Allgemeine Java-Themen 5
T Gleiche Operation dauert teilweise sehr lange Allgemeine Java-Themen 12
M Externe Jar sehr langsam Allgemeine Java-Themen 23
M JUnit & Multithreading - sehr seltener Fehler Allgemeine Java-Themen 3
H Sehr viele Threads effizient Verwalten Allgemeine Java-Themen 13
J Laden von JAR Files geht ohne ADMIN Rechte sehr langsam Allgemeine Java-Themen 6
H Kopieren sehr langsam Allgemeine Java-Themen 5
B Cipher.getInstance Aufruf sehr langsam Allgemeine Java-Themen 2
B Eingabemaske Komponenten aktivieren, funktionert nicht (sehr kurios) Allgemeine Java-Themen 2
hdi Heap Sapce Error bei sehr großem String Allgemeine Java-Themen 5
G RXTX library braucht sehr lange zum laden. Ist das normal? Allgemeine Java-Themen 8
L Java 1.5 - Anwendung unter 1.6 JRE sehr langsam geworden Allgemeine Java-Themen 8
O Speicherverbrauch von Java / VM sehr hoch? Allgemeine Java-Themen 27
M Rechnen mit sehr kleinen Zahlen Allgemeine Java-Themen 8
M String zusammensetzen->sehr langsam Allgemeine Java-Themen 3
G Sehr sehr merkwürdige Ereignisse mit Fibonacci Programm Allgemeine Java-Themen 6
G Sehr gutes Java-Framework(Gui-Builder) auf XML-Basis gesucht Allgemeine Java-Themen 21
T [SVNKit] Commit sehr langsam. Allgemeine Java-Themen 7
G Arraylist statt List - Sehr schlimm? Allgemeine Java-Themen 8
F JAVA Applikationen starten sehr langsam Allgemeine Java-Themen 14
D Datei öffnung sehr langsam Allgemeine Java-Themen 17
G Neue Warenwirtschaft aber sehr langsam! Allgemeine Java-Themen 3
H Entpacken sehr langsam Allgemeine Java-Themen 10
Bleiglanz Benchmarks sind sehr schwierig Allgemeine Java-Themen 2
T Modulo-Operator versagt bei zu großen Zahlen? Allgemeine Java-Themen 14
H Gibt es einen großen Unterschied zwischen Java 6 und Java 7? Allgemeine Java-Themen 3
R Panel mit 8 gleich großen "fenstern" Allgemeine Java-Themen 11
M Eclipse Stackoverflow beim Einlesen von großen Bilder in kd Baum Allgemeine Java-Themen 15
S Schnelles arbeiten mit großen CSV Dateien Allgemeine Java-Themen 4
H2SO3- großen double in string mit e umwandeln Allgemeine Java-Themen 4
kb22 CMS mit großen Dateien (heap problem) Allgemeine Java-Themen 3
H2SO3- speichern von Daten in seeeeeehr großen Tabellen (nicht DB) Allgemeine Java-Themen 8
G Bringt es etwas System.gc() nach großen Aufgaben aufzurufen? Allgemeine Java-Themen 2
T Suche den großen Calendar Thread ! Allgemeine Java-Themen 2
U Kompilieren einer großen Datei if-else = StackOverflowError Allgemeine Java-Themen 4
S Datenbank Abfragen mit großen Datenmengen Allgemeine Java-Themen 22
M String#equals(), Probleme mit großen Strings? Allgemeine Java-Themen 4
F Mehrere Bilder zu einem Großen zusammenkleben Allgemeine Java-Themen 3
R Was nehmen für Flußdiagramme und Druck von großen Grafiken Allgemeine Java-Themen 4
W JTextArea beschleunigen bei großen Texten Allgemeine Java-Themen 4
flashfactor Problem mit mehren großen Dateien Allgemeine Java-Themen 3
N Graph Visualizition Allgemeine Java-Themen 5
B Type mismatch: cannot convert from Graph.Edge to ArrayList<Graph.Edge> Allgemeine Java-Themen 21
T Graph/Adjazenzliste programmieren Allgemeine Java-Themen 10
F Framework/Plugin für Tree-Darstellung in Graph Allgemeine Java-Themen 0
J Breitensuche in Graph rekursiv Allgemeine Java-Themen 2
Y Prüfen ob ein Graph immer einen von mehren Enden erreicht Allgemeine Java-Themen 4
H Graph-Algorithmus gesucht Allgemeine Java-Themen 21
M Jaxb und JPA: A cycle is detected in the object graph Allgemeine Java-Themen 5
T Algorithmus Graph Allgemeine Java-Themen 10
Mike90 Graph in einer Mail verschicken Allgemeine Java-Themen 7
N Graph mit JUNG-Framework erstellen Allgemeine Java-Themen 2
as182005 Bibliothek für Graph Visualisierung gesucht Allgemeine Java-Themen 3
dru Graph aus Ascii Daten erstellen Allgemeine Java-Themen 2
P Graph Permutationen Allgemeine Java-Themen 29
J Vererbungshirachie Graph Allgemeine Java-Themen 4
royale Breitendurchlauf / Dijkstra durch Graph, vereinfacht Allgemeine Java-Themen 3
G Graph mittels Punkte erstellen Allgemeine Java-Themen 27
C JUNG Framework - einfacher Graph Allgemeine Java-Themen 7

Ähnliche Java Themen

Neue Themen


Oben