Entwickler-Ecke

Datenbanken - Index erstellen auf einem VarChar Feld unter Firebird 2.5


NOS1971 - Mi 01.10.14 11:01
Titel: Index erstellen auf einem VarChar Feld unter Firebird 2.5
Hallo,

ich versuche einen Index auf das URL Feld zu legen aber es klappt einfach nicht ... was mache ich falche ?


Delphi-Quelltext
1:
  sqlexec := 'CREATE UNIQUE INDEX IDX_URL ON AnalyseResultURLTable(URL);';                    


Hier die Tabelle


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
  sqlexec := 'CREATE TABLE AnalyseResultURLTable (ID BIGINT PRIMARY KEY NOT NULL, ' +
                                                 'URL VARCHAR(4000), ' +
                                                 'STATUS SMALLINT, ' +
                                                 'URLLINKSOURCE BLOB SUB_TYPE TEXT, ' +
                                                 'PAGERANK INTEGER, ' +
                                                 'HTTPSTATUS INTEGER, ' +
                                                 'CONTENTLENGTH INTEGER, ' +
                                                 'INTERNALLINKS INTEGER, ' +
                                                 'EXTERNALLINKS INTEGER, ' +
                                                 'ANALYSISTIME INTEGER, ' +
                                                 'MIMETYPE BLOB SUB_TYPE TEXT, ' +
                                                 'REQUESTDATETIME BLOB SUB_TYPE TEXT, ' +
                                                 'CHARSET BLOB SUB_TYPE TEXT, ' +
                                                 'SERVER BLOB SUB_TYPE TEXT, ' +
                                                 'RETRYCOUNT INTEGER, ' +
                                                 'FEED INTEGER, ' +
                                                 'LOCATION INTEGER, ' +
                                                 'ROOTURL BLOB SUB_TYPE TEXT, ' +
                                                 'TITLE BLOB SUB_TYPE TEXT, ' +
                                                 'DOCTYPE BLOB SUB_TYPE TEXT, ' +
                                                 'BASE BLOB SUB_TYPE TEXT, ' +
                                                 'KEYWORDS BLOB SUB_TYPE TEXT, ' +
                                                 'DESCRIPTION BLOB SUB_TYPE TEXT, ' +
                                                 'METATAGLIST BLOB SUB_TYPE TEXT, ' +
                                                 'HTAGLIST BLOB SUB_TYPE TEXT, ' +
                                                 'LINKLIST BLOB SUB_TYPE TEXT, ' +
                                                 'SITESIZE INTEGER, ' +
                                                 'REDIRECTLIST BLOB SUB_TYPE TEXT, ' +
                                                 'HTMLTAGDATA BLOB SUB_TYPE TEXT, ' +
                                                 'CSSTAGDATA BLOB SUB_TYPE TEXT, ' +
                                                 'ROBOTS BLOB SUB_TYPE TEXT, ' +
                                                 'CONNECTIONLIST BLOB SUB_TYPE TEXT, ' +
                                                 'URLCONTENT BLOB SUB_TYPE TEXT, ' +
                                                 'LASTUPDATED BLOB SUB_TYPE TEXT, ' +
                                                 'WORDCOUNT BIGINT, ' +
                                                 'CHARCOUNT BIGINT);';


Nersgatt - Mi 01.10.14 11:04

Hilfreich wäre die Fehlermeldung.

Ich vermute, dass das Feld URL zu lang ist (4000 ist ja schon ne Nummer). Die maximale Indexlänge hängt von der verwendeten Pagesize ab:
http://www.firebirdsql.org/refdocs/langrefupd20-create-index.html#langrefupd20-creatind-keylength


NOS1971 - Mi 01.10.14 11:17

Hier mal der Auszug vom FireDac Monitor ... PageSize ist bei mir 32768 ... das bringt nichts oder ? ... da die maximale in der Tabelle auf 16384 liegt ... ?


Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
         1  11:13:44:531      << TFDConnection($03E65700).Commit [ConnectionDef="seoBOXX_Database_Connection", Retaining=False]
         2  11:13:44:531  << TFDConnection($03E65700).TFDPhysIBTransactionBase($03ED9740).TFDPhysFBCommand($067997E0).Execute [Command="CREATE TABLE AnalyseResultURLTable (ID BIGINT PRIMARY KEY NOT NULL, URL VARCHAR(4000), STATUS SMALLINT, URLLINKSOURCE BLOB SUB_TYPE TEXT, PAGERANK INTEGER, HTTPSTATUS INTEGER, CONTENTLENGTH INTEGER, INTERNALLINKS INTEGER, EXTERNALLINKS INTEGER, ANALYSISTIME INTEGER, MIMETYPE BLOB SUB_TYPE TEXT, REQUESTDATETIME BLOB SUB_TYPE TEXT, CHARSET BLOB SUB_TYPE TEXT, SERVER BLOB SUB_TYPE TEXT, RETRYCOUNT INTEGER, FEED INTEGER, LOCATION INTEGER, ROOTURL BLOB SUB_TYPE TEXT, TITLE BLOB SUB_TYPE TEXT, DOCTYPE BLOB SUB_TYPE TEXT, BASE BLOB SUB_TYPE TEXT, KEYWORDS BLOB SUB_TYPE TEXT, DESCRIPTION BLOB SUB_TYPE TEXT, METATAGLIST BLOB SUB_TYPE TEXT, HTAGLIST BLOB SUB_TYPE TEXT, LINKLIST BLOB SUB_TYPE TEXT, SITESIZE INTEGER, REDIRECTLIST BLOB SUB_TYPE TEXT, HTMLTAGDATA BLOB SUB_TYPE TEXT, CSSTAGDATA BLOB SUB_TYPE TEXT, ROBOTS BLOB SUB_TYPE TEXT, CONNECTIONLIST BLOB SUB_TYPE TEXT, URLCONTENT BLOB SUB_TYPE TEXT, LASTUPDATED BLOB SUB_TYPE TEXT, WORDCOUNT BIGINT, CHARCOUNT BIGINT);", ATimes=1, AOffset=0, RowsAffected=0, RowsAffectedReal=True, ErrorAction=5]
         3  11:14:21:844   . Preprocessed [CMD="CREATE UNIQUE INDEX IDX_URL ON AnalyseResultURLTable(URL);", FROM="", VP=0, VPE=0, OBP=0, CK=8]
         4  11:14:21:844  >> Execute [Command="CREATE UNIQUE INDEX IDX_URL ON AnalyseResultURLTable(URL);", ATimes=0, AOffset=0]
         5  11:14:21:844      >> Prepare [Command="CREATE UNIQUE INDEX IDX_URL ON AnalyseResultURLTable(URL);"]
         6  11:14:21:844           . Preprocessed [CMD="CREATE UNIQUE INDEX IDX_URL ON AnalyseResultURLTable(URL);", FROM="", VP=0, VPE=0, OBP=0, CK=8]
         7  11:14:21:844          >> TFDConnection($03E65700).StartTransaction [ConnectionDef="seoBOXX_Database_Connection"]
         8  11:14:21:844               . isc_start_multiple [count=1, params="write,read_committed,rec_version,wait"]
         9  11:14:21:844          << StartTransaction [ConnectionDef="seoBOXX_Database_Connection"]
        10  11:14:21:844      << TFDConnection($03E65700).TFDPhysIBTransactionBase($03ED9740).TFDPhysFBCommand($067997E0).Prepare [Command="CREATE UNIQUE INDEX IDX_URL ON AnalyseResultURLTable(URL);"]
        11  11:14:21:844       . isc_dsql_execute_immediate [db_handle=$00000002, tra_handle=$00000006, sql="CREATE UNIQUE INDEX IDX_URL ON AnalyseResultURLTable(URL);", dialect=3]
        12  11:14:21:844       . ERROR: unsuccessful metadata update can't format message 8:118 -- message file E:\AnSoTeC\SEOWorkshop2013\ThreadAndDBTest\bin\firebird.msg not found [ErrorCode=335544351, ObjName=""]


Nersgatt - Mi 01.10.14 12:08

Zitat:
message file E:\AnSoTeC\SEOWorkshop2013\ThreadAndDBTest\bin\firebird.msg not found

Beheb das mal, dann bekommst Du auch ne gescheite Fehlermeldung.

Ich vermute in dem Feld soll eine URL gespeichert werden? Da würde ich mich fragen, ob das wirklich 4000 Stellen haben muss. Die meisten Browser können wohl eh nur um die 2000 Stellen verarbeiten. Somit wird Dir in der Praxis wohl kaum eine URL unterkommen, die 4000 Stellen lang ist.
Und sonst müsste man überlegen, ob man das komplette Feld indizieren muss, oder ob es reichen würde, ein weiteres (Such-) Feld zu erstellen, das z.B. nur den Hostnamen enthält (könnte z.B. über einen Trigger automatisch gefüllt werden). Das könnte man dann problemlos indizieren.


NOS1971 - Mi 01.10.14 12:26

Also behoben habe ich das .. in der Datei steht aber danach dennoch nichts ... ich habe mal die Fehlermeldung als Screen angehangen und den aktuellen Auszug aus dem Firedac Monitor

Wenn ich das also recht sehe ist bei einer Pagesize von 16384 das ende erreicht ? ... also eine teil der url indizieren bringt nichts da ich in dem crawler jedesmal checke ob es die url schon in der db gibt ... das wollte ich schneller machen ... der IE schafft urls bis 2083 zeichen soweit ich das ermitteln konnte ... laut HTTP Spezifikationen gibt es keine Einschränkung der länge ... ich denke aber mal das man es durchaus reduzieren kann


Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
        79  12:17:59:588   . Preprocessed [CMD="CREATE UNIQUE INDEX IDX_IDP ON AnalyseResultParentURLTable (URL,PARENTURL);", FROM="", VP=0, VPE=0, OBP=0, CK=8]
        80  12:17:59:588  >> Execute [Command="CREATE UNIQUE INDEX IDX_IDP ON AnalyseResultParentURLTable (URL,PARENTURL);", ATimes=0, AOffset=0]
        81  12:17:59:588      >> Prepare [Command="CREATE UNIQUE INDEX IDX_IDP ON AnalyseResultParentURLTable (URL,PARENTURL);"]
        82  12:17:59:588           . Preprocessed [CMD="CREATE UNIQUE INDEX IDX_IDP ON AnalyseResultParentURLTable (URL,PARENTURL);", FROM="", VP=0, VPE=0, OBP=0, CK=8]
        83  12:17:59:588          >> TFDConnection($02605700).StartTransaction [ConnectionDef="seoBOXX_Database_Connection"]
        84  12:17:59:588               . isc_start_multiple [count=1, params="write,read_committed,rec_version,wait"]
        85  12:17:59:588          << StartTransaction [ConnectionDef="seoBOXX_Database_Connection"]
        86  12:17:59:588      << TFDConnection($02605700).TFDPhysIBTransactionBase($02679740).TFDPhysFBCommand($067897E0).Prepare [Command="CREATE UNIQUE INDEX IDX_IDP ON AnalyseResultParentURLTable (URL,PARENTURL);"]
        87  12:17:59:588       . isc_dsql_execute_immediate [db_handle=$00000002, tra_handle=$0000000B, sql="CREATE UNIQUE INDEX IDX_IDP ON AnalyseResultParentURLTable (URL,PARENTURL);", dialect=3]
        88  12:17:59:588       . ERROR: unsuccessful metadata update can't format message 8:118 -- message system code -4 [ErrorCode=335544351, ObjName="can't format message 8:118 -- message system code -4"]


Ralf Jansen - Mi 01.10.14 12:48

Was für ein Encoding speicherst du den in der Spalte? Wenn du utf-8 verwendest brauchst du halt 4 Byte was ziemliche Verschwendung wäre wenn es tatsächlich Urls sind die eigentlich nur ASCII enthalten. Wenn du die Spalte explizit als CHARACTER SET ASCII definierst solltest du noch ein wenig mehr mögliche Indexbreite (im Falle von utf-8 -> Ascii ein Faktor 4) rausschlagen können.


NOS1971 - Mi 01.10.14 13:08

Ich habe jetzt die Länge auf 1000 runtergesetzt ... ich hoffe mal das das inkl. Parametern etc. reichen wird ...

Zunächst einmal vielen Dank für Eure Hilfe !!!!!


NOS1971 - Mi 01.10.14 18:29

Hallo,

da bin ich wieder :-) ... Leider sind einige URLs mit Parametern aus Shops tatsächlich länger als erwartet ... was nun ? Gibt es eine andere Single File DB die diese Vorraussetzungen erfüllt und in einem Index längere VarChars zulässt ? --- 2083 Chars ist das derzeitige maximum welches zu erreichen ist in den standard browsern. Oder wäre eine andere Variante wie eine Chaecksumme ein Hashwert etc. abzulegen und danach zu gehen ?

Grüße,
Andreas


Delete - Mi 01.10.14 18:40

Wieso nimmst du nicht einfach einen Text-Blob für deine ellenlangen URLs?


NOS1971 - Mi 01.10.14 19:45

Weil ein Blog Textfeld nicht indiziert werden kann soweit ich das sehe


Ralf Jansen - Mi 01.10.14 20:35

Du hast ASCII für die Column ausprobiert?


NOS1971 - Mi 01.10.14 20:54

Nein ... habe ich nicht ausprobiert, da ja auch umlaute etc. in einer url vorkommen können ... soweit ich das sehe ist es standard das eine url im utf-8 format gespeichert wird ... oder sehe ich das falsch ?


Ralf Jansen - Mi 01.10.14 21:03

Ja. URLs dürfen nur ASCII Zeichen enthalten. Wenn dir dein Browser was anderes anzeigt ist das das Ergebnis eines URL-Encodings. Über die Leitung geht nur ASCII.


NOS1971 - Mi 01.10.14 21:18

es geht ja auch darum dem user fehler zu zeigen die er im code hat ... eventuell wäre das sinnig das umzubauen und ein zusätzliches feld mit der originalen url zu haben .... ich probiere das mal aus :-)


NOS1971 - Mi 01.10.14 21:40

Mal so auf die schnelle ... wie definiere ich denn eine einzige Column als ASCII ohne die ganze tabelle umzustricken aus ASCII ?


Ralf Jansen - Mi 01.10.14 21:43


SQL-Anweisung
1:
2:
CREATE TABLE ... blah
   URL VARCHAR(4000CHARACTER SET ASCII,


Blup - Mo 06.10.14 16:47

Stellt sich die Frage:
Für welchen Zweck benötige ich einen eindeutigen Index über ein Textfeld dieser Größe?

Antwort:
Um sicher zu stellen, daß der selbe Text nicht mehrmals in der Tabelle landet.
Die tatsächliche Reihenfolge die sich aus dem Index ergibt, spielt keine Rolle.

Da es so nicht geht, welche Alternative bietet sich an?
Man kann einen Hash über den gesamten Text (z.B. MD5) bilden.
Diesen in einer separaten Spalte speichern und darauf den eindeutigen Index setzen.
Der Text selbst kann in einem Blobfeld gespeichert werden und damit praktisch beliebig lang sein.