Domanda

La tabella prodotto ha 700K record in esso. La query:

SELECT TOP 1 ID, Name FROM Product WHERE contains(Name, '"White Dress"') ORDER BY DateMadeNew desc

richiede circa 1 minuto per l'esecuzione. V'è un indice non cluster in DateMadeNew e FREETEXT indice sul nome.

Se rimuovo TOP 1 o ORDER BY -. Ci vogliono meno di 1 secondo per eseguire

Ecco il link al piano di esecuzione. http://screencast.com/t/ZDczMzg5N

appare come FullTextMatch ha più di 400K esecuzioni. Perché sta succedendo? Come può essere reso più veloce?

AGGIORNAMENTO 5/3/2010

appare come cardinalità è fuori di colpo sulle ricerche FREETEXT a più di parole:

Optimizer stima che ci siano 28K record corrispondenti 'White Dress', mentre in realtà solo 1 non c'è. http://screencast.com/t/NjM3ZjE4NjAt

Se sostituisco 'White Dress' con 'White', il numero stimato è di '27, 951' , mentre il numero reale è '28, 487' , che è molto meglio.

Sembra Optimizer sta usando solo la prima parola nella frase ricercata cardinalità.

È stato utile?

Soluzione

Modifica

http://technet.microsoft.com/en- us / library / cc721269.aspx # _Toc202506240

  

La cosa più importante è che la   corretto tipo di join viene raccolto per   query full-text. Cardinalità   la stima sul FulltextMatch STVF   è molto importante per il piano giusto.   Quindi la prima cosa da controllare è la   FulltextMatch stima di cardinalità.   Questo è il numero stimato di colpi   nel indice per la ricerca full-text   corda. Ad esempio, nella query in   Figura 3 questo dovrebbe essere vicino al   il numero di documenti contenenti le   termine ‘parola’. Nella maggior parte dei casi si deve   essere molto accurata, ma se la stima   era fuori da un lungo cammino, si potrebbe   generare piani cattivi. La stima per la   singoli termini è normalmente molto buona,   ma la stima più termini quali   frasi o e query è più complessa   dal momento che non è possibile sapere che cosa   l'intersezione dei termini nell'indice   sarà basato sulla frequenza del   termini nell'indice. Se la cardinalità   la stima è buono, un cattivo piano di   probabilmente è causata dalla query   modello di costo ottimizzatore. L'unico modo per   risolvere il problema piano è quello di utilizzare una query   AVVISO Per forzare un certo tipo di join   o OPTIMIZE FOR.

Quindi, semplicemente, non può conoscere dalle informazioni che memorizza se i 2 termini di ricerca insieme sono suscettibili di essere del tutto indipendente o comunemente trovati insieme. Forse si dovrebbe avere 2 procedure distinte una per le query sola parola che si lascia l'ottimizzatore di fare il suo roba e uno per le procedure a più di parole che si forza un piano di "abbastanza buono", a (sys.dm_fts_index_keywords potrebbe aiutare se non si desidera un taglia unica piano).

. NB: La procedura di sola parola sarebbe probabilmente necessario l'opzione WITH RECOMPILE guardando questo pezzo di questo articolo

  

In SQL Server 2008 la ricerca full-text abbiamo la possibilità di modificare il piano che viene generato sulla base di una stima di cardinalità del termine di ricerca utilizzato. Se il piano di query è fisso (come in una query con parametri all'interno di una stored procedure), questo passo non avviene. Pertanto, il piano compilato serve sempre questa domanda, anche se questo piano non è l'ideale per un determinato termine di ricerca.

risposta originale

Il nuovo piano appare ancora piuttosto male però. Sembra che esso è solo tornando 1 fila dalla parte piena di query di testo, ma la scansione di tutti i 770159 righe della tabella Product.

Come funziona questo esegue?

CREATE TABLE #tempResults
(
ID int primary key,
Name varchar(200),
DateMadeNew datetime
)

INSERT INTO #tempResults
SELECT 
      ID, Name, DateMadeNew 
      FROM Product 
      WHERE contains(Name, '"White Dress"')


SELECT TOP 1
    *
    FROM #tempResults
    ORDER BY DateMadeNew desc

Altri suggerimenti

Non riesco a vedere il piano di esecuzione legata, la polizia di rete che stanno bloccando, quindi questo è solo una supposizione ...

se è in esecuzione veloce senza l'TOP e ORDER BY, prova a fare questo:

SELECT TOP 1
    *
    FROM (SELECT 
              ID, Name, DateMadeNew 
              FROM Product 
              WHERE contains(Name, '"White Dress"')
         ) dt
    ORDER BY DateMadeNew desc
  

appare come FullTextMatch ha più di 400K esecuzioni. Perché sta succedendo?

Dal momento che si dispone di un indice combinato con TOP 1, ottimizzatore pensa che sarà meglio per attraversare l'indice, controllando ogni record per la voce.

  

Come può essere reso più veloce?

Se l'aggiornamento delle statistiche non aiuta, prova ad aggiungere un suggerimento per la vostra richiesta:

SELECT  TOP 1 *
FROM    product pt
WHERE   CONTAINS(name, '"test1"')
ORDER BY
        datemadenew DESC
OPTION (HASH JOIN)

Questo costringerà il motore di utilizzare un algoritmo HASH JOIN per unire il vostro tavolo e l'output della query full-text.

interrogazione

testo completo è considerata come una sorgente remota restituisce l'insieme di valori indicizzati da KEY INDEX previsto nella definizione FULLTEXT INDEX.

Aggiornamento:

Se i vostri usi ORM parametrizzate query, è possibile creare una guida di piano.

  • Usa Profiler per intercettare la query che il ORM invia Verbatim
  • Genera un corretto piano di in SSMS utilizzando i suggerimenti e salvarla come XML
  • Usa sp_create_plan_guide con una OPTION USE PLAN per forzare l'ottimizzatore utilizzare sempre questo piano.

ho avuto lo stesso problema in precedenza.

Il rendimento dipende da quale unico indice che si sceglie per l'indicizzazione full-text. Il mio tavolo ha due colonne uniche -. ID e article_number

La query:

select top 50 id, article_number, name, ... 
from ARTICLE 
CONTAINS(*,'"BLACK*" AND "WHITE*"')
ORDER BY ARTICLE_NUMBER

Se l'indice testo completo è collegato ad ID allora è lento a seconda della parola cercata. Se l'indice testo completo è collegato all'indice ARTICLE_NUMBER UNIQUE poi è stato sempre veloce.

Ho una migliore soluzione.

I. prima panoramica di Let proposto soluzioni come anche possono essere utilizzati in alcuni casi:

  1. OPTION (hash join) - non è buono come si può ottenere errore di "processore di query potrebbe non produrre un piano di query a causa degli hint definiti nella query Reinvia la query senza specificare alcun suggerimento e senza. utilizzando SET FORCEPLAN. "

  2. Seleziona TOP 1 * FROM (ORIGINAL_SELECT) ORDER BY ... - non è buono, quando è necessario utilizzare impaginare i risultati da voi ORIGINAL_SELECT

  3. sp_create_plan_guide - non è buona, come per l'uso plan_guide è necessario salvare piano di un'individuazione precisa SQL, questo non funzionerà per le dichiarazioni SQL dinamiche (ad esempio generati da ORM)

II. La mia soluzione contiene due parti     1. Auto unirsi tabella utilizzata per la ricerca Full Text     2. HASH Utilizzare MS SQL JOIN suggerimenti MSDN JOIN suggerimenti

Il tuo SQL:

SELECT TOP 1 ID, Name FROM Product WHERE contains(Name, '"White Dress"') 
ORDER BY DateMadeNew desc

Dovrebbe essere riscritto come:

SELECT TOP 1 p.ID, p.Name FROM Product p INNER HASH JOIN Product fts ON fts.ID = p.ID
WHERE contains(fts.Name, '"White Dress"') 
ORDER BY p.DateMadeNew desc

Se si utilizza NHibernate con / senza Castello record attivi, ho risposto in posta come intercettore scrittura per modificare la query per sostituire INNER JOIN da INNER JOIN HASH

Un paio di riflessioni su questo:

1) Avete aggiornato le statistiche sul tavolo del prodotto? Sarebbe utile per vedere le stime e il numero effettivo di righe sulle operazioni anche lì.

2) Quale versione di SQL Server stai usando? Ho avuto un problema simile con SQL Server 2008 che si è rivelato essere niente di più che non avere il Service Pack 1 installato. Installare SP1 e una query FREETEXT che stava prendendo un paio di minuti (a causa di un enorme numero di esecuzioni effettive contro reale) è andato giù a prendere un secondo.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top