6
votes

Comment forcer SQL Server à traiter contient des clauses avant les clauses?

J'ai une requête SQL qui utilise à la fois des clauses et l'index de texte complet contient des clauses. La requête est construite dynamiquement à partir du code et comprend un nombre variable de l'endroit et contient des clauses.

Pour que la requête soit rapide, il est très important que l'indice de texte complet soit recherché avant que le reste des critères ne soit appliqué.

Toutefois, SQL Server choisit de traiter les clauses où les clauses contiennent des clauses contenant et que les analyses des tables et la requête est très lente.

Je suis capable de réécrire cela en utilisant deux questions et une table temporaire. Quand je le fais, la requête exécute 10 fois plus vite. Mais je ne veux pas faire cela dans le code qui crée la requête parce qu'il est trop complexe.

Y a-t-il un moyen de forcer SQL Server à traiter la conception avant toute autre chose? Je ne peux pas forcer un plan (plan d'utilisation) car la requête est construite de manière dynamique et varie beaucoup.

Remarque: j'ai le même problème sur SQL Server 2005 et SQL Server 2008.


2 commentaires

Ce bit sonne problématique - "La requête est construite de manière dynamique et varie de manière dynamique et varie" - car cela peut signifier que le traitement contient d'abord après peut ne pas être optimal, donc Même si vous réussissez à attacher les mains de l'optimiseur, il peut ne pas avoir les effets désirés.


@Damien_the_unbeliever: La seule solution parfaite serait une solution dans l'optimiseur SQL Server lui-même. Je ne sais pas pourquoi il ne comprend pas que le traitement de la contient est d'abord beaucoup plus rapide. Donc, toute autre solution ne sera pas optimale dans tous les cas. Cependant, je sais que dans notre traitement, le traitement de la contient sera d'abord plus rapide la plupart du temps. Mais vous avez raison; Je ne peux pas le garantir.


3 Réponses :


0
votes

Essayez de le faire avec 2 requêtes sans tables Temps:

SELECT * 
FROM table
WHERE id IN (
    SELECT id 
    FROM table 
    WHERE contains_criterias
) 
AND further_where_classes


0 commentaires

2
votes

Vous pouvez signaler votre intention de l'optimiseur comme celle-ci xxx pré>

Cependant, SQL est déclarative: vous dites ce que em> vous voulez, pas em> pour le faire. Donc, l'optimiseur peut décider d'ignorer l'imbrication ci-dessus. P>

Vous pouvez forcer la table dérivée avec contient pour être matérialisée avant que la clause classique où est appliquée. Je ne garantirai pas la performance. P>

SELECT
   *
FROM
    (
    SELECT TOP 2000000000
       *
    FROM
       ....
    WHERE
       CONTAINS
    ORDER BY
       SomeID
    ) T1
WHERE
   (normal conditions)


7 commentaires

Hmm, Nice, j'allais suggérer une boucle Inscrivez-vous si les résultats contenant sont toujours connus pour être petit en nombre, mais c'est beaucoup plus propre, meilleur des deux mondes.


@gbn: Si vous utilisez un CTE, cela ne signifie pas que Force Évaluation en premier?


@Yuck: Considérons une macro CTE une macro comme ma table dérivée. C'est-à-dire que j'aurais pu utiliser un CTE à la place. Même résultat ...


@GBN: intéressant. J'étais sous le - erroné apparemment - impression qu'un CTE ressemblait davantage à une table tempentielle implicite qu'une sous-requête.


@Yuck: Cela peut être quand récursif, mais pour ce scénario, c'est une macro de rendre votre code meilleur :-)


@TAO, pouvez-vous s'il vous plaît poster votre solution de convivialité de votre boucle. Bien que moins propre, il pourrait être plus facile de mettre dans notre constructeur de requêtes. Merci


Je confirme que le truc sur top fonctionne même si utilisé dans . Comme où dans (Select Top ....) N'a même pas besoin de faire la sous-requête



0
votes

Comme je l'ai noté ci-dessus, il ne s'agit pas aussi propre de "matérialiser" la table dérivée que la clause supérieure que @gbn proposait, mais une ligne de jointure de boucle oblige l'ordre d'évaluation et a travaillé pour moi dans le passé. (certes généralement avec deux tables différentes impliquées). Il y a quelques problèmes que:

  • La requête est laide
  • Vous n'obtenez toujours aucune garantie que l'autre où les paramètres ne sont pas évalués avant la jointure (je serai intéressé de voir ce que vous obtenez)

    Voici cependant, étant donné que vous avez demandé: xxx


1 commentaires

Merci d'avoir pris le temps de poster la réponse.