Herzlich willkommen auf dem Blog der exensio GmbH

exensio ist ein unabhängiges Software-Unternehmen von erfahrenen IT Beratern und Architekten. Zu unseren Kunden zählen namhafte deutsche Großunternehmen.

exensio verbessert das Kommunikations- und Informationsmanagement von Unternehmen. Auf Basis sinnvoller und zweckmäßiger Technologien erarbeiten wir flexible und übergreifende Lösungen für webbasierte Informationssysteme. Abhängig von den Kundenanforderungen realisieren wir Web Applikationen sowie Lösungen auf Basis von Web Content Management- und Portalsystemen. Integrativ, wirtschaftlich und anwenderfreundlich!

Hier gelangen Sie zur exensio GmbH.

Samstag, 23. April 2016

OLAP Cube vs. Elasticsearch

In diesem Blog-Post möchte ich die Möglichkeiten aufzeigen, die Elasticsearch im Bereich Business Analytics bietet. Als Basis benutzte ich wiederum Testdaten aus der Publikation »Excel 2010 im Controlling« [1], das im Verlag Rheinwerk (früher Galileo Computing) erschienen ist. Diesmal ist es eine CSV-Datei mit 1,5 Millionen Zeilen. Da diese für Excel zu umfangreich ist (~1 Million Zeilen Limit in Excel 2007), wird im Buch PowerPivot und OLAP Cubes (auch als Datenwürfel bezeichnet) in Kombination mit dem Microsoft SQL Server benutzt.

OLAP ist die Abkürzung für »Online Analytical Processing« und dient der Abfrage von mehrdimensionalen Informationen, analog zu einer Pivot-Tabelle. In unserem Beispiel ist die erste Dimension das Land, die zweite das Produkt und die dritte das Jahr (zeitliche). Die Dimensionen können in einem OLAP-Cube je nach Anforderung flexibel gewählt werden, jedoch sind spätere Änderungen äußerst aufwändig. Des Weiteren gibt es noch die Faktentabellen, die mathematische Auswertungen, wie berechnete Umsätze enthalten. Solch ein Datenbankschema wird auch als Star-Schema bezeichnet. Vorteil des Star-Schemas besteht darin, dass nur eine geringe Anzahl von Joins benötigt werden (bessere Performance bei großen Datenmengen einer RDB). Die Abfrage von OLAP-Cubes erfolgt mit einer speziellen Sprache, genannt MDX (Multidimensional Expressions).

In Elasticsearch wird dies alles nicht benötigt. Die Daten müssen demzufolge nicht voraggregiert in ein Star-Schema geladen werden, sie werden einfach flach (denormalisiert) in einem JSON-Dokument gespeichert. Will man Relationen in Elasticsearch verwenden, so gibt es die Möglichkeit »Nested Objects« bzw. »Parent/Child Relationships« zu benutzen. In meinem Beispiel habe ich zu Testzwecken »Nested Objects« für die Kunden und die Produkte eingefügt. Man sollte jedoch darauf verzichten, sofern es machbar ist, da dies komplexere Abfragen gegen Elasticsearch bewirkt. 

Folgendes Python-Skript erzeugt das Elasticsearch-Schema: 
Mit folgendem Python-Skript erzeuge ich das JSON-File für den Bulk-Import in Elasticsearch. Es werden auch gleich noch die 1:n und m:n Relationen aufgelöst und als »Nested Objects« gespeichert. Die Datei ist zum Schluss ca. 1 GByte groß, mit dem Linux Befehl split (split -l 700000 olap_test.json ./bulk) habe ich dieses dann in kleinere Happen aufgeteilt und mit mehreren Imports (curl -XPOST localhost:9200/_bulk --data-binary @bulkaa) in Elasticsearch importiert. Folgendes Python-Skript zeigt die Abfrage gegen Elasticsearch, die benötigt wird, um die Pivot-Tabelle aufzubauen. Das Skript enthält auch die Query für die Nested Objects. Hierbei sieht man sehr schön, dass diese um einiges komplexer ist. Ich habe auch die Zeiten ausgegeben, die Elasticsearch benötigt. Diese sind beim initialen Aufruf fast gleich. Bei mehrmaligem Aufruf greift der Cache, dann ist die Nested Query um ca. 30% langsamer. Ich habe meinen Elasticsearch-Server in keiner Weise optimiert. Am Ende des Python-Skripts findet sich noch die ausgegebene Tabelle. Das Ergebnis sieht folgendermaßen aus:
+-----------+------------------------------------+-------------+-------------+-------------+
| Land      | Kunde                              | Umsatz 1994 | Umsatz 1995 | Umsatz 1996 |
+-----------+------------------------------------+-------------+-------------+-------------+
| Brazil    |                                    |             |             |             |
|           | Hanari Carnes                      |  232872.00  |  181903.08  |  944863.26  |
|           | Queen Cozinha                      |       0.00  | 2704507.80  | 1017204.30  |
|           | Ricardo Adocicados                 |   79852.56  |  485725.92  |  621214.02  |
|           | Que Delícia                        |   17747.10  |  491754.30  |  105637.50  |
|           | Wellington Importadora             |   26235.66  |  108304.26  |  231125.46  |
|           | Gourmet Lanchonetes                |       0.00  |  521745.96  |   83500.20  |
|           | Familia Arquibaldo                 |    5821.80  |  431282.70  |       0.00  |
|           | Tradição Hipermercados             |    2535.30  |  236947.26  |  276141.12  |
|           | Comércio Mineiro                   |  149676.60  |  146333.76  |   56055.82  |
| Venezuela |                                    |             |             |             |
|           | HILARIÓN-Abastos                   |  153826.98  | 1487469.90  |  720745.36  |
|           | LILA-Supermercado                  |  248947.68  |  576151.62  |  553818.20  |
|           | LINO-Delicateses                   |       0.00  |  834376.62  |  431038.56  |
|           | GROSELLA-Restaurante               |  124492.62  |       0.00  |    2835.78  |
| Mexico    |                                    |             |             |             |
|           | Tortuga Restaurante                |  306696.18  |  448316.16  |  137876.06  |
|           | Antonio Moreno Taquería            |   41316.00  |  353233.02  |  109731.54  |
|           | Pericles Comidas clásicas          |  101787.60  |  286977.18  |  132695.20  |
|           | Ana Trujillo Emparedados y helados |    3023.58  |  104961.42  |   74969.76  |
|           | Centro comercial Moctezuma         |    6103.50  |       0.00  |       0.00  |
| Argentina |                                    |             |             |             |
|           | Cactus Comidas para llevar         |       0.00  |   32339.16  |  104296.86  |
|           | Océano Atlántico Ltda.             |       0.00  |   71270.10  |  504599.82  |
|           | Rancho grande                      |       0.00  |  115290.42  |  296329.62  |
+-----------+------------------------------------+-------------+-------------+-------------+

Fazit

Anhand dieses Beispiels kann man m.E. überaus schön sehen, dass sich mit Elasticsearch auch im Bereich Business Analytics einiges bewerkstelligen lässt. Man muss kein Star-Schema aufsetzen und dieses über nächtliche Aggregationen laden. Ebenso ist das Erlernen von MDX oder eine Einarbeitung in andere BI-Tools nicht notwendig. Besonders interessant wird solch eine Lösung, wenn man noch die Volltextsuche in dieses Szenario integriert. So könnte man beispielsweise nach dem Kundennamen suchen. Bei einem riesigen Kundenkreis ist dies bestimmt schneller als das Filtern in einer Tree-View in einem klassischen BI-Tool. Einige BI-Tools verfügen auch über eine Suche, aber eine Suchmaschine kann hier beispielsweise mit einer Fuzzy-Search (Kundennamen werden dann auch noch mit Schreibfehlern gefunden) noch mehr punkten.

Links 

[1] https://www.rheinwerk-verlag.de/excel-2010-im-controlling_2289/

Freitag, 15. April 2016

Latest jQuery with Grails 2 and the resources plugin

We just updated the front end of an older Grails 2.1.5 application to Bootstrap.

The application uses the resources plugin and due to some other dependencies the jQuery plugin is loaded. The jQuery plugin ships with jQuery 1.11.1 and was not updated since 2014. The latest jQuery version as of now is 2.2.3. So how can we update the javascript library without fiddling with dependency excludes or other hacks?

The resources plugin lets you override single resource files that are loaded in a plugin. The only thing you need is the id of the resource. In this case we have the following definition in the Grails jQuery plugin: The id for the javascript file is 'js'. The new jQuery version was put in web-app/lib/jquery-2.2.3. With the following override in the ApplicationResources.goorvy configuration the latest jQuery version is used everywhere: This is a simple and fast way to override any javascript or css file that is provided by a Grails plugin. The documentation of the resources plugin has some more informations about overrides.

Dienstag, 12. April 2016

RSS Feeds mit Logstash und Elasticsearch durchsuchen

In diesem Blogpost möchte ich aufzeigen, wie man RSS Feeds mit Logstash und Elasticsearch durchsuchen kann. Folgendes Logstash-Skript holt sich alle 2 Stunden Informationen aus der Logistikbranche.
Und folgendes Python-Skript ermöglicht das Dursuchen des RSS-Feeds. Die Elasticsearch-Query liefert keine Dubletten (da ja alle 2 Stunden der RSS-Feed indiziert wird) zurück. Dies wird mit Hilfe einer top_hits Aggregation erreicht.
Und so sieht das Ganze in Aktion aus:
Natürlich kann die Abfrage auch in einer Web-Applikation bereitgestellt werden. Python wurde hier nur zur Veranschaulichung benutzt.

Montag, 21. März 2016

CeBIT 2016

Auf der diesjährigen CeBIT durfte ich einen Vortrag mit dem Thema "Die Suche macht den Unterschied" halten.

Die Präsentation fand im Rahmen der vom Heise-Verlag organisierten developer world statt. Da ich gleich um 10 Uhr die erste Präsentation hatte, dachte ich, dass sich nicht allzu viele Zuhörer einfinden würden. Zum Glück erwies sich dies als Trugschluss und nach den ersten Vortrags-Minuten gingen die Sitzplätze im Auditorium zu Neige und die neu eingetroffenen Hörer mussten sich mit Stehplätzen begnügen.



Was gibt es sonst noch zur CeBIT zu sagen?

Die CeBIT ist nach wie vor ein enormer Besuchermagnet, bei der man alle Altersklassen antrifft, die sich für moderne IT-Technologien interessieren. Erschreckend fand ich dagegen beim Durchschlendern der Hallen, wie beinahe auf jedem Stand die Banner mit den selben Buzzwörtern (IoT, Digitalisierung, ..) versehen waren und zwanghaft die Aufmerksamkeit erringen wollten.


Donnerstag, 10. März 2016

Javaland 2016

Dieses Jahr besuchte ich das erste Mal die Javaland-Konferenz im Phantasialand in Brühl. Die Lokation ist für eine Konferenz natürlich etwas Außergewöhnliches, und spätestens als am ersten Abend die Fahrgeschäfte aufmachten, leuchteten die Augen der Teilnehmer wie bei kleinen Kindern.

Mit meinem Kollegen Ralf Müller durfte ich einen Vortrag zum Thema Testen mit Spock und Geb unter Einbeziehung des Fachbereiches halten. Die Problematik der nachvollziehbaren Tests für den Fachbereich scheint viele Entwickler anzusprechen, da sie offensichtlich ähnliche Probleme haben, wie nachträgliche Diskussionen zeigten.



Die von mir besuchten Sessions auf der Konferenz waren durchweg qualitativ hochwertig. Neben Hype-Themen wie Microservices oder Container, die meiner Wahrnehmung nach aktuell auf jeder Konferenz zu finden sind, gab auch zahlreiche klassische Vorträge zu Java, die einen Besuch wert waren.

Hier ein Auszug meiner gehörten Vorträge:
  • JUnit Lambda - the Next Generation (Jens Schauder)
    Netter Überblick über die Neuerungen in der nächsten JUnit Version. Ich ziehe Spock aber aufgrund der Lesbarkeit nach wie vor jederzeit als Testframework vor.
  • Fun in groovyLand (Dierk König)
    Allergrößten Respekt, dass Dierk die ersten 15 Minuten der Session ohne Beamer auskommen musste, und dies bravourös mit seinem gewohnt angenehmen Vortragsstil meisterte. Anschließend zeigte er einige Szenarien auf wie mit groovy kompakt und doch übersichtlich Code produziert werden kann.
  • Hacking Java (Sean Floyd)
    Der Titel-Name war Programm und es wurden Tricks gezeigt, die ich eigentlich nur in Notfällen anwenden möchte.
  • Mit Vert.x vom Monolithen zum reaktiven Microservice (Jochen Mader)
    Nachdem Jochen zunächst sehr schön auf die Probleme von verteilten Applikationen und damit auch Mikroservices einging, zeigte er auf wie vert.x OutOfTheBox den Übergang von einer monolithischen in eine verteilte Applikation unterstützt.
  • IoT with Apache ActiveMQ, Camel & Spark (Burr Sutter)
    Mit Hilfe von iBeacons, die wir ebenfalls bei unserem letzten ShipIt-Day nutzen, wurden einige IoT-Szenarien aufgezeigt und ich konnte mir Ideen für die Weiterentwicklung unserer eigenen Applikation holen.


Mittwoch, 2. März 2016

Formeln direkt in Confluence berechnen

Seit einiger Zeit steht unsere Firma vor einer großen Herausforderung:
Wieviel Spaghetti müssen für das Mittagessen für die Anzahl der Anwesenden Mitarbeiter gekocht werden?
Nach langer Recherche und einigen mehr oder weniger erfolgreichen Versuchen haben wir beschloßen uns auf folgende Formel festzulegen:
Mit dieser Formel bekommt jeder unserer Mitarbeiter mindestens 125g Spaghetti. Damit die Köche (immer abwechselnd zwei unserer Mitarbeiter) nicht gezwungen sind krumme Mengen abzumessen wird mit der obigen Formel automatisch auf halber 500g Packungen gerundet.
Nun brauchen wir noch eine einfache Möglichkeit, wie man die eigentliche Berechnung ausführen kann. Dazu haben wir die Formel mit einem Eingabe-Feld in unser Confluence-Wiki eingebaut:
Dies ist relativ einfach mit dem HTML Macro möglich. Dieses wird mit Confluence bereits ausgeliefert muss aber extra aktiviert werden. Eine Anleitung dazu gibt es hier.

So können auch andere Berechnungen direkt in Confluence eingefügt werden. Es könnten z.B. Umrechnungen oder Auswertungen von Tabellen vorgenommen werden.

Der gesamte Code für das obige Beispiel ist:
<input type="text" id="spaghetti-persons" name="spaghetti-persons" placeholder="Anzahl Personen"/>
Packungen Spaghetti: <b><span id="spaghetti-result"></span></b>
<script type="application/javascript">
var input = $("input#spaghetti-persons");
input.bind("propertychange change click keyup input paste", function(event) {
 var result = Math.ceil(Number(input.val())/2)/2;
 $("#spaghetti-result").text(result);
});
</script>