jQuery: mehr als nur ein JS-Framework

Seit kurzem beschäftige ich mich auch mit jQuery, welches sich selbst so beschreibt: jQuery is a new type of Javascript library. It is not a huge, bloated, framework promising the best in AJAX – nor is just a set of needlessly complex enhancements – jQuery is designed to change the way that you write Javascript.

Das sind große Worte, aber ich muss ihnen zustimmen. jQuery behandelt natürlich auch AJAX, aber wirklich besonders ist, wie jQuery die Struktur eines Projektes verändern kann – selbst wenn es keinen Gebrauch von AJAX macht.

Java Script kann die Benutzerführung einer Webapplikation erheblich vereinfachen, das Schreiben einer solchen Website aber auch erheblich verkomplizieren. Alleine schon, weil man den JS-Code an vielen Stellen in der Website hinterlegen kann und bei mehreren Seiten die Anzahl der Plätze nur noch vielfältiger wird.

Dann stehen an ziemlich vielen Stellen in der Website die eigentlichen JS-Aufrufe drin, der HTML-Code wird um jede Menge DIVs und IDs angereichert um von JavaScript aus auf die Webelemente zugreifen zu können.

Genau an dieser Stelle greift jQuery ein, wie man an folgendem Beispiel sieht:
$("input.buttonCAdd").click(function(){$("div.contentToChange").find("p").not(".alert")
.append(" This text was just appended to this paragraph")});

Das Beispiel stammt von Cody, auf seiner Seite kann man sich anschauen, was sich tatsächlich mit jQuery anstellen lässt.

Der größte Unterschied zur „normalen“ Verwendung von JavaScript ist bei obigem Beispiel, dass die Aktion, die bei Klick auf einen Button passiert, nicht in der Website selbst definiert wird, sondern unabhängig davon passieren kann. Man kann sich jQuery als eine Art CSS für JavaScript vorstellen. Dadurch lässt sich eine MVC-Trennung des Website-Codes bis auf Ebene des JS herunter durchziehen.

Der Website-Code wird außerdem schlanker, da nicht mehr so viele DIVs und IDs benötigt werden. Zusätzlich kann die Usability der Website für Nutzer ohne JS gesteigert werden, weil der eigentliche Website-Code kein JavaScript mehr enthält. Dadurch ist es einfach schwieriger, Websites zu entwerfen, die nur mit JS einwandfrei funktionieren.

Die AJAX-Funktionalitäten von jQuery habe ich mir dabei noch garnicht angeschaut. Aber damit werde ich in den nächsten Tagen genug zu tun haben :-)

MySQL 5: Trigger sind da!

Für den Counterkram habe ich die Datenbank gestern auf MySQL 5 aktualisiert. Der wichtigste Grund war die Einführung von Triggern. Mit diesem (bei „richtigen“ Datenbanken schon lange vorhandenen) Feature ist es möglich, innerhalb der Datenbank direkt auf SELECT, UPDATE oder INSERT einer Tabell zu reagieren und weitere Aktionen anzustoßen.

Momentan halte ich die Daten für stündliche, tägliche und monatliche Zugriffe auf die einzelnen Blogs in separate Tabellen der gleichen Datenbank fest. Natürlich könnte man auch mit nur einer Tabelle auskommen, nämlich einer, in der die Zugriffe protokolliert werden und mit entsprechenden SUM– und GROUP BY-Spielereien die gewünschten Daten aus dieser einen Tabelle auswerten.

Diese Tabelle wird aber ziemlich schnell sehr groß und damit auch träge, wenn man nicht gerade viel Geld in teure Hardware steckt. Um dieses Problem zu lösen, habe ich mich also für die redundante Speicherung der Daten entschieden. Bevor ich auf MySQL 5 umgestiegen bin, musste ich dies aber auf Applikationsebene machen, was mir nicht besonders gefällt, da es (a) genau für solche Fälle Trigger gibt und (b) die Daten einfach konsistenter sind, wenn die Datenbank sich um die redundante Speicherung kümmert.

Nun kommen also die Trigger ins Spiel. Dafür nehmen wir ein einfaches Beispiel an: In den Logfiles ist der User-Agent schon so aufbereitet, dass nur noch „Internet Explorer“, „Safari„, etc. als Browser angegeben ist. In einer separaten Tabelle soll nun pro Blog eine Statistik der verwendeten Browser abgelegt werden. Dabei interessiert nur die monatliche Verteilung. Die Tabelle tbl_browser_stat hat also die drei Felder blog_id, month, browser und impressions.

Über einen Trigger soll nun bei jeder neuen Zeile in der Tabelle mit den Logfile-Zeilen, die Tabelle tbl_browser_stat aktualisiert werden. Und hier kommt jetzt ein weiteres, kleines Problem ins Spiel: Falls für die Kombination aus Browser und Blog noch kein Eintrag in der Datenbank vorhanden ist, muss ja ein INSERT statt eines UPDATEs gemacht werden. Dafür gibt es in MySQL das Konstrukt INSERT ... ON DUPLICATE KEY UPDATE .... Deer Trigger sieht dann also folgendermaßen aus:

CREATE TRIGGER monthly_browser_stats AFTER INSERT ON tbl_log_rows
    FOR EACH ROW
        INSERT INTO tbl_browser_stats SET blog_id=NEW.blog_id, month=NEW.month, browser=NEW.browser, impressions=1 
        ON DUPLICATE KEY UPDATE impressions=impressions+1;

Auf der Tabelle tbl_browser_stats wurde ein UNIQUE-Key auf die Kombination von blog_id, month und browser angelegt. Von nun an wird die Tabelle automatisch gefüllt und es können sehr einfach die Verteilung der Zugriffe bestimmter Browser auf einzelne oder alle Blogs abgefragt werden. Die Applikation wird von mir in den nächsten Tagen schrittweise von diesem Ballast befreit, neue Statistiken können dann fast ausschließlich über neue Trigger realisiert werden.

Linux New Media Award für PostgreSQL

Die Linux New Media AG hat am Abend des 27. Oktober die Gewinner des diesjährigen Media Award bekannt gegeben.
[…]
Das beste Datenbanksystem ist laut Linux New Media das freie RDBMS PostgreSQL.
[…]
Details über die einzelnen Gewinner, die exakten Stimmverteilungen, die Nächstplatzierten und die Jury erfahren alle Interessenten in laufe des Tages auf der Webseite der Linux New Media AG.

[via Pro-Linux.de]

Leider fehlen die Informationen auf den Webseiten der Linux New Media AG. Die Begründung für PostgreSQL würde mich doch interessieren. Es waren ja einige weitere Datenbanken nominiert.

Flickr and MySQL

In the following presentation, the overall system design of flickr.com is described:
http://www.niallkennedy.com/blog/uploads/flickr_php.pdf

Especially Page 27 raised my attention, as I encountered that kind of thinking around MySQL users a lot. As I’m just turning von MySQL to PostgreSQL, I’m curious what people which are using „real“ databases saying about the following statements on that sheet:
– JOIN’s are slow
– Normalised data is for sissies
– Keep multiple copies of data around
– Makes searching faster
– Have to ensure consistence in the application logic

That last item frightens me most, as I know from my own experiences, that this is a very difficult task. I currently prefer a clean database design with aggregation of data done by triggers.

All the others things in that presentation do not sound like magic. It’s quite normal to move SELECT statements to a read only copy of the database to avoid too much requests to the main database. Especially for some MySQL table types this is a major issue as MySQL only supports table locking on those types (all except InnoDB and BDB). Flickr uses both types (row and table locking) and seems to do SELECTs only on the table locking. So this is no problem for them. But all this shows how you have to design your system around MySQL. I no longer feel good about this, as there is no other database behaving like MySQL but with better (in term of more professional) quality. I hope to have a possible upgrade path from PostgreSQL to DB2 or Oracle – without currently knowing. So if you have to share your opinion, leave a comment.

Unfortunately, the numbers on page 22 of this presentation are not further specified. So you cannot tell in what period of time they take place:
– 44,220,588 SELECTS
– 1,349,234 INSERTS
– 1,755,503 UPDATES

Nice to see, flickr.com is not much more than a bigger one-person-project, at least only one programmer… (Page 7).

[via Lummaland]

CSS-Effekte

Wer einen entsprechenden Browser hat, wird es schon bemerkt haben: Links werden jetzt nur noch angezeigt, wenn man sich mit der Maus in dem entsprechenden Beitrag befindet. Gefunden habe ich das hier nachdem ich den Hinweis bei wurch.log gelesen hatte.
Das jetzige Blau empfinde ich noch als etwas grell, aber vielleicht muss ich mich noch daran gewöhnen; vielleicht finde ich aber noch eine bessere Farbkombination.