# Von Oracle zu Couchbase



## Chaya (23. Feb 2015)

Hallo zusammen,

ich sitze hier gerade an einer Aufgabe und komme nicht weiter.

Zum Hintergrund:
Die Aufgabe besteht im Grunde darin Daten aus einer Oracle-DB in eine Couchbase zu überführen.
In der Oracle-DB sind Keys mit zugehörigen XML-Strings hinterlegt, diese werden dann in JSON umgewandelt (das funktioniert bereits).
In der Oracle-DB sind derzeit 11 Millionen Datensätze.

Derzeit habe ich folgenden Ansatz:



```
package multithreading;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

import com.couchbase.client.java.Bucket;
import com.couchbase.client.java.document.JsonDocument;

import couchbase.ConnectionManager;
import couchbase.InsertBuild;

public class TestClob {
	static ResultSet res;
	static Statement stmt;
	private static Bucket bucket;
	
	
	
public static void insertStuff(String id, String xml, Bucket bucket) throws Exception {
		JsonDocument doc = InsertBuild.buildJsonDocument(id, xml);
		bucket.async().upsert(doc);
	}
	
	
	public static void main(String[] args) throws Exception{
		long lStartTime = System.nanoTime();
		ConnectionManager cm = new ConnectionManager();
		bucket = cm.connect();
		Class.forName("oracle.jdbc.driver.OracleDriver");
		String url = "jdbc:oracle:thin:@host:port:name";
		Connection conn = DriverManager.getConnection(url, "nutzer", "pwd");
		String sql = "select NVL(LAST_UPDATE_DATE,'01.01.1000') as LAST_UPDATE_DATE, XML_MESSAGE from db" +
				"inner join db" +
				"on db.ORDER_HEADER_ID = db2.ORDER_HEADER_ID " +
				"and db.ORDER_HEADER_ID< 25348167";
		stmt = conn.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);
		stmt = conn.createStatement();
		res = stmt.executeQuery(sql);
		
		while(res.next()){
			insertStuff(res.getString(1), res.getString(2), bucket);
		}
		
		long lEndTime = System.nanoTime();
		 
		long difference = lEndTime - lStartTime;
	 
		System.out.println("Elapsed milliseconds: " + difference/1000000);
		
		
		bucket.close();
		conn.close();
		
		
	}

}
```

Das Problem hierbei ist allerdings, das das mit den 11 Millionen Datensätzen ewig dauert.
Daher dachte ich daran, das ganze eventuell mit Threads zu lösen, das wäre das Einzige was mir jetzt noch eingefallen wäre.
Nur habe ich hierbei keine Ahnung, wie man anfangen soll, gerade weil es ja ein scrollable Resultset ist.
Threads habe ich im Studium zwar schon einmal kurz gehört und auch kurz ausprobiert, allerdings nie in Verbindung mit Datenbanken.

Könnte mir hierbei vielleicht jemand "Starthilfe" geben?
Auch eine vollkommen andere Lösung wäre ok. Hauptsache das geht alles ein bisschen schneller


vielen Dank und liebe Grüße
Chaya


----------



## dzim (24. Feb 2015)

Per se würde dir Threading vermutlich nicht helfen. Machst du die lesende und die schreibende Operation auf der selben Maschine?
Wie sieht die IO-Belastung aus? Ist die Anwendung am Limit (also CPU 100%)? Ist es lediglich eine Tabelle (mit den 11 Mio. einträgen), bzw. ein ResultSet, die es zu überführen gilt?

Ich habe mich noch nie mit diesem NoSQL-Zeug auseinandergesetzt (bisher waren SQL-DBs immer die für mich bessere Wahl), aber ich vermute, auch dort gibt es für bessere Performance so etwas wie Batch-Jobs. Denn ich vermute, dass die vielen einzelnen "Insert"-Operationen und evtl. Updates auf dem Index auf CouchDB (gibt es da so etwas?) zu einer unnötig hohen Last führen.

Such vielleicht mal nach "couchdb batch insert" oder "couchdb bulk insert"

Nutzt du LightCouch für die Java-Seite? 
LightCouch User Guide 0.1.6
CouchDbClientBase (LightCouch 0.1.6 API)

Also ich denke, ein Bulk-Insert sollte dir helfen.

Aber: Nicht alle 11 Mio Datensätze erst im Speicher halten. Vielleicht ein Bulk-Insert wenn 1000 oder so angesammelt wurden (mal herumspielen, ob das was bringt).

_#edit_: Gib dem Java-Programm eventuell auch etwas mehr Speicher. Google mal nach "Xmx" und "Xms"...


----------

