Warum Google sein Geld besser anlegen kann als für Twitter

[Kommentar] Das Gerücht ist alt, bekommt heute aber wieder neue Nahrung: Google soll Interesse an dem Kurznachrichtendienst Twitter haben. Um eine fremde Übernahme abzuwehren, hat Twitter angeblich entsprechende Finanzexperten engagiert. Wie wahrscheinlich ist Googles Interesse? Bei näherem Hinsehen macht eine Übernahme nicht wirklich Sinn.

Unter anderem das Handelsblatt vermutet heute hinter einerm Übernahmeversuch den Suchgiganten aus Kalifornien (http://www.handelsblatt.com/finanzen/maerkte/aktien/neue-uebernahmegeruechte-greift-google-nach-twitter/11607568.html). Hintergrund sei der Versuch, Google+ neues Leben einzuhauchen. Das soziale Netzwerk des Suchmaschinenbetreibers hat derzeit einen großen Wandel zu verkraften. Bradley Horowitz, der nach dem Ausscheiden seines Vorgängers gerade die Verantwortung für Google+ übernommen hat, nimmt es gerade in seine Bestandteile wie Stream und Photos auseinander. Kent Walker, Anwalt des Unternehmens, führt Google+ sogar als Beispiel ins Felde, wenn es darum geht, Miserfolge des Konzerns zur Abwendung einer Wettbewerbsklage aufzuzählen.

Hilfe hätte Google+ also bitter nötig – sofern das Netzwerk noch als solches fortgeführt wird.

Twitter hat eine aktive Nutzerbasis, 280 Millionen, und die Zahlen steigen sogar noch. Aber das Wachstum lässt nach (http://blogs.wsj.com/digits/2015/02/05/twitters-user-growth-falls-below-facebooks-for-the-first-time/), die besten Zeiten für das Kerngeschäft scheinen auch vorüber. Hinzu kommt, dass Twitter und Google+ sich wohl einen beträchtlichen Anteil der Nutzer teilen. Beim Aufbau einer postwütigen Nutzerschaft scheint der Kurznachrichtendienst also kein guter Kandidat.

Auch die Aussicht auf die Tweet-Daten macht das Interesse von Google unwahrscheinlich. Es gab bereits mehrfach Abkommen zwischen den beiden Konzernen, so dass die Tweets in Echtzeit in den Suchergebnissen erscheinen. Aber dieses Abkommen ist gerade erst erneuert worden (http://www.bloomberg.com/news/articles/2015-02-05/twitter-said-to-reach-deal-for-tweets-in-google-search-results). Wozu also sollte Google noch mehr Geld ausgeben für eine Firma ausgeben, wenn man dessen kostbarsten Schatz schon im Zugriff hat.

Jedoch sticht Twitter derzeit in neue Geschäftsfelder vor. Die Zukunft liegt in Videos, heißt es. Und so baut Twitter an einem Videodienst, der in Konkurrenz zu Youtube treten könnte. Hinzu der Hype um den Livestreamingdienst Periscope. Darauf könnte Google es abgesehen haben: Einen Konkurrenten auszuschalten, bevor sich Erfolg einstellt.

Kommen wir zum Finanziellen: Die Marktkapitalisierung von Twitter liegt bei etwas mehr als 30 Milliarden Dollar. Selbst ohne einen Preisaufschlag müsste Google also tief in die Tasche greifen. Zum Vergleich: Facebook hat sich den Messenger Whatsapp mit seinen 600 Millionen Usern knapp 22 Milliarden Dollar (!) kosten lassen. Da wird sich doch etwas finden lassen, was Google weiter voran bringt.

Advertisements

Was Google Werbekunden wert sind

Wir wissen es alle. Und jede Pressekonferenz zum Quartalsergebnis führt es uns wieder vor Augen: Werbung ist das Brot- und Buttergeschäft von Google. Nicht mit einer Suchmaschine wird man reich, auch nicht mit einem sozialen Netzwerk oder Tabellenkalkulation oder Emaildiensten oder, oder, oder. Mit Werbung macht man Geld, die heißgeliebten Services, die ich vorher aufgezählt habe und zu denen sich noch so viele andere gesellen, sind nur das Mittel, um die Werbung an den Mann zu bringen. Besser noch, der Kunde kommt ganz von alleine, solange man ihm die Services kostenlos vor die Füße wirft. Der Kunde holt sich die Werbung quasi selber ab.

Und da verwundert es auch nicht, dass man nie mit Google Mitarbeitern direkt in Berührung kommt. Während andere Unternehmen Werbefiguren erfinden, damit Marcel D’Avis z.B. jedem aktuellen und zukünftigen 1&1 Kunden alle Fragen beantworten kann, herrscht beim Internetgiganten das Motto vor, jeder Kunde nimmt sich einfach soviel er tragen kann.

Werbetreibende investieren dort, wo sie ihre Kunden vermeindlich erreichen

Dass jeder einzelne Kunde mit der Aufgabe seiner Privatsphäre bezahlt, ist hinlänglich bekannt. Die Aktualisierung der Datenschutzerklärung, die die Zusammenführung der Profildaten aller Google Services ermöglicht, ist nur eines der Beispiele. Jahrelang konnte man sich an die Google Services gewöhnen. Erst hat man die Suchmaschine so ausgiebig genutzt, dass sich das Wort „googeln“ im deutschen Sprachgebrauch synonym für „suchen im Internet“ etabliert hat. Mit jeder Suchanfrage erfährt der US-Konzern damit, welche Themen gerade „heiß“ sind. Sofern der Suchende eingeloggt ist, lässt sich über die Zeit ein lückenloses Webprotokoll bzw. Interessenprofil erstellen. Es folgten Maps, Youtube, GMail und Google+. In Summe weiß Google, wo sich bevorzugte Restaurants und Hotels befinden, welche Musik oder Videos man toll findet, welchen Leuten man Emails schreibt und dank des sozialen Netzwerks auch Geschlecht, Alter und Wohnort.

Das Problem aber bleibt: Wissen macht die Kuh nicht fett, harte Währung kann man nur verdienen, wenn man dieses Wissen ausnutzt und Werbung schaltet. Das Wissen über den Nutzer dient allein dazu, Werbetreibenden das glaubwürdige Versprechen geben zu können, dass die eigene Anzeige genau den Nutzer erreicht, der das Beworbene zu kaufen bereit ist. Und dafür kassiert Google.

Jedes werbetreibende Schäfchen ins Trockene bringen

Damit die Geldquelle nicht versiegt, kümmert man sich um jeden einzelnen Werbetreibenden. Das erfährt man am einfachsten, wenn man sich bei Google Adwords anmeldet und nach der Registrierung nicht sofort eine Werbekampagne schaltet. Das ist mir eher zufällig widerfahren. In einer Computerzeitschrift prangte Anfang des Jahres ein 75 Euro Gutschein für Onlinewerbung. Das konnte ich mir als Betreiber eigener Webseiten nicht entgehen lassen. Letztlich hielt mich aber meine eigene Faulheit und die Tatsache von meiner ersten Kampagne ab, dass ich mir bis zum Ende nicht sicher war, wo ich meinen Gutscheincode hätte eingeben müssen.

So bleibt mein Konto bislang unbenutzt. Das will Google offenbar aber nicht hinnehmen. Schon einige Tage nach meiner Adwords Registrierung bekam ich per Mail die erste Erinnerung: Online-Werbung ist jetzt noch einfacher und schneller. Um meine Motivation für einen erneuten Anlauf zu steigern, lag der Mail ein 50 Euro Gutschein bei.

Zu einem persönlichen Gespräch eingeladen wurde ich nach zwei weiteren Tagen resoluten Schweigens. Eine nett klingende Mitarbeiterin eines Dienstleistungsunternehmens, das für Google tätig ist, möchte sich telefonisch mit mir unterhalten. Sie ist Adwords Spezialistin und möchte mir bei meinen ersten Schritten helfen, Google mit zu finanzieren…

Update: sich selber nicht so wichtig nehmen

Nachdem ich von dem Angebot eines Telefongesprächs auch keinen Gebrauch gemacht habe, scheint Google mitsamt Dienstleistern vorerst das Interesse an mir verloren zu haben. So wichtig scheine ich für die Bilanz des Internetriesen doch nicht zu sein. Stattdessen meldet sich aber höflich der Personalchef der nett klingenden Dienstleistermitarbeiterin mit der Bitte, ihren Namen aus meinem Blog zu entfernen. Zwei Dinge dazu: 1. ich wollte mit diesem Blogpost niemanden diffamieren oder anprangern. Und 2. scheinbar gibt es doch Leute, die mein Blog lesen. Vielleicht lohnt es sich doch, hier Werbung zu schalten.

 

CouchDB reif für die Produktion

Die Freigabe der Version 0.11.0 markiert den Meilenstein zur Produktionsreife von CouchDB. Das Release wird als „feature-freeze“ bezeichnet und ist als Release Candidate für die anstehende Version 1.0 zu verstehen.

Damit tut neben MongoDB ein zweiter NoSQL Vertreter Ende März einen weiteren Schritt Richtung Produktion. MongoDB 1.4 kam am 26.03.2010.

Der Download von CouchDB 0.11.0 steht für Unix im Apache Incubator unter http://couchdb.apache.org/downloads.html zur Verfügung und ist unter der Apache License 2.0 zu haben. Das Installationspaket für Windows ist zwar etwas versteckt, findet sich wie sein Vorgänger aber hier – die Lizenz ist selbstverständlich die gleiche.

TaffyDB Performance Testreihe

Mit der erfolgreichen Anwendung des Höher-schneller-weiter-Paradigmas auf JavaScript steigen auch die Begehrlichkeiten an die Implementierungen von Browserengine und Libraries. In einem vorigen Post habe ich eine Einführung in TaffyDB gegeben, eine clientseitge Datenhaltung für JavaScript. Um die Speicherung im Browser erfolgreich nutzen zu können, ist ausreichende Performance unerlässlich, weshalb ich die Library im Nachgang einer Reihe von Performancetests unterzog. Als Grundlage habe ich der Einfachheit halber das mitgelieferte Skript tests/speedtest.htm aus dem TaffyDB Quellcode benutzt und es mit steigender Anzahl von Records mehrfach durchlaufen lassen (ceteris paribus). Die Ergebnisse sind in nachfolgender Tabelle zusammengefasst (Angaben in Millisekunden) – grafisch dargestellt in Abbildung 1 .

Anzahl Datensätze Create and Fill Taffy Do 80% record remove via lookup Do a forEach Update Find Every Record Find Record x Sort by Value Desc RAM (in MB)
1000 17 20,6 46,6 14,4 3 37,2 12
2000 33,2 56,8 96,2 46,2 6,8 84,6 9
3000 48,6 113,2 145 99,8 10 132,8 10
4000 69,2 184,2 218 225 13,8 180,2 11
5000 83,8 324 238,4 262,2 17,8 239,8 12
6000 102,6 431,8 278,4 375,4 20,8 276 14
7000 118,6 508,2 438 551 24,2 328,2 16
8000 132,2 1367 380,8 660,4 27,4 383,8 18
9000 147,8 1175 618,6 823,8 31,4 436 19
10000 165 1001,4 662,8 1051,8 34,4 557 18

Wie zu sehen ist, skaliert TaffyDB sehr gut. Weitergehende Tests zeigen, dass dies auch mit größeren Datenmengen der Fall ist. Dabei ergeben sich jedoch Warnmeldungen des Browsers, dass ein ausgeführtes Skript nicht antwortet (siehe Abbildung 2). Einen Workaround bietet die setTimeout Funktion, die von Nicholas Zakas auf dessen Webseite sehr anschaulich und hintergründig erklärt wird. Da der Einbau des Workarounds die Aussage der dann durchgeführten Tests verändert, sind hier keine weiteren Ergebnisse aufgeführt.

MySQL Performance bei INNER Join vs. OUTER Join

Bei der Universenerstellung mit Business Object kam neulich die Frage nach dem Performancetuning auf, speziell in Bezug auf die verwendeten Joins. Zitat meines BO-erfahrenen Kollegen war: „Die Datenbank freut sich jedes Mal, wenn sie einen INNER Join statt OUTER Join machen darf.“.  Eine Google-Suche zu dem Thema ergab wenig quantifizierbare, valide Ergebnisse, also habe ich zuhause eine eigene Testreihe gestartet.

Mein Setup:

  • MySQL 5.4.2 Beta
  • Employees Datenbank, mit vervielfachter employees-Tabelle auf 10 Millionen Datensätze

Als Testabfrage dient ein Self-Join der Tabelle employees, der für OUTER und INNER Joins jeweils an fett gedruckter Stelle angepasst wird:

SELECT o.first_name, i.last_name
FROM employees o
{LEFT OUTER | INNER} JOIN employees i ON o.emp_no = i.emp_no
WHERE o.last_name =  'Sichman';

Die WHERE Klausel ist lediglich eingebaut, um die Ergebnismenge zu verkleinern. Als Ergebnis zeigt sich, dass der INNER Join in diesem Fall deutlich schneller ist (Durchschnittswerte nach 10 Iterationen mit FLUSH Statements, Angaben in Sekunden):

Jointyp Zeit in Sekunden
INNER JOIN 4.20
OUTER JOIN 12.17

By the way: Der Teufel steckt hier wie auch in obigem Business Objects Fall im Detail. Zeigt die WHERE Klausel auf die i-Tabelle, wird der Vorteil des INNER Join gegenüber dem OUTER Join dadurch zunichte gemacht – beide Anfragen haben fast identische Laufzeiten von über einer Minute.

TaffyDB und serverseitige Daten synchronisieren

TaffyDB zeigt, wo die Reise hingeht: Mit der JavaScript Schnittstelle wird die Datenhaltung von Web-Applikationen in den Browser gehievt. Wer auf die serverseitige Speicherung nicht verzichten kann oder will, bekommt hier einen Eindruck, wie leicht TaffyDB mit jQuery zusammen als Datenbank-Interface für relationale Datenbanken werden kann.

TaffyDB ist eine CRUD (Create, Read, Update, Delete) Schnittstelle, die JavaScript Objekte zu Kollektionen zusammenfasst und sie komfortabel verwalten und durchsuchen lässt. Die Operationen erinnern namentlich stark an SQL, so dass die Einarbeitungszeit für altgediente Freunde relationaler Datenbanken auf ein Nichts minimiert. Die Daten sind flüchtig, also verloren, sobald die aktuelle Seite neu geladen oder verlassen wird. Dauerhafte Speicherung erzeugt man nur mit entsprechendem Zusatz, etwa Google Gears und/oder der Übertragung in eine Datenbank auf dem Server (z.B. MySQL oder CouchDB).

Eben diese Anbindung an eine – in diesem Beispiel – relationale Datenbank, erreicht man mit einer Handvoll Ajax und vordefinierten Hooks in TaffyDB selbst in Form von drei Methoden, die auf die Ereignisse Insert, Update und Remove reagieren. Den Ajax-Teil realisieren wir in jQuery, jedes vergleichbare JavaScript Bibliothek erledigt dies auf gleich einfache Weise. Im Beispiel sieht das wie folgt aus:


<script src="jquery-1.3.2.min.js" type="text/javascript"></script>
<script src="taffy-min.js" type="text/javascript"></script>
<script type="text/javascript"><!--
var records = new TAFFY([])
records.onInsert = function (r) {
jQuery.ajax({
type: "POST",
url: "save.php",
data: "action=insert&b="+r.a,
success: function(msg){
alert( "Data Saved: " + msg );
}
});
};
records.onRemove = function (r) {
jQuery.ajax({
type: "POST",
url: "save.php",
data: "action=remove&b="+r.a,
success: function(msg){
alert( "Data deleted: " + msg );
}
});
};
// --></script>
Daten:
<input id="d" maxlength="30" name="d" size="30" type="text" value="zyx" />
<input onclick="records.insert({a:document.getElementById("d").value})" name="add" type="button" value="add" />
<input onclick="records.remove({a:document.getElementById("d").value})" name="remove" type="button" value="remove" />
<input onclick="records.forEach(function (f,n) {alert(f.a)});" name="show" type="button" value="show" />

Im JavaScript Teil definieren wir zuerst eine leere Kollektion durch die Instanziierung der Klasse TAFFY. Die Kollektion dient uns als Sammelbecken für Daten, die wir gemeinsam vorhalten und beispielsweise durchsuchen wollen – im relationalen Denkbild entspricht dies einer Tabelle. An dieser Stelle lassen sich schon Objekte vordefinieren, die im Folgenden jedoch nicht mit synchronisiert werden. Darüber hinaus belegen wir die Hooks zum Einfügen (onInsert) und Löschen (onRemove) mit Ajax Aufrufen. Damit werden Änderungen an der Kollektion Datensatz für Datensatz mit dem Bestand auf dem Server synchronisiert – namentlich durch Verarbeitung des Datensatzes im Skript save.php. Pro forma quittieren wir jede erfolgreiche Synchronisierung mit einem alert().

Der HTML Teil besteht aus einem Eingabefeld und drei Knöpfen, die den Inhalt des Textfeldes als Objekt an die Taffy Kollektion anhängen oder daraus entfernen. Der letzte Knopf gibt uns nach und nach alle Objekte der Kollektion aus.

Beim Drücken des add-Knopfes wird die Methode insert der Kollektion aufgerufen. Dies erweitert die Kollektion und sorgt für den Aufruf des Hooks onInsert, der die Daten darüber hinaus zum Server schickt. Der remove Knopf reagiert analog. Sicherheit der Synchronisation wird mit dieser einfachen Version des Skriptes nicht erreicht!

Serverseitig muss die Verarbeitung der Daten, die als POST Parameter daherkommen, durch das Skript save.php geschehen, die im Folgenden dargestellt ist.

< ?php
if($_POST['b'] != ""){
$fehler = "";
$sqldb = new SQLiteDatabase('test.sqlite2', 0666, $fehler);
if($_POST['action'] == "insert"){
$sqldb->queryExec("INSERT INTO d (b) VALUES ('".$_POST['b']."');", $fehler);
} elseif ($_POST['action'] == "remove"){
$sqldb->queryExec("DELETE FROM d WHERE b='".$_POST['b']."';", $fehler);
}
echo $_POST['b'];
}?>

Der Einfachheit halber werden Daten in einer SQLite v2 Datenbank hinterlegt. Je nach Ausprägung des Parameters action wird der (nicht leere) String b in die Datenbank eingefügt oder daraus gelöscht. Das Löschen beachtet dabei nicht, dass ein gleichlautender String vorab in der Tabelle vorhanden sein kann. Beim Löschen eines der Datensätze würden beide entfernt werden.