2011-09-17 2 views
-1

Exécution de SQL Server 2008, j'ai une table avec quelques millions de lignes de vidage d'informations de journal à partir d'une application. J'essaie de comprendre comment écrire le meilleur indice pour obtenir des informations pertinentes.Index SQL Server optimal sur la sous-chaîne?

La table ressemble à ceci. Juste un échantillon, les données de message réelles sont longues.

CREATE TABLE #Info(
    [infoID] [int] IDENTITY(1,1) NOT NULL, 
    [ActionHappened] [datetime] NOT NULL, 
    [PartialMessage] [nvarchar](1500) NULL, 
    [FullMessage] [nvarchar](max) NULL, 
CONSTRAINT [pk_info] PRIMARY KEY CLUSTERED([infoID] ASC) 
     WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, 
      ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]) ON [PRIMARY] 

Insert Into #Info Values (GETDATE() , 'Thread:05;D:Start;Msg:Activity A' , 'Thread:05;D:Start;Msg:Activity A abcdegghijklmnopqrstuvwxyvabcdegghijklmnopqrstuvwxyvabcdegghijklmnopqrstuvwxyvabcdegghijklmnopqrstuvwxyvabcdegghijklmnopqrstuvwxyvabcdegghijklmnopqrstuvwxyvabcdegghijklmnopqrstuvwxyvabcdegghijklmnopqrstuvwxyvabcdegghijklmnopqrstuvwxyvabcdegghijklmnopqrstuvwxyvabcdegghijklmnopqrstuvwxyv') 
Insert Into #Info Values (dateadd(minute , 3 , GETDATE()) , 'Thread:05;D:Start;Msg:Activity B' , 'Thread:05;D:Start;Msg:Activity B abcdegghijklmnopqrstuvwxyvabcdegghijklmnopqrstuvwxyvabcdegghijklmnopqrstuvwxyvabcdegghijklmnopqrstuvwxyvabcdegghijklmnopqrstuvwxyvabcdegghijklmnopqrstuvwxyvabcdegghijklmnopqrstuvwxyvabcdegghijklmnopqrstuvwxyvabcdegghijklmnopqrstuvwxyvabcdegghijklmnopqrstuvwxyvabcdegghijklmnopqrstuvwxyv') 
Insert Into #Info Values (dateadd(minute , 6 , GETDATE()) , 'Thread:05;D:Start;Msg:Activity C' , 'Thread:05;D:Start;Msg:Activity D abcdegghijklmnopqrstuvwxyvabcdegghijklmnopqrstuvwxyvabcdegghijklmnopqrstuvwxyvabcdegghijklmnopqrstuvwxyvabcdegghijklmnopqrstuvwxyvabcdegghijklmnopqrstuvwxyvabcdegghijklmnopqrstuvwxyvabcdegghijklmnopqrstuvwxyvabcdegghijklmnopqrstuvwxyvabcdegghijklmnopqrstuvwxyvabcdegghijklmnopqrstuvwxyv') 
Insert Into #Info Values (dateadd(minute , 9 , GETDATE()) , 'Thread:05;D:Start;Msg:Activity D' , 'Thread:05;D:Start;Msg:Activity E abcdegghijklmnopqrstuvwxyvabcdegghijklmnopqrstuvwxyvabcdegghijklmnopqrstuvwxyvabcdegghijklmnopqrstuvwxyvabcdegghijklmnopqrstuvwxyvabcdegghijklmnopqrstuvwxyvabcdegghijklmnopqrstuvwxyvabcdegghijklmnopqrstuvwxyvabcdegghijklmnopqrstuvwxyvabcdegghijklmnopqrstuvwxyvabcdegghijklmnopqrstuvwxyv') 
Insert Into #Info Values (dateadd(minute , 15 , GETDATE()) , 'Thread:05;D:Start;Msg:Activity E' , 'Thread:05;D:Start;Msg:Activity F abcdegghijklmnopqrstuvwxyvabcdegghijklmnopqrstuvwxyvabcdegghijklmnopqrstuvwxyvabcdegghijklmnopqrstuvwxyvabcdegghijklmnopqrstuvwxyvabcdegghijklmnopqrstuvwxyvabcdegghijklmnopqrstuvwxyvabcdegghijklmnopqrstuvwxyvabcdegghijklmnopqrstuvwxyvabcdegghijklmnopqrstuvwxyvabcdegghijklmnopqrstuvwxyv') 

J'ai besoin de choisir parmi PartialMessage, en ignorant tout avant la deuxième virgule, puis revenir ActionHappened et FullMessage. Par exemple je veux

select ActionHappened, FullMessage 
from #Info 
where PartialMessage Like '%Activity D%' 

mais bien sûr pas de balayage de table et soft-recherche à l'intérieur de chaque colonne.

Toutes les idées ont été appréciées.

Merci.

+6

Vous devez les diviser en colonnes séparées pour 'thread',' start', 'activity' quoi que ce soit au lieu de le stocker dans une chaîne concaténée qui est impossible à indexer et que vous avez besoin de décomposer pour interroger. L'atomicité est une exigence pour même [première forme normale] (http://en.wikipedia.org/wiki/First_normal_form#Atomicity) –

+0

Totalement d'accord avec la réponse précédente (+1). Une autre option peut être XML. Vous pouvez transformer PartialMessage en un champ XML, puis vous pouvez créer un [index XML] (http://msdn.microsoft.com/en-us/library/ms345121%28v=sql.90%29.aspx) (voir aussi [Optimisations de performances pour le type de données XML dans SQL Server 2005] (http://msdn.microsoft.com/en-us/library/ms345118%28v=sql.90%29.aspx)). Enfin, vous pouvez interroger les valeurs XML en utilisant [xquery] (http://technet.microsoft.com/en-us/library/ms189075.aspx). –

+0

J'aimerais avoir la possibilité de modifier le schéma de la table. Mais je ne le fais pas. Voilà pourquoi je suis ici. :) – Snowy

Répondre

1

Pourriez-vous créer une vue indexée pour séparer les champs, comme le suggère Martin? Ce qui suit pourrait fonctionner, mais avec la taille du champ, cela pourrait ne pas être bénéfique.

  • Créer un champ appelé ReversePartialMessage
  • L'utilisation d'un déclencheur pour remplir ce champ avec le REVERSE (partialMessage)
  • Ajouter un index sur deux PartialMessage et ReversePartialMessage champs
  • Faire la clause WHERE

    où PartialMessage comme 'activité D% Et ReversePartialMessage Comme « D ytivitcA% »

Cependant, avec la taille de PartialMessage, je ne sais pas si l'effort de ces indices gagnerait beaucoup. Si le champ peut être raccourci, ces index peuvent être pratiques. Si vous créez les index, assurez-vous de visiter le plan d'exécution pour voir s'ils sont réellement utilisés. L'optimiseur peut décider qu'une analyse de table est plus efficace que les index. Le travail de fusion de la sortie des deux index, en particulier avec des valeurs clés aussi grandes, pourrait ne pas donner de gains significatifs ...