web-dev-qa-db-fra.com

Le moyen le plus rapide de trouver une chaîne par sous-chaîne dans SQL?

J'ai une énorme table avec 2 colonnes: id et titre. ID est Bigint et je suis libre de choisir Type de titre Colonne: Varchar, Char, Texte, peu importe. Le titre de la colonne contient des chaînes de texte aléatoire telles que "ABCDEFG", "Q", "AllyourbaseBelongTous" avec un maximum de 255 caractères.

Ma tâche consiste à obtenir des chaînes par substration donnée. Les sous-chaînes ont également une longueur aléatoire et peuvent être démarrages, moyens ou fin des chaînes. La façon la plus évidente de l'exécuter:

SELECT * FROM t LIKE '%abc%'

Je me fiche de l'insertion, je n'ai besoin que de choisir rapidement. Que puis-je faire pour effectuer la recherche aussi vite que possible?

J'utilise MS SQL Server 2008 R2, la recherche de texte intégral sera inutile, autant que je sache.

22
msergey

Si vous souhaitez utiliser moins d'espace que la réponse de Randy et que vous êtes une répétition considérable dans vos données, vous pouvez créer une structure de données d'arborescence N-ARY où chaque bord est le caractère suivant et accrocher chaque chaîne et la sous-chaîne de la fin de vos données.

Vous numérotez les nœuds en profondeur premier ordre. Ensuite, vous pouvez créer une table avec jusqu'à 255 lignes pour chacun de vos enregistrements, avec l'ID de votre enregistrement et l'ID de nœud de votre arbre qui correspond à la chaîne ou à la sous-chaîne de suivi. Ensuite, lorsque vous effectuez une recherche, vous trouvez l'ID de nœud qui représente la chaîne que vous recherchez (et toutes les sous-chaînes de suivi) et effectuez une recherche de gamme.

7
antlersoft

On dirait que vous avez exclu toutes les bonnes alternatives.

Vous savez déjà que votre requête

SELECT * FROM t WHERE TITLE LIKE '%abc%'

n'utilisera pas d'index, il fera une numérisation de table complète à chaque fois.

Si vous étiez sûr que la ficelle était à la début du champ, vous pourriez faire

SELECT * FROM t WHERE TITLE LIKE 'abc%'

qui utiliserait un index sur le titre.

Êtes-vous sûr que la recherche de texte complet ne vous aiderait pas ici?

En fonction de vos besoins en entreprise, j'ai parfois utilisé la logique suivante:

  • Faire une requête "commence par" (LIKE 'abc%') Tout d'abord, qui utilisera un index.
  • Selon si des lignes sont renvoyées (ou combien), passez à la recherche "plus difficile" qui fera la balayage complète (LIKE '%abc%')

Cela dépend de ce dont vous avez besoin, bien sûr, mais j'ai utilisé cela dans des situations où je peux d'abord montrer les résultats les plus faciles et les plus courants, et ne passerai que la requête plus difficile lorsque cela est nécessaire.

4
BradC

Vous pouvez ajouter une autre colonne calculée sur la table: la longueur de titres comme Len (titre) persistait. Cela stockerait la longueur de la colonne "Titre". Créez un index à ce sujet.

En outre, ajoutez une autre colonne calculée appelée: reversetitle comme inverse (titre) persistait.

Maintenant, lorsque quelqu'un recherche un mot clé, vérifiez si la longueur de mot-clé est identique à la longueur de titres. Si oui, faites une recherche "=". Si la longueur de mot-clé est inférieure à la longueur de la longueur de titres, alors faites un. Mais d'abord faire un titre comme "ABC%", puis faire un retournement comme "CBA%". Semblable à l'approche de Brad - c'est-à-dire que vous faites la prochaine requête difficile que si nécessaire.

De plus, si les règles 80-20 s'appliquent à vos mots-clés/sous-chaînes (c'est-à-dire si la plupart des recherches sont sur une minorité des mots-clés), vous pouvez également envisager de faire une sorte de mise en cache. Par exemple: dites que vous constatez que de nombreux utilisateurs recherchent le mot-clé "ABC" et cette recherche de mots-clés renvoie les enregistrements avec IDS 20, 22, 24, 25 - Vous pouvez stocker ceci dans une table séparée et avoir cette indexée. Et maintenant, lorsque quelqu'un recherche un nouveau mot clé, consultez d'abord dans cette table "cache" pour voir si la recherche était déjà effectuée par un utilisateur antérieur. Si oui, pas besoin de regarder à nouveau dans la table principale. Renvoie simplement les résultats du tableau "Cache".

Vous pouvez également combiner ce qui précède avec SQL Server Textsearch. (En supposant que vous avez une raison valable de ne pas l'utiliser). Mais vous pouvez néanmoins utiliser le texte de la recherche de texte en tant que liste de résultats. puis exécutez une requête SQL contre votre table pour obtenir des résultats exacts à l'aide des identifiants retournés par la recherche de texte sous forme de paramètre avec votre mot clé.

Tout cela suppose évidemment que vous devez utiliser SQL. Sinon, vous pouvez explorer quelque chose comme Apache Solr.

3

Créer une vue Index Il existe une nouvelle fonctionnalité dans SQL Créer un index sur la colonne que vous devez rechercher et utiliser cette vue après votre recherche qui donnera votre résultat plus rapide.

0
KuldipMCA

Faites une chose, utilisez la clé primaire sur une colonne spécifique et indice sous forme de cluster.

Ensuite, recherchez à l'aide de n'importe quelle méthode (carte wild ou = ou non), elle effectuera une recherche de manière optimale car la table est déjà sous forme en clustere, elle sait donc où il peut trouver (car la colonne est déjà en forme de tri))

0
Mohit Verma
  1. Utilisez [~ # ~ # ~] ascii [~ # ~] Charset avec Indexation en cluster La colonne Char. Le charert influence les performances de recherche en raison de la taille de données sur la RAM et le disque. Le goulot d'étranglement est souvent des E/S.
  2. Votre colonne est de 255 caractères de temps pour que vous puissiez utiliser un index normal sur votre champ de caractère plutôt que sur le texte intégral, ce qui est plus rapide. Ne sélectionnez pas de colonnes inutiles dans votre relevé de sélection.
  3. Enfin, ajoutez plus RAM au serveur et à augmenter Taille de cache.
0
Uğur Gümüşhan