web-dev-qa-db-fra.com

Taille maximale pour une requête SQL Server? Clause IN? Est-ce qu'il y a une meilleure approche

Duplicate possible:
T-SQL WHERE col (IN) (…)

Quelle est la taille maximale d'une requête SQL Server? (nombre de caractères)

Taille maximale pour une clause IN? Je pense avoir vu quelque chose à propos du fait qu’Oracle avait une limite de 1 000 articles, mais vous pourriez contourner cela avec ANDing 2 IN ensemble. Problème similaire dans SQL Server?

[~ # ~] mise à jour [~ # ~] Quelle serait donc la meilleure approche si je dois utiliser 1000 GUID d’un autre système (non relationnel)? Base de données) et effectuez une opération "JOIN in code" sur SQL Server? S'agit-il de soumettre la liste des 1000 GUID à une clause IN? Ou existe-t-il une autre technique plus efficace?

Je n'ai pas testé cela, mais je me demande si je pourrais soumettre les GUID en tant que doc XML. Par exemple

<guids>
    <guid>809674df-1c22-46eb-bf9a-33dc78beb44a</guid>
    <guid>257f537f-9c6b-4f14-a90c-ee613b4287f3</guid>
</guids>

et ensuite faire une sorte de XQuery JOIN contre le Doc et la Table. Moins efficace que la clause 1000 item IN?

87
BuddyJoe

Chaque lot SQL doit correspondre à Taille maximale du lot : 65 536 * Taille du paquet réseau.

En dehors de cela, votre requête est limitée par les conditions d'exécution. Il manquera généralement de taille de pile car x IN (a, b, c) n’est autre que x = a OR x = b OR x = c qui crée un arbre d’expression similaire à x = a OR (x = b OR (x = c))), de sorte qu’il est très profond avec un grand nombre de OR. SQL 7 frapperait un SO à environ 10k valeurs dans le IN , mais les piles sont de nos jours beaucoup plus profondes (à cause de x64), donc ça peut aller assez Profond.

Mettre à jour

Vous avez déjà trouvé l'article d'Erland sur le thème du passage de listes/tableaux à SQL Server. Avec SQL 2008, vous avez également Paramètres de table qui vous permettent de transmettre un DataTable complet en tant que paramètre de type table unique et de le rejoindre.

XML et XPath sont une autre solution viable:

SELECT ...
FROM Table
JOIN (
   SELECT x.value(N'.',N'uniqueidentifier') as guid
   FROM @values.nodes(N'/guids/guid') t(x)) as guids
 ON Table.guid = guids.guid;
73
Remus Rusanu

Les valeurs maximales de SQL Server sont divulguées http://msdn.Microsoft.com/en-us/library/ms143432.aspx (version 2008)

Une requête SQL peut être une variable maximum (varchar), mais sa taille est limitée à 65 536 * Taille du paquet réseau, mais même dans ce cas, les 2100 paramètres par requête sont susceptibles de vous tromper. Si SQL choisit de paramétrer les valeurs littérales dans la clause in, je pense que vous atteindriez cette limite en premier, mais je ne l'ai pas testée.

Edit: Testez-le, même sous un paramétrage forcé, il a survécu. J'ai lancé un test rapide et je l'ai exécuté avec 30 000 éléments dans la clause In. (SQL Server 2005)

À 100k éléments, cela a pris un certain temps puis abandonné avec:

Msg 8623, niveau 16, état 1, ligne 1 Le processeur de requête a épuisé ses ressources internes et n'a pas pu créer de plan de requête. Il s'agit d'un événement rare et attendu uniquement pour les requêtes extrêmement complexes ou faisant référence à un très grand nombre de tables ou de partitions. S'il vous plaît simplifier la requête. Si vous pensez avoir reçu ce message par erreur, contactez le support technique pour plus d'informations.

Donc 30k est possible, mais ce n’est pas parce que vous pouvez le faire que vous devriez: :)

Edit: Suite en raison d'une question supplémentaire.

50k a fonctionné, mais 60k ont ​​décroché, donc quelque part sur mon banc d'essai.

Pour ce qui est de faire cette jointure de valeurs sans utiliser une clause large, personnellement, je créerais une table temporaire, insérerais les valeurs dans cette table temporaire, l’indexerais puis l’utiliserais dans une jointure, ce qui lui donnerait les meilleures chances de réussir. optimise les jointures. (La génération de l'index sur la table temporaire créera des statistiques pour celle-ci, ce qui aidera en règle générale l'optimiseur, bien que 1000 GUID ne trouvent pas les statistiques trop utiles.)

36
Andrew

Par lot, 65536 * Taille du paquet résea , soit 4 Ko, soit 256 Mo

Cependant, IN s'arrêtera bien avant mais ce n'est pas précis.

Vous vous retrouvez avec des erreurs de mémoire mais je ne me souviens pas de l'erreur exacte. Un énorme IN sera de toute façon inefficace.

Edit: Remus m'a rappelé que l'erreur concernait la "taille de la pile"

12
gbn

Pouvez-vous charger les GUID dans une table de travail, puis effectuez une

... WHERE var IN SELECT guid FROM #scratchtable
7
DaveE