# Schnell eine fortlaufende nummer erzeugen SQL, kein Primkey



## sence (5. Sep 2011)

Hallo,

bei einem Import einer großen CSV Datei, sowie an weiteren Stellen (andere Objekte)
benötige ich eine fortlaufende Nummer.
Soweit kein Problem, letzten Wert aus SQL holen, incrementieren, und wieder speichern.
Wenn ich nun aber die CSV Datei importiere > 80.000 Datensätzte 
wird der Import durch die generierung der Nummer sehr stark ausgebremst.
Selbst das reflection Parsen der Datensätze geht schneller :O)

Ich arbeite mit Hibernate als SQL Schnitstelle.

bis jetzt schauts so aus:

```
public Long getConsecutiveNumber(Session p_session) {
		if(p_session == null) { // keine Session übergeben
		Long toRet = 0L;
		
		Session session = hibernate.InitSessionFactory.getInstance().getCurrentSession();
		Transaction tx = session.beginTransaction();
				
		ConsecutiveNumber CN = (ConsecutiveNumber) session.get(ConsecutiveNumber.class, 1);
		if(CN == null) { // Noch nicht vorhanden
			CN = new ConsecutiveNumber();
			CN.setNumber(1L);
			CN.setId(1);
			session.save(CN);
			toRet = 1L;
		}else{
		toRet = CN.getNumber() + 1;
		CN.setNumber(toRet);
		session.update(CN);
		tx.commit();
		}
		return toRet;
	}else{ // Session vorhanden
		Long toRet = 0L;
		
		ConsecutiveNumber CN = (ConsecutiveNumber) p_session.get(ConsecutiveNumber.class, 1);
		if(CN == null) { // Noch nicht vorhanden
			CN = new ConsecutiveNumber();
			CN.setNumber(1L);
			CN.setId(1);
			p_session.save(CN);
			toRet = 1L;
		}else{
		toRet = CN.getNumber() + 1;
		CN.setNumber(toRet);
		p_session.update(CN);
		}
		return toRet;
	}
	}
```

Die Nummer darf nicht gecached werden, da eventuell, sofern einmal das Programm zwei mal im Einsatz ist, nicht die IDś zwei mal vergeben werden könnten.

Vielen Dank!


----------



## SlaterB (5. Sep 2011)

reserviere mit einem Mal gleich 10.000 Ids oder noch mehr, die kann dann doch wohl dieser Prozess cachen, sind nur für ihn gedacht,
wenn sie nicht genutzt werden, dann verkraftbar, oder muss es immer +1 sein?

edit:
dass du den Haupt-Code-Block zweimal schreibst ist sehr ungünstig, 
was immer du an Transaktion oder Session machen musst schreibe lieber ans Anfang und Ende per if/else,
das wichtigste dazwischen nur einmal


----------



## parabool (5. Sep 2011)

autoincrement wäre doch eine Möglichkeit ?
Bei Hibernate glaube ich SequenceGenerator.


----------



## sence (5. Sep 2011)

parabool:

dann hätte ich aber pro neue Nummer, einen neuen Datensatz. 
Also wieder mehr SQL Querys, welche das System ausbremsen.
Object obj = new Object():
session.save(obj).
tx.commit();
return obj.id;

leider nicht performant genug.

Werde wohl nicht um einen Cache herum kommen.

Denke werde 500 IDS reservieren, diesen Bereich gleich updaten, damit dieser "syncron" zwichen mehren Applikationen ist und dann sollte es klappen.

Das mit dem Hauptblock werde ich berückstichtigen. Danke!


----------



## TheDarkRose (5. Sep 2011)

Welche Datenbank läuft im Backend?


----------



## sence (5. Sep 2011)

MySql


----------



## sence (5. Sep 2011)

Fehler, zeige gleich den Code -.-


----------



## TheDarkRose (5. Sep 2011)

Tja, und warum machst du nicht aus dem ID Feld ein auto_increment?


----------



## sence (5. Sep 2011)

Hey, das Problem ist, dass es den Import vorgang ausbremst, wenn ich schnell viele IDS erzeuge.
für jede ID einen DB Eintrag machen, ist nicht gerade effizient oder ?

So könnte der Cache aussehen, vorschläge?
teste gleich mal die Geschwindigkeit, mit neuen Datensätzten Erzeugen.


```
Long pool = null;
	
	Long lastID = 0L;
	Long idsLeft = null;	
	Long cacheSize = 500L; 
	
	public Long nextNumber() {			
		
		if(pool == null || pool == 0L) {
			pool = cacheSize; // Cachesize reservieren.
			System.out.println("Speichere in DB den Pool: " + pool);
			idsLeft = cacheSize; 
			lastID = 0L;
		}
		
		
		if(idsLeft != null && idsLeft > 0 ) {
			lastID ++;
			idsLeft --;
			return lastID;
		}else{
			System.out.println("Erhöhe Cache Size um: " + cacheSize + " und speichere in DB: " );
			pool += cacheSize;
			System.out.println("Speichere in DB : " + pool);
			lastID = (pool - (cacheSize) );
			idsLeft = cacheSize;
			
			idsLeft --;
			lastID++;
			return lastID;
		}
	
			
	}
```

hab gerade mal das getestet mit Objecten erzeugen und Speichern, also nur primkeys, das dauert zulange :/

bleibe bei der Cache veriante.
Danke @ all


----------

