2017-05-18 3 views
0

I 2 Tabellen habe, '[Option], mit dem Feld [name] nvarchar (255) ' [Transaktion] mit dem Feld [short_description] nvarchar (3999)Ein großer 'wie' passende Abfrage

Und ich brauche also zu tun:

Select [Transaction].id, [Item].id 
From [Transaction] inner join [Item] 
on [Transaction].[short_description] like ('%' + [Item].[name] + '%') 

Die oben genannten Arbeiten, wenn auf eine Handvoll Elemente beschränkt, sondern ungefiltert ist etwas mehr als 20 Minuten zu gehen und ich stornieren.

Ich habe einen NC-Index auf [Name], aber ich kann wegen seiner Länge nicht [short_description] indexieren.

[Transaction] has 320,000 rows 
[Items] has 42,000. 

Das sind 13.860.000.000 Kombinationen.

Gibt es eine bessere Möglichkeit, diese Abfrage durchzuführen? Ich habe im Volltext gestochert, aber ich bin nicht wirklich so vertraut, die Antwort war nicht, mich dort herauszuspringen.

Jeder Ratschlag geschätzt !!

+0

Sie schließen sich einem Platzhalter an. Es gibt keine Möglichkeit, das schneller zu machen. Es muss jeden einzelnen Artikel mit jeder einzelnen Transaktion vergleichen. –

+0

Dies könnte ein Fall sein, in dem Denormalisierung sinnvoll ist. Sie könnten eine separate Tabelle erstellen, um Artikelnamen und Kurzbeschreibungen von Transaktionen zu referenzieren. Trigger auf beiden Tabellen würden den Querverweis auf dem neuesten Stand halten.Wenn Sie veraltete Daten tolerieren könnten, könnten Sie auf Trigger verzichten und einen Job planen, um den Querverweis zu geeigneten Zeitpunkten zu aktualisieren. – HABO

Antwort

3

Das Starten einer Vergleichszeichenfolge mit einem Platzhalter (% oder _) wird NIEMALS einen Index verwenden und ist in der Regel katastrophal für die Leistung. Ihre Abfrage muss Indizes durchsuchen und nicht durch sie suchen, sodass die Indexierung nicht hilft.

Idealerweise sollten Sie über eine dritte Tabelle verfügen, die basierend auf IDs eine Viele-zu-Viele-Beziehung zwischen Transaktion und Artikel ermöglicht. Das Design ist hier das Thema.

+0

Es kann sogar von einem Index-Scan profitieren. Ein Index-Scan benötigt in der Regel weniger I/O als ein Tabellen-Scan. Je kleiner die Indexbreite relativ zur Zeilenbreite ist, desto größer ist der Vorteil. – HABO

+0

Ich habe meine Antwort präzisiert, aber wenn Sie sich keine gefilterten Indizes ansehen, betrachten Sie wahrscheinlich entweder einen Tabellenscan oder einen Clustered-Index-Scan, also genauso groß. Die Wurzel des Problems, das das OP brachte, ist immer noch das Design. Der Beitritt zu einem mittleren Textabschnitt ist nicht skalierbar. –

0

Nach ein wenig mehr Nachforschungen habe ich einige Fulltext-Funktionen genutzt.

sp_fulltext_keymappings mir id meine Transaktionstabelle gibt, zusammen mit dem FT docID

sys.dm_fts_index_keywords_by_document gibt mir FT DocumentID zusammen (ich, dass 'doc' = Textfeld herausgefunden) mit den einzelnen Stichwörtern darin

Sobald ich das hatte, war der Rest einfach. Obwohl ich den Begriff 'Schlüsselwort' ein bisschen mehr suchen muss ... scheint, dass die Definition variabel sein kann.

Das funktioniert nur, weil der Text, den ich suche, keinen Leerraum hat. Ich glaube, dass Sie die FTI-Konfiguration optimieren konnten, um mit anderen Szenarien zu arbeiten ... aber ich konnte nicht versprechen. Ich muss mehr im Volltext sehen.

Mein aktueller 'Beta' Code unten.

CREATE TABLE #keyMap 
    ( 
     docid INT PRIMARY KEY , 
     [key] varchar(32) NOT NULL 
    ); 
DECLARE @db_id int = db_id(N'<database name>'); 
DECLARE @table_id int = OBJECT_ID(N'Transactions'); 

INSERT INTO #keyMap 
EXEC sp_fulltext_keymappings @table_id; 

select km.[key] as transaction_id, i.[id] as item_id 
from  
    sys.dm_fts_index_keywords_by_document (@db_id, @table_id) kbd 
    INNER JOIN 
    #keyMap km ON km.[docid]=kbd.document_id 
    inner join [items] i 
    on kdb.[display_term] = i.name 
    ; 

Meine aktuelle Version des Codes enthält das Einfügen der Daten in eine Final Table. Ausführungszeit ist in 30 Sekunden, die meine Bedürfnisse für jetzt erfüllt.

Verwandte Themen