Powered by Invision Power Board


  Reply to this topicStart new topic

> MySQL Datentyp, TEXT UNIQUE KEY ???
Alex S.
geschrieben am: 11.11.2010, 14:01
Quote Post





Gruppe: Mitglieder
Beiträge: 8
Mitglieds-Nr.: 780
Mitglied seit: 28.01.2010



Hallo, zusammen.

Folgendes wurmt mich jetzt seit knapp 8 Stunden!!!1

Ausgangssituation (in etwa):
CODE
CREATE TABLE IF NOT EXISTS $TabellenName
(
`Nachrichten-ID` int NOT NULL AUTO_INCREMENT,
PRIMARY KEY(`Nachrichten-ID`),
`readfile` TEXT UNIQUE KEY,
`MySQL-TIMESTAMP` TIMESTAMP
)

Fehlermeldung:
QUOTE
#1170 - BLOB/TEXT column 'readfile' used in key specification without a key length


Warum kann ich diesen TEXT nicht als UNIQUE KEY deklarieren? Die offizielle Doku verstehe ich einfach nicht (und den folgenden Code habe ich nicht getestet, denn wenn das schon auf der offiziellen MySQL-5.1dev-site steht, dann sollte das auch laufen):
CODE
CREATE TABLE example (
 a INT NOT NULL,
 b INT NOT NULL,
 c INT NOT NULL,
 PRIMARY KEY(a),
 UNIQUE(b)
) ENGINE=NDBCLUSTER;


Wenn das laufen soll, warum dann bitte die TEXT UNIQUE KEY bzw UNIQUE(`readfile`) nicht, keines von beiden tut's!

ps: Ich sitze wie gesagt schon seit fast acht Stunden an diesem Problem, und ich würde am liebsten nur noch in die Welt hinaus fluchen.

LG,
Alex
PMEmail Poster
Top
NetPanther
geschrieben am: 11.11.2010, 18:39
Quote Post


Administrator


Gruppe: Administratoren
Beiträge: 7.696
Mitglieds-Nr.: 1
Mitglied seit: 29.08.2004



Guten Abend,

im Prinzip sagt dir die Fehlermeldung doch schon, was verkehrt ist beziehungsweise was MySQL erwartet: Du möchtest eine Spalte vom Typ BLOB/TEXT als Schlüssel verwenden, hast aber keine Länge angegeben. Bei textuellen Datentypen ist dies aber immer zu empfehlen, da die Index-Datei dadurch klein gehalten wird. Die Datenbank ist dann dazu in der Lage, Einträge anhand des Schlüssels schneller wieder aufzufinden und zu verarbeiten. Bei den Datentypen BLOB und TEXT ist die Angabe der Länge sogar Pflicht.

Dazu folgender Auszug aus der MySQL Dokumentation:
QUOTE (CREATE TABLE Syntax)
For CHAR, VARCHAR, BINARY, and VARBINARY columns, indexes can be created that use only the leading part of column values, using col_name(length) syntax to specify an index prefix length. BLOB and TEXT columns also can be indexed, but a prefix length must be given. Prefix lengths are given in characters for nonbinary string types and in bytes for binary string types. That is, index entries consist of the first length characters of each column value for CHAR, VARCHAR, and TEXT columns, and the first length bytes of each column value for BINARY, VARBINARY, and BLOB columns. Indexing only a prefix of column values like this can make the index file much smaller. See Section 7.5.1, “Column Indexes”.

Only the MyISAM, BDB, and InnoDB storage engines support indexing on BLOB and TEXT columns.


Wenn du dem Link im Zitat folgst, findest du die Informationen auch nochmal Schwarz auf Weiß.

MfG


--------------------
:: NetPanther :: NetPanther@gmx.net :: Website :: IRC Channel: #NetPanther ::

Das Leben ist eine Beta. Nichts ist vollkommen.
PMEmail PosterUsers WebsiteICQAOLYahooMSN
Top
Alex S.
geschrieben am: 12.11.2010, 12:06
Quote Post





Gruppe: Mitglieder
Beiträge: 8
Mitglieds-Nr.: 780
Mitglied seit: 28.01.2010



Hallo, NetPanther.

Ich beschäftige mich zum ersten mal mit MySQL. Eigentlich dachte ich die betreffende Spalte als UNIQUE auszeichnen zu können um doppelte Einträge zu vermeiden. Ich bin aber noch im Design der Datenbank. Hier erst einmal die Einträge, und dann folgend die Erklärung dazu.
CODE
$MeineTabellenSpalte['000__readfile']                 = 'TEXT';

$MeineTabellenSpalte['001__Zeit-Stempel']             = 'TEXT';

$MeineTabellenSpalte['002__Nachrichten-Zeit']         = 'TEXT';
$MeineTabellenSpalte['003__Nachrichten-Titel']        = 'TEXT';
$MeineTabellenSpalte['004__Nachrichten-Beschreibung'] = 'LONGTEXT';
$MeineTabellenSpalte['005__Nachrichten-Link']         = 'TEXT';

$MeineTabellenSpalte['006__Rating']                   = 'TEXT';

$MeineTabellenSpalte['007__Kommentare']               = 'LONGTEXT';


readfile dient nur zum Übertragen meiner TXT-Dateien. Diese TXT-Dateien werden dann verschoben. Durch das Verschieben will ich verhindern das doppelte Einträge stattfinden.

Zeit-Stempel enthält fileatime/filectime/filemtime-Werte. Daraus ermittele ich in einem weiteren Schritt die Nachrichten-Zeit.

Nachrichten-Zeit und Nachrichten-Titel und Nachrichten-Beschreibung sowie Nachrichten-Link wird in der weiteren Aufbereitung von readdfile gefüllt.

Rating ist neu. Gedenke es mittels parse_str() auszulesen und entsprechend zu verarbeiten.

Kommentare sind sporadisch vorhanden, und werden ebenso aus der Aufbereitung von readfile gefüllt.

Jetzt wo ich sehe das man einen INDEX fahren kann, frage ich mich, da ich das Durchsuchen der Datenbank schnell haben möchte, welche Spalten in den INDEX sollen. Die Datenbank soll natürlich auch nicht unnötig aufgebläht werden. Deshalb mal folgende Werte.

So ein readfile-Eintrag hat eine Größe von 400 bis 1500 Bytes. Dieser Eintrag wird im 2ten Schritt in die nebenstehenden Spalten übertragen und geleert. Lohnt es sich denn Titel und Beschreibung als INDEX zu deklarieren um SELECT-Operationen (also eine Wortsuche wie zum Beispiel "Wo ist mein Hund") schneller zu machen? Die Datenbank würde dann doch doppelt so groß werden, oder habe ich da etwas falsch verstanden?

MfG,

Alex
PMEmail Poster
Top
NetPanther
geschrieben am: 12.11.2010, 14:09
Quote Post


Administrator


Gruppe: Administratoren
Beiträge: 7.696
Mitglieds-Nr.: 1
Mitglied seit: 29.08.2004



Guten Tag,

aktuelle Versionen von MySQL bieten bereits eine integrierte Volltextsuche. Du musst dazu lediglich einen entsprechenden Index auf die gewünschte Spalte legen und kannst dann mit speziellen Kommandos gezielt nach einzelnen Begriffen im Datenbestand suchen.

SQL
-- Volltextindex anlegen
ALTER TABLE tabelle ADD FULLTEXT (spalte);

-- Tupel anhand eines Worts suchen
SELECT * FROM tabelle WHERE MATCH spalte AGAINST ('wort');


Die Lösung sollte für deine Zwecke ausreichend performant sein. Bei größeren Applikationen sind externe Suchlösungen zu empfehlen (Lucene, Solr usw.), aber in deinem Fall dürften die Bordmittel von MySQL vollkommen ausreichen. Voraussetzung ist allerdings, dass du MyISAM als Storage Engine verwendest und deine MySQL Version irgendwo über 3.x liegt. - Das sollte aber heutzutage hoffentlich überall der Fall sein. smile.gif Bei älteren Versionen müsstest du mit LIKE-Anfragen arbeiten, was bei großer Datenbasis nicht mehr ratsam ist (sehr langsam).

Ansonsten solltest du dich zunächst vielleicht noch etwas mit Datenbank-Design auseinandersetzen, bevor du einfach losprogrammierst. Kommentare zu einem Artikel würde man zum Beispiel als n:m-Beziehung abbilden und nicht zusammen mit den Beiträgen speichern. Für Zeit- und Datumsangaben (auch UNIX Zeitstempel) kennt MySQL ferner eigene Datentypen. Informationen dazu findest du hier. Was du mit parse_str() vorhast, erschließt sich mir aus deiner Beschreibung nicht, aber die Andeutungen lassen nichts Gutes vermuten. Besser das Datenschema noch einmal überarbeiten und normalisieren (Rating in 1. Normalform bringen). Auch den Umgang mit Dateien eventuell überdenken, aber hier weiß ich nicht genau, was du vorhast. In der Regel ist es sinnvoll, Dateien nur in der Datenbank zu referenzieren (Pfad im Dateisystem) und sie nicht selbst darin zu speichern. Alternativ bietet sich eventuell ein BLOB als Datentyp an, sofern die Daten nur gehalten werden sollen (und du SQL-seitig nicht an den Inhalt ran musst).

Zum Verhindern doppelter Tupel sollte bereits die Verwendung eines Primärschlüssels ausreichen. Wie sinnvoll es ist, komplette Texte miteinander abzugleichen, sei mal dahingestellt. Auch hier kenne ich deine Anwendung nicht, aber du solltest dir dessen bewusst sein, dass diese Operation sehr teuer sein kann. Ansonsten kannst du Indizes natürlich setzen, wie du lustig bist. Oftmals können sie den Zugriff auf Daten massiv beschleunigen. Ob man den verwaltungstechnischen Overhead dafür in Kauf nehmen kann, sollte man dann von Fall zu Fall entscheiden.

MfG


--------------------
:: NetPanther :: NetPanther@gmx.net :: Website :: IRC Channel: #NetPanther ::

Das Leben ist eine Beta. Nichts ist vollkommen.
PMEmail PosterUsers WebsiteICQAOLYahooMSN
Top
0 Besucher zu diesem Thema (0 Gäste und 0 'versteckte' Mitglieder)
0 Mitglied(er):

Topic Options Reply to this topicStart new topic

 



[ DB Queries: 11 ]   [ Execution Time: 0.2189 ]   [ GZIP aktiviert ]