ruben: MySQL optimal benutzen

Hallo!

Ich habe eigentlich kein unlösbares Problem, es geht mehr um die Performance und – naja – das Gefühl.
Ich finde MySQL in Kombination mit PHP ist sehr leicht zu benutzen, wenn man nur das Basiswissen in MySQL hat (also INSERT, UPDATE, REPLACE, DELETE und "wie installiere ich PHPmyAdmin").
Das liegt daran, dass man auf Umwegen vieles, was in MySQL geht, in PHP tun kann (zum Beispiel die Anzahl der Datensätze, die eine where-Klausel erfüllen zählen COUNT(*) oder count()).
Das ist aber oft nervig und schlägt sich vermutlich auch in der Performance nieder.

Nun habe ich also folgende Frage:
Der relevante Teil meiner Datenbank sieht so aus:
Tabelle "Vokabeln":
id | nutzer | sprache | vokabelspezifische Felder
Tabelle "Sprachen":
nutzer | sprache | sprachenspezifische Felder
Die Sprachen sind allgemeiner als die Vokabeln.

Nun ist es folgendermaßen:
Die Sprachen sollen nur die Vokabeln widerspiegeln.
Damit meine ich, dass es eine Sprache nur gibt, wenn es auch Vokabeln dieser Sprache gibt. Wenn alle Vokabeln einer Sprache gelöscht werden, soll es auch die Sprache nicht mehr geben.
Ich kann diesen Umstand umständlich mit PHP verwirklichen, indem ich bei jeder Vokabellöschung/-veränderung überprüfe, ob es die letzte war oder die erste und wenn dem so ist, die Tabelle "Sprachen" verändere.
Das nervt aber sehr.
Ich denke, es geht auch mit MySQL, vermutlich sogar recht komfortabel, aber ich weiß nicht genau, ob ich schon bei der Tabellenstruktur ansetzen muss, oder bei den Anfragen.

Ich hab mir meine Kenntnisse Stück für Stück angeeignet und deswegen bergen Dokumentationen, die es von Anfang an aufrollen viele redundante Informationen für mich. Vielleicht hätte ich anders an MySQL rangehen sollen, aber es ist wohl zu spät.

Ich arbeite mit MySQL 5.0.

Vielen Dank für hilfreiche Hinweise,
Ruben

  1. Nun ist es folgendermaßen:
    Die Sprachen sollen nur die Vokabeln widerspiegeln.
    Damit meine ich, dass es eine Sprache nur gibt, wenn es auch Vokabeln dieser Sprache gibt.

    Ich kenne das angeforderte feature als cascading deletes.

    Allerdings rate ich davon ab solchen Mechanismen einzusetzen, der Nutzen ist ausgesprochen gering.

    Ob MySQL das kann?
    Mal hier klicken:   ;)
    http://www.google.de/search?hl=de&q=myslq+cascading+deletes&meta=

    1. Nun ist es folgendermaßen:
      Die Sprachen sollen nur die Vokabeln widerspiegeln.
      Damit meine ich, dass es eine Sprache nur gibt, wenn es auch Vokabeln dieser Sprache gibt.

      Ich kenne das angeforderte feature als cascading deletes.

      Allerdings rate ich davon ab solchen Mechanismen einzusetzen, der Nutzen ist ausgesprochen gering.

      Ob MySQL das kann?
      Mal hier klicken:   ;)
      http://www.google.de/search?hl=de&q=myslq+cascading+deletes&meta=

      Bzw. ggf. allgemein googlen nach referentieller Integrität.

      Mit kaskadierendem Löschen würde ich übrigens auch vorsichtig. Wobei hier die Frage ist, in welcher Richtung wirkt es. Wenn ich eine Sprache löschen, löscht kaskadierend ggf. alle Vokabeln. Jedoch soll ja hier beim Löschen der letzten Vokabel die zugehörige Sprache gelöscht werden (und nur dann).

      Nick

      --
      --------------------------------------------------
      http://www.xilp.eu
      XILP Internet Links People
      Dein persoenliches privates Netzwerk
      aus Freunden, Verwandten, Bekannten und Kollegen.
      --------------------------------------------------
      1. Ob MySQL das kann?
        Mal hier klicken:   ;)
        http://www.google.de/search?hl=de&q=mysql+cascading+deletes&meta=

        Anscheinend ja, aber nur mit InnoDB (merklich langsamer als standard MyISAM).

        Bzw. ggf. allgemein googlen nach referentieller Integrität.

        Mit kaskadierendem Löschen wäre ich übrigens auch vorsichtig. Wobei hier die Frage ist, in welcher Richtung es wirkt. Wenn ich eine Sprache lösche, löschen Kaskaden ggf. alle Vokabeln. Jedoch soll ja hier beim Löschen der letzten Vokabel die zugehörige Sprache gelöscht werden (und nur dann).

        Das ist eben die Frage, was hier die optimale Vorgehensweise ist.
        Macht es Sinn, diesen etwas komplizierteren Datenbankaufbau in Kauf zu nehmen?
        Gibt es Statements (ich kenn mich z.B. mit IF NOT EXISTS nicht aus), die es ohne den komplizierten Aufbau etwas leichter machen?
        Oder am besten alles mit PHP und ich bleib meinen SELECT, DELETE, UPDATE, REPLACE?

        Schöne Grüße,
        Ruben

  2. Hallo Ruben,

    Die Sprachen sollen nur die Vokabeln widerspiegeln.
    Damit meine ich, dass es eine Sprache nur gibt, wenn es auch Vokabeln dieser Sprache gibt. Wenn alle Vokabeln einer Sprache gelöscht werden, soll es auch die Sprache nicht mehr geben.

    das ist in meinen Augen suboptimal.
    Ändere Deine Einstellung - und mach es bestenfalls umgekehrt.

    Wenn eine Sprache gelöscht wird, dann soll es auch keine Vokabeln dieser Sprache
    mehr geben. Die Stichworte dazu wurden bereits genannt: Referentielle Integrität
    durchsetzbar mit

    ON DELETE CASCADE

    bei MySQL nur bei Verwendung der InnoDB-Engine.

    Willst Du Deine derzeitige Strategie beibehalten, so kannst Du dies
    datenbankseitig mit Triggern erledigen. Diese übernehmen die Prüfung, die Du
    derzeit in der API machst und löschen gegebenenfalls die Sprache aus der zweiten
    Tabelle.

    Nein, dies ist meiner Meinung nach keine gute Idee und erst recht nicht "optimal".

    Eine Sprache hat meiner Meinung nach nichts damit zu tun, ob Vokabeln, Wörter
    dazu abgespeichert sind. Umgekehrt solltest Du erst Vokabeln einer Sprache
    abspeichern, nachdem Du diese Sprache angelegt hast. Deine
    Spaltenbezeichnungen lassen (möglicherweise zu Unrecht) auf eine suboptimale
    Tabellenstruktur schließen. Ohne ein paar Beispieldatensätze, insbesondere
    auch mit den vokabel- und sprachenspezifischen Feldern läßt sich das aber
    nicht endgültig beurteilen.

    Freundliche Grüße

    Vinzenz

    1. das ist in meinen Augen suboptimal.
      Ändere Deine Einstellung - und mach es bestenfalls umgekehrt.

      Ich fürchte, ich habe die Datenbanksituation wirklich nicht ausreichend dargestellt. Ich bin mir aber sicher. Soweit ich deine Ausführungen bisher verstehe, will ich wirklich keine Kaskaden sondern Trigger (gibt es die auch für MyISAM-Tabellen)?

      Wenn eine Sprache gelöscht wird, dann soll es auch keine Vokabeln dieser Sprache
      mehr geben. Die Stichworte dazu wurden bereits genannt: Referentielle Integrität
      durchsetzbar mit

      ON DELETE CASCADE

      bei MySQL nur bei Verwendung der InnoDB-Engine.

      Willst Du Deine derzeitige Strategie beibehalten, so kannst Du dies
      datenbankseitig mit Triggern erledigen. Diese übernehmen die Prüfung, die Du
      derzeit in der API machst und löschen gegebenenfalls die Sprache aus der zweiten
      Tabelle.

      Die möchte ich beibehalten, ich illustriere warum an folgendem Beispiel.

      Nein, dies ist meiner Meinung nach keine gute Idee und erst recht nicht "optimal".
      Eine Sprache hat meiner Meinung nach nichts damit zu tun, ob Vokabeln, Wörter
      dazu abgespeichert sind. Umgekehrt solltest Du erst Vokabeln einer Sprache
      abspeichern, nachdem Du diese Sprache angelegt hast. Deine
      Spaltenbezeichnungen lassen (möglicherweise zu Unrecht) auf eine suboptimale
      Tabellenstruktur schließen. Ohne ein paar Beispieldatensätze, insbesondere
      auch mit den vokabel- und sprachenspezifischen Feldern läßt sich das aber
      nicht endgültig beurteilen.

      Ich hoffe, so wird es klarer (ich hielt diese Informationen für redundant):
      CREATE TABLE vokabeln (
        id int(5) unsigned NOT NULL auto_increment,
        user varchar(255) NOT NULL default '',
        sprache varchar(255) NOT NULL default '',
        bekannt text NOT NULL,
        fremd text NOT NULL,
        hinweis text NOT NULL,
        phase tinyint(2) unsigned NOT NULL default '0',
        zeit int(8) unsigned NOT NULL default '0',
        PRIMARY KEY  (id)
      ) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=10449 ;

      --
      -- Daten für Tabelle vokabeln
      --
      INSERT INTO vokabeln VALUES (1, 'ruben', 'SCHWEDISCH', 'trinken', 'dricka', '', 5, 20060218);
      INSERT INTO vokabeln VALUES (23, 'ruben', 'SCHWEDISCH', 'Die Sonne scheint.', 'Solen skiner.', '', 5, 20060218);
      INSERT INTO vokabeln VALUES (121, 'ruben', 'SPANISCH', 'gelb', 'amarillo', '', 5, 19700101);
      INSERT INTO vokabeln VALUES (710, 'ruben', 'ENGLISCH', 'sich erfreuen/ergötzen', 'to regale', '', 5, 20061220);
      CREATE TABLE sprachen (
        nutzer varchar(255) NOT NULL default '',
        sprache varchar(255) NOT NULL default '',
        zeichen varchar(255) NOT NULL default '',
        abfrage tinyint(1) NOT NULL default '0'
      ) ENGINE=MyISAM DEFAULT CHARSET=utf8;
      --
      -- Daten für Tabelle sprachen
      --
      INSERT INTO sprachen VALUES ('ruben', 'englisch', 'x y z', 1);
      INSERT INTO sprachen VALUES ('ruben', 'franzoesisch', 'ï œ æ ë', 1);
      Soweit so simpel.
      Der Knackpunkt ist aber eigentlich der:
      Man fügt beständig neue Vokabeln hinzu, und wählt für die neuen Datensätze entweder eine der bereits vertretenen Sprachen oder eine neue.
      Wenn man die Sprache löschen will, kann man alle Vokabeln dieser Sprache löschen (das halte ich für besser, da man es selten will).
      Du kannst es dir live in der genannten URL ansehen, das ist aber nicht die Version an der ich arbeite. Dort sind Sprachen und Vokabeln vollkommen unabhängig voneinander (eine sehr nervige Lösung).
      Ich bin mir auf jeden Fall sehr sicher, dass meine Lösung für meinen Fall die bessere ist. Wenn du dir die Seite ansiehst, verstehst du es auch; gibt es dafür keine Zeit; dann nimm mein Wort dafür.
      Schönen Gruß und vielen Dank für die hilfreichen Stichworte,
      Ruben (in Eile…)