<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>ebene7 &#187; Datenbank</title>
	<atom:link href="http://blog.ebene7.com/schlagwort/datenbank/feed/" rel="self" type="application/rss+xml" />
	<link>https://blog.ebene7.com</link>
	<description></description>
	<lastBuildDate>Tue, 04 Jun 2013 18:57:27 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.2.1</generator>
		<item>
		<title>MySQL: Datenbank kopieren</title>
		<link>https://blog.ebene7.com/2013/02/05/mysql-datenbank-kopieren/</link>
		<comments>https://blog.ebene7.com/2013/02/05/mysql-datenbank-kopieren/#comments</comments>
		<pubDate>Tue, 05 Feb 2013 13:00:22 +0000</pubDate>
		<dc:creator>Daniel</dc:creator>
				<category><![CDATA[Datenbank]]></category>
		<category><![CDATA[Tipps und Tricks]]></category>
		<category><![CDATA[kopieren]]></category>
		<category><![CDATA[MySQL]]></category>

		<guid isPermaLink="false">http://blog.ebene7.com/?p=4005</guid>
		<description><![CDATA[Bestehende Datenbank in Datei schreiben: mysqldump datenbank_orig &#62; datenbank_orig.sql -ubenutzername -p Neue Datenbank aus Datei befüllen: mysql -ubenutzername -p datenbank_kopie &#60; datenbank_orig.sql]]></description>
			<content:encoded><![CDATA[<p>Bestehende Datenbank in Datei schreiben:</p>
<pre>mysqldump datenbank_orig &gt; datenbank_orig.sql -ubenutzername -p</pre>
<p>Neue Datenbank aus Datei befüllen:</p>
<pre>mysql -ubenutzername -p datenbank_kopie &lt; datenbank_orig.sql</pre>
]]></content:encoded>
			<wfw:commentRss>https://blog.ebene7.com/2013/02/05/mysql-datenbank-kopieren/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>MySQL: Doppelte Datensätze löschen</title>
		<link>https://blog.ebene7.com/2011/01/12/mysql-doppelte-datensaetze-loeschen/</link>
		<comments>https://blog.ebene7.com/2011/01/12/mysql-doppelte-datensaetze-loeschen/#comments</comments>
		<pubDate>Wed, 12 Jan 2011 05:00:20 +0000</pubDate>
		<dc:creator>Daniel</dc:creator>
				<category><![CDATA[Datenbank]]></category>
		<category><![CDATA[Snippets]]></category>
		<category><![CDATA[Duplikat]]></category>
		<category><![CDATA[Löschen]]></category>
		<category><![CDATA[MySQL]]></category>
		<category><![CDATA[Query]]></category>
		<category><![CDATA[Selbstreferenz]]></category>

		<guid isPermaLink="false">http://blog.ebene7.com/?p=2552</guid>
		<description><![CDATA[Hin und wieder kann es vorkommen, dass sich Datensätze ungewollt doppelt in der Datenbank wiederfinden. Hier ein kleiner Spickzettel, wie sich die Doubletten wieder entfernen lassen. Die Struktur der Testtabelle sieht folgendermaßen aus: CREATE TABLE `sqltest`.`duplicates` ( `id` INT(11) UNSIGNED &#8230; <a href="https://blog.ebene7.com/2011/01/12/mysql-doppelte-datensaetze-loeschen/">Weiterlesen <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Hin und wieder kann es vorkommen, dass sich Datensätze ungewollt doppelt in der Datenbank wiederfinden.</p>
<p>Hier ein kleiner Spickzettel, wie sich die Doubletten wieder entfernen lassen.</p>
<p><span id="more-2552"></span>Die Struktur der Testtabelle sieht folgendermaßen aus:</p>
<pre><code>CREATE TABLE `sqltest`.`duplicates` (
  `id` INT(11) UNSIGNED NOT NULL AUTO_INCREMENT,
  `a` VARCHAR(10) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,
  `b` INT(11) NOT NULL ,
  `c` DATETIME NOT NULL ,
PRIMARY KEY (`id`)
) ENGINE = InnoDB CHARACTER SET utf8 COLLATE utf8_general_ci;</code></pre>
<p>Noch ein paar Daten rein und fertig ist die Spielwiese.</p>
<pre>mysql&gt; select * from duplicates;
+----+--------+-----+---------------------+
| id | a      | b   | c                   |
+----+--------+-----+---------------------+
|  1 | Apfel  | 123 | 2011-01-11 17:00:00 |
|  2 | Apfel  | 123 | 2011-01-11 17:00:00 |
|  3 | Banane | 234 | 2011-01-12 17:00:00 |
|  4 | Banane | 234 | 2011-01-12 17:00:00 |
|  5 | Birne  | 456 | 2011-01-15 17:00:00 |
|  6 | Birne  | 456 | 2011-01-15 17:00:00 |
+----+--------+-----+---------------------+
6 rows in set (0.00 sec)</pre>
<p>Die erste Abfrage macht einen JOIN auf sich selbst, dafür die Aliasse d1 und d2 und dient zunächst der Prüfung, ob wir die gewünschten Datensätze geliefert bekommen.</p>
<pre>SELECT d1.* FROM duplicates d1, duplicates d2
 WHERE d1.id != d2.id
   AND d1.a = d2.a
   AND d1.b = d2.b
   AND d1.c = d2.c
   AND d1.id &lt; d2.id</pre>
<p>Das Ergebnis:</p>
<pre>+----+--------+-----+---------------------+
| id | a      | b   | c                   |
+----+--------+-----+---------------------+
|  1 | Apfel  | 123 | 2011-01-11 17:00:00 |
|  3 | Banane | 234 | 2011-01-12 17:00:00 |
|  5 | Birne  | 456 | 2011-01-15 17:00:00 |
+----+--------+-----+---------------------+
3 rows in set (0.00 sec)</pre>
<p>MySQL kann offensichtlich keine Daten löschen, wenn die Löschaktion auf derselben Tabelle wie die Subquery gemacht wird. Darum schreiben wir die Ids in eine temporäre Tabelle.</p>
<pre>CREATE TABLE duplicates_ids AS (
  SELECT d2.id FROM duplicates d1, duplicates d2
   WHERE d1.id != d2.id
     AND d1.a = d2.a
     AND d1.b = d2.b
     AND d1.c = d2.c
     AND d1.id &lt; d2.id
)</pre>
<p>Im letzten Schritt löschen wir die zuvor ausgewählten Datensätze und auch die temporäre Tabelle. Je nachdem was wir behalten wollen, noch ggf. ein &#8220;NOT&#8221; vor das &#8220;IN&#8221; schreiben.</p>
<pre>DELETE FROM duplicates WHERE id [NOT] IN (SELECT * FROM duplicates_ids);
DROP TABLE duplicates_ids;</pre>
<p>Achtung! Ich hafte nicht bei Datenverlust oder sonstigen Fehlern. Ein Backup sollte sicherheitshalber vorher gemacht werden.</p>
]]></content:encoded>
			<wfw:commentRss>https://blog.ebene7.com/2011/01/12/mysql-doppelte-datensaetze-loeschen/feed/</wfw:commentRss>
		<slash:comments>10</slash:comments>
		</item>
		<item>
		<title>Faule Models und große Datenmengen</title>
		<link>https://blog.ebene7.com/2010/12/13/faule-models-und-grosse-datenmengen/</link>
		<comments>https://blog.ebene7.com/2010/12/13/faule-models-und-grosse-datenmengen/#comments</comments>
		<pubDate>Mon, 13 Dec 2010 05:00:46 +0000</pubDate>
		<dc:creator>Daniel</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[CustomLibrary]]></category>
		<category><![CDATA[Custom_Model]]></category>
		<category><![CDATA[Data Mapper]]></category>
		<category><![CDATA[Datenbank]]></category>
		<category><![CDATA[Entwurfsmuster]]></category>
		<category><![CDATA[Magento]]></category>
		<category><![CDATA[Model]]></category>
		<category><![CDATA[MVC]]></category>
		<category><![CDATA[OOP]]></category>

		<guid isPermaLink="false">http://blog.ebene7.com/?p=1536</guid>
		<description><![CDATA[Unter verschiedenen Umständen kann es vorteilhaft sein, wenn Models nicht vollständig geladen und mit Daten befüllt werden, weil das Lesen zu komplex ist (Stichwort EAV-Model) oder wir mit sehr vielen Datensätzen arbeiten und dabei Speicherplatz sparen wollen/müssen. Gleichzeitig wollen wir &#8230; <a href="https://blog.ebene7.com/2010/12/13/faule-models-und-grosse-datenmengen/">Weiterlesen <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Unter verschiedenen Umständen kann es vorteilhaft sein, wenn Models nicht vollständig geladen und mit Daten befüllt werden, weil das Lesen zu komplex ist (Stichwort EAV-Model) oder wir mit sehr vielen Datensätzen arbeiten und dabei Speicherplatz sparen wollen/müssen.</p>
<p>Gleichzeitig wollen wir aber zu jeder Zeit sicherstellen, dass wir das Model wie gewohnt vollständig abfragen und verwenden können. An dieser Stelle kommt eine Technik namens LazyLoading (lazy = engl. faul, träge) zum Einsatz.</p>
<p><span id="more-1536"></span></p>
<p>Nun konstruiere ich einfach ein Beispiel, um den Ablauf besser erklären zu können. In unserer Anwendung brauchen wir ein Model &#8220;Person&#8221;, das Informationen wie Name, Geburtstag und diverse andere speichern kann. Den Namen und den Geburtstag brauchen wir immer (z.B. in der Listenansicht) und die restlichen Felder nur wenn wir eine Detailansicht erstellen.</p>
<p>Wie kommt unser Model nun an die Daten? In der Regel wird sicherlich load() auf dem Modelobjekt aufgerufen oder eine vergleichbare Methode auf der jeweiligen Collection, dann werden die Daten über ein Resourcemodel geladen und letztendlich komplett auf die einzelnen Modelobjekte kopiert.</p>
<p>Um unser Vorhaben umzusetzen müssen wir das etwas abändern. Die Methode load() des Models funktioniert wie gewohnt und lädt alle Daten und die Collection nur die Nötigsten. Um nun sicherzustellen, dass wir trotzdem immer alles abrufen können, muss das Model etwas intelligenter werden.</p>
<p>Die Entwicklung des <a href="http://blog.ebene7.com/schlagwort/custom_model/" target="_self">Custom_Model</a>s hat der eine oder andere ja vielleicht mitbekommen und kennt den grundlegenden Aufbau. Relativ neu ist die Klasse Custom_Model_Persistent, durch die eine weitere Unterscheidung zwischen einfachen Datencontainern und speicherbaren Models möglich wird.</p>
<p>Für das automatische Nachladen muss die Modelklasse nun erweitert werden.</p>
<pre>&lt;?php
class Custom_Model_Persistent extends Custom_Model
{
  private $_isLoaded;

  // ...

  public function load($value = null, $field = 'id')
  {
    if (null === $value &amp;&amp; $this-&gt;_isset($field)) {
      $value = $this-&gt;_get($field);
    }

    $this-&gt;getResource()
         -&gt;loadModel($this, $value, $this-&gt;_mapKey($field))
         -&gt;markLoaded();

    return $this;
  }

  public function isLoaded()
  {
    return $this-&gt;_isLoaded;
  }

  public function markLoaded()
  {
    $this-&gt;_isLoaded = true;
    return $this;
  }

  protected function _get($key, $default = null)
  {
    if (!$this-&gt;_isset($key) &amp;&amp; !$this-&gt;isLoaded()) {
      $this-&gt;load();
    }
    return parent::_get($key, $default);
  }
}</pre>
<p>Die entscheidenen Stellen sind hier der überschriebene zentrale Getter, der ein das &#8220;Default-Load()&#8221; auslöst, wenn der Wert nicht gesetzt ist und die Daten auch noch nicht vollständig geladen wurden und die Methode load() mit optionalen Parameter $value.</p>
<p>Im Beispiel verlasse ich mich darauf, dass das Standardfeld schon gesetzt ist. Eine ordentliche Fehlerbehandlung muss aber unbedingt her, wenn wir das ganze produktiv einsetzen wollen.</p>
<p>Die Methoden isLoaded() bzw markLoaded() sind absichtlich public, damit sie z.B. aus einer Collection aufgerufen werden können, wenn das Model komplett geladen wurde. Eine weitere Möglichkeit wäre ein Vergleich mit einer Liste die gesetzt sein sollten.</p>
<p>Im Moment ist das noch etwas im Entwurf und sogar ungetestet. Wenn euch nun noch was dazu einfällt, dann schreibt einen Kommentar. Wo seht ihr für euch die Vor- oder evtl. auch die Nachteile?</p>
]]></content:encoded>
			<wfw:commentRss>https://blog.ebene7.com/2010/12/13/faule-models-und-grosse-datenmengen/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Aufzählungen mit GROUP_CONCAT()</title>
		<link>https://blog.ebene7.com/2010/11/02/aufzaehlungen-mit-group-concat/</link>
		<comments>https://blog.ebene7.com/2010/11/02/aufzaehlungen-mit-group-concat/#comments</comments>
		<pubDate>Tue, 02 Nov 2010 05:00:13 +0000</pubDate>
		<dc:creator>Daniel</dc:creator>
				<category><![CDATA[Datenbank]]></category>
		<category><![CDATA[Snippets]]></category>
		<category><![CDATA[Formatierung]]></category>
		<category><![CDATA[Funktion]]></category>
		<category><![CDATA[MySQL]]></category>

		<guid isPermaLink="false">http://blog.ebene7.com/?p=2159</guid>
		<description><![CDATA[Für verschiedene Anwendungsfälle ist es übersichtlicher, wenn 1:n Beziehungen als Aufzählung angezeigt werden. Für dieses Beispiel verwende ich eine kleine, übersichtliche Tabelle mit Emailadressen und deren Aliase. CREATE TABLE `mails` ( `id` int(11) NOT NULL auto_increment, `parent_id` int(11) NOT NULL, &#8230; <a href="https://blog.ebene7.com/2010/11/02/aufzaehlungen-mit-group-concat/">Weiterlesen <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Für verschiedene Anwendungsfälle ist es übersichtlicher, wenn 1:n Beziehungen als Aufzählung angezeigt werden. Für dieses Beispiel verwende ich eine kleine, übersichtliche Tabelle mit Emailadressen und deren Aliase.<span id="more-2159"></span></p>
<pre>CREATE TABLE `mails` (
  `id` int(11) NOT NULL auto_increment,
  `parent_id` int(11) NOT NULL,
  `addy` varchar(255) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8</pre>
<p>Jede Emailadresse hat eine Id und eine ParentId. Sind beide Ids identisch, dann ist es die Originaladresse, ansonsten ein Alias.</p>
<pre>mysql&gt; select * from mails;
+----+-----------+------------------+
| id | parent_id | addy             |
+----+-----------+------------------+
|  1 |         1 | m1@example.com   |
|  2 |         1 | a1m1@example.com |
|  3 |         3 | m2@example.com   |
|  4 |         1 | a2m1@example.com |
|  5 |         3 | a1m2@example.com |
+----+-----------+------------------+
5 rows in set (0.00 sec)
</pre>
<p>Mit einem selbstreferenzierenden Join werden die Daten nun wieder aus der Tabelle ausgelesen. Dabei wird die Tabelle &#8216;mails&#8217; durch Aliasnamen wie zwei Tabellen behandelt. Wir selektieren die &#8216;addy&#8217; aus der Tabelle &#8216;m1&#8242; und die gejointen Aliase aus &#8216;m2&#8242;. Durch <a href="http://dev.mysql.com/doc/refman/5.0/en/group-by-functions.html#function_group-concat" target="_blank">GROUP_CONCAT()</a> werden die Werte nun kommasepariert in der Spalte &#8216;aliases&#8217; ausgegeben.</p>
<pre>mysql&gt; SELECT m1.addy, GROUP_CONCAT(m2.addy SEPARATOR ', ') AS aliases
 -&gt;   FROM mails m1
 -&gt;   JOIN mails m2 ON m2.parent_id = m1.id
 -&gt;  WHERE m2.id &lt;&gt; m2.parent_id
 -&gt;  GROUP BY m1.id;
+----------------+--------------------------------------+
| addy           | aliases                              |
+----------------+--------------------------------------+
| m1@example.com | a1m1@example.com, a2m1@example.com   |
| m2@example.com | a1m2@example.com                     |
+----------------+--------------------------------------+
2 rows in set (0.00 sec)
</pre>
<p>Das funktioniert natürlich auch mit den Ids der Alias-Adressen. In diesem Fall muss dann aber der Rückgabewert von GROUP_CONCAT() gecastet werden, da sonst entweder nur die erste Id oder [BLOB] in der Ausgabe stehen würde.</p>
<pre>mysql&gt; SELECT m1.addy,
 -&gt;           CAST(GROUP_CONCAT(m2.id SEPARATOR ', ') AS char) AS alias_ids
 -&gt;   FROM mails m1
 -&gt;   JOIN mails m2 ON m2.parent_id = m1.id
 -&gt;  WHERE m2.id &lt;&gt; m2.parent_id
 -&gt;  GROUP BY m1.id;
+----------------+-----------+
| addy           | alias_ids |
+----------------+-----------+
| m1@example.com | 2, 4      |
| m2@example.com | 5         |
+----------------+-----------+
2 rows in set (0.00 sec)
</pre>
<p>Die Funktion kann nicht nur gruppieren und mit beliebigen Trennzeichen aufzählen, es ist auch möglich, eine Sortierrichtung mit anzugeben. Mehr dazu im MySQL-Manual.</p>
]]></content:encoded>
			<wfw:commentRss>https://blog.ebene7.com/2010/11/02/aufzaehlungen-mit-group-concat/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>Speicherproblem bei sehr großen InnoDB-Tabellen</title>
		<link>https://blog.ebene7.com/2010/10/18/speicherproblem-bei-sehr-grossen-innodb-tabellen/</link>
		<comments>https://blog.ebene7.com/2010/10/18/speicherproblem-bei-sehr-grossen-innodb-tabellen/#comments</comments>
		<pubDate>Mon, 18 Oct 2010 11:00:35 +0000</pubDate>
		<dc:creator>Daniel</dc:creator>
				<category><![CDATA[Datenbank]]></category>
		<category><![CDATA[Notiz an mich]]></category>
		<category><![CDATA[Tipps und Tricks]]></category>
		<category><![CDATA[InnoDB]]></category>
		<category><![CDATA[MySQL]]></category>
		<category><![CDATA[Speicherproblem]]></category>

		<guid isPermaLink="false">http://blog.ebene7.com/?p=2090</guid>
		<description><![CDATA[Heute hatte ich das Problem, dass ich verschiedene Aktionen auf einer InnoDB-Tabelle nicht ausführen konnte, weil die zugewiesende Buffergröße zu niedrig war bei ca. 24 Millionen Datensätzen. The total number of locks exceeds the lock table size Nach kurzem googlen &#8230; <a href="https://blog.ebene7.com/2010/10/18/speicherproblem-bei-sehr-grossen-innodb-tabellen/">Weiterlesen <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Heute hatte ich das Problem, dass ich verschiedene Aktionen auf einer InnoDB-Tabelle nicht ausführen konnte, weil die zugewiesende Buffergröße zu niedrig war bei ca. 24 Millionen Datensätzen.</p>
<pre><code>The total number of locks exceeds the lock table size</code></pre>
<p>Nach kurzem googlen fand ich den <a href="http://cyrilmazur.com/2010/04/mysql-error-the-total-number-of-locks-exceeds-the-lock-table-size.html" target="_blank">Artikel von Cyril</a>, der offensichtlich die selben Schwierigkeiten hatte.</p>
<p>Die Lösung war zum Glück recht einfach. In der Datei my.cnf muss der folgende Wert erhöht werden, bzw. die Konfigurationseinstellung hinzugefügt werden.</p>
<pre><code>innodb_buffer_pool_size = 16M</code></pre>
<p>Die neue Einstellung sollte dann die Arbeit mit der großen Tabelle ermöglichen.</p>
<pre><code>innodb_buffer_pool_size = 268435456</code></pre>
<p>Zum Schluss dann noch den MySQL-Server neu starten, damit die Änderungen auch wirksam werden.</p>
]]></content:encoded>
			<wfw:commentRss>https://blog.ebene7.com/2010/10/18/speicherproblem-bei-sehr-grossen-innodb-tabellen/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Attachment in CouchDB speichern</title>
		<link>https://blog.ebene7.com/2010/10/07/attachment-in-couchdb-speichern/</link>
		<comments>https://blog.ebene7.com/2010/10/07/attachment-in-couchdb-speichern/#comments</comments>
		<pubDate>Thu, 07 Oct 2010 05:00:21 +0000</pubDate>
		<dc:creator>Daniel</dc:creator>
				<category><![CDATA[Datenbank]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Snippets]]></category>
		<category><![CDATA[Attachment]]></category>
		<category><![CDATA[CouchDB]]></category>
		<category><![CDATA[Zend_Http_Client]]></category>

		<guid isPermaLink="false">http://blog.ebene7.com/?p=1532</guid>
		<description><![CDATA[Letzte Woche habe ich ja schon etwas über CouchDB berichtet und wie unkompliziert man damit arbeiten kann. In den Dokumenten können aber nicht nur beliebige Daten in beliebiger Struktur gespeichert werden, es ist auch sehr einfach Dateianhänge zu speichern. Dieser &#8230; <a href="https://blog.ebene7.com/2010/10/07/attachment-in-couchdb-speichern/">Weiterlesen <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Letzte Woche habe ich ja schon etwas über <a href="http://blog.ebene7.com/2010/09/30/couchdb-kann-mehr-als-nur-moebel-speichern/" target="_self">CouchDB</a> berichtet und wie unkompliziert man damit arbeiten kann. In den Dokumenten können aber nicht nur beliebige Daten in beliebiger Struktur gespeichert werden, es ist auch sehr einfach Dateianhänge zu speichern. Dieser Code-Schnipsel ist ein einfaches Beispiel, wie es mit dem Zend_Http_Client funktioniert. Wichtig ist nur, dass immer die _rev(Id) des jeweiligen Dokumentes mit übergeben wird, da sonst nichts gespeichert wird und ein Konflikt auftritt.</p>
<pre><code>$image = 'bild.jpg'; $mimeType = mime_content_type($image); $content = file_get_contents($image); $url = 'http://developer:5984/database/document/path?rev=xx-xxxxx'; $client = new Zend_Http_Client(); $response = $client-&gt;setUri($url) -&gt;setMethod('PUT') -&gt;setHeaders(array('Content-Type' =&gt; $mimeType)) -&gt;setRawData($content, $mimeType) -&gt;request() </code></pre>
<p>Die Anhänge könnten auch mit dem Dokument im JSON-Format übertragen werden. Dafür müsste $content dann aber erst base64_encoded werden. Hierbei werden bestehende Anhänge aber gelöscht!</p>
]]></content:encoded>
			<wfw:commentRss>https://blog.ebene7.com/2010/10/07/attachment-in-couchdb-speichern/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>CouchDB: kann mehr als nur Möbel speichern</title>
		<link>https://blog.ebene7.com/2010/09/30/couchdb-kann-mehr-als-nur-moebel-speichern/</link>
		<comments>https://blog.ebene7.com/2010/09/30/couchdb-kann-mehr-als-nur-moebel-speichern/#comments</comments>
		<pubDate>Thu, 30 Sep 2010 05:00:23 +0000</pubDate>
		<dc:creator>Daniel</dc:creator>
				<category><![CDATA[Datenbank]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[CouchDB]]></category>
		<category><![CDATA[Datenstruktur]]></category>
		<category><![CDATA[Futon]]></category>
		<category><![CDATA[MySQL]]></category>
		<category><![CDATA[Rest-API]]></category>

		<guid isPermaLink="false">http://blog.ebene7.com/?p=1514</guid>
		<description><![CDATA[CouchDB klingt nicht nur bequem, es ist bequem! CouchDB ist eine dokumentenbasierte Datenbank mit REST-API, serverseitigen JavaScript-Views, Datenaustausch im JSON-Format und weil das noch nicht genug ist gibt es das Admin-Webinterface Futon gleich noch mit der Installation dazu. Die Anbindung &#8230; <a href="https://blog.ebene7.com/2010/09/30/couchdb-kann-mehr-als-nur-moebel-speichern/">Weiterlesen <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>CouchDB klingt nicht nur bequem, es ist bequem! CouchDB ist eine dokumentenbasierte Datenbank mit REST-API, serverseitigen JavaScript-Views, Datenaustausch im JSON-Format und weil das noch nicht genug ist gibt es das Admin-Webinterface Futon gleich noch mit der Installation dazu.</p>
<p>Die Anbindung an eine (PHP-)Anwendung ist bei den Voraussetzungen nun denkbar einfach. Aber eins nach dem anderen.<span id="more-1514"></span></p>
<p>Was macht CouchDB denn aber nun zu einer &#8220;bequemen&#8221; Datenbank? Eigentlich fast alles. CouchDB arbeitet mit Dokumenten und eignet sich dadurch besonders für variable Strukturen und jegliche Daten, die eigentlich nicht in eine relationale Datenbank passen und nur mit viel Mühe geschrieben und gelesen werden können.</p>
<p>In RDBM-Systemen werden derartige Daten im besten Fall im EAV-Datenbankmodel (EAV = Entity-Attribute-Value) abgelegt. Das ist nicht nur sehr CPU-lastig, sondern auch für Menschen schwer bis garnicht lesbar. In CouchDB-Dokumenten liegen die Daten quasi im Stück vor, sind schnell geladen und können auch über Futon einfach bearbeitet werden.</p>
<p>Eigentlich macht alles einen sehr einfachen und leichten Eindruck. Die Installation dauerte mit ein paar Einstellungen nicht länger als zehn Minuten und das System war zumindest als Entwicklungsserver einsatzbereit. Das Admintool Futon und die REST-API sind unter &#8220;http://localhost:5984&#8243; direkt nach dem Start verfügbar.</p>
<p>Futon überrascht mit einer eher schlichten Oberfläche ohne unnötigen Schnickschnack, bietet aber alles Nötige, um damit arbeiten zu können.</p>
<p>Die Verbindung aus der PHP-Anwendung heraus habe ich mit <code>Zend_Http_Client</code> umgesetzt, es funktioniert aber auch mit curl oder anderen HTTP-Clients. Die Daten werden im JSON-Format gelesen und auch wieder geschrieben, daher lassen sich auch komplexere Strukturen einfach mit <code>json_encode()</code> und <code>json_decode()</code> verarbeiten.</p>
<p>Im Gespräch mit einem bekannten Entwickler bekam ich die Antwort, CouchDB sei doch nur ein einfacher Key-Value-Speicher und nicht mächtig genug.</p>
<p>Dem ersten Punkt möchte ich nicht widersprechen. Grob betrachtet haben wir einen Key-Value-Speicher, der jedoch durch seine Views die Daten in beliebiger Form zusammenstellen kann (habe ich eigentlich schon erwähnt, dass die Views mit einfachen JavaScript funktionieren?). Und gegen einfach ist aus meiner Sicht auch garnichts einzuwänden. Warum sollte man auch ein Tool nutzen wollen, welches die Arbeit komplizierter statt einfacher macht?</p>
<p>Fazit: Auch Zahnarztfrauen, ähm&#8230; Möbelhändler empfehlen <a href="http://couchdb.apache.org/" target="_self">CouchDB</a>!</p>
]]></content:encoded>
			<wfw:commentRss>https://blog.ebene7.com/2010/09/30/couchdb-kann-mehr-als-nur-moebel-speichern/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
	</channel>
</rss>
