¿Tamaño máximo para una consulta de SQL Server? ¿Cláusula IN? ¿Existe un mejor enfoque [duplicado]

Resuelto BuddyJoe asked hace 14 años • 4 respuestas

Posible duplicado:
T-SQL DONDE col IN (…)

¿Cuál es el tamaño máximo para una consulta de SQL Server? (# de caracteres)

¿Tamaño máximo para una cláusula IN? Creo que vi algo acerca de que Oracle tenía un límite de 1000 elementos, pero se podría solucionar esto haciendo AND con 2 IN juntos. ¿Problema similar en SQL Server?

ACTUALIZACIÓN Entonces, ¿cuál sería el mejor enfoque si necesito tomar, digamos, 1000 GUID de otro sistema (base de datos no relacional) y hacer un "UNIRSE en el código" contra SQL Server? ¿Es enviar la lista de 1000 GUID a una cláusula IN? ¿O existe otra técnica que funcione de manera más eficiente?

No he probado esto, pero me pregunto si podría enviar los GUID como un documento XML. Por ejemplo

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

y luego hacer algún tipo de XQuery JOIN contra el Doc y la Tabla. ¿Menos eficiente que la cláusula IN de 1000 elementos?

BuddyJoe avatar Dec 09 '09 03:12 BuddyJoe
Aceptado

Cada lote de SQL debe ajustarse al límite de tamaño de lote : 65.536 * Tamaño del paquete de red.

Aparte de eso, su consulta está limitada por las condiciones de tiempo de ejecución. Generalmente se quedará sin tamaño de pila porque x IN (a,b,c) no es más que x=a OR x=b OR x=c lo que crea un árbol de expresión similar a x=a OR (x=b OR (x =c)), por lo que se vuelve muy profundo con una gran cantidad de OR. SQL 7 alcanzaría un SO con valores de aproximadamente 10k en IN , pero hoy en día las pilas son mucho más profundas (debido a x64), por lo que puede llegar bastante profundo.

Actualizar

Ya encontró el artículo de Erland sobre el tema de pasar listas/matrices a SQL Server. Con SQL 2008 también tiene parámetros con valores de tabla que le permiten pasar una tabla de datos completa como un parámetro de tipo de tabla único y unirse a ella.

XML y XPath es otra solución 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;
Remus Rusanu avatar Dec 08 '2009 21:12 Remus Rusanu

Los máximos de SQL Server se divulgan en http://msdn.microsoft.com/en-us/library/ms143432.aspx (esta es la versión 2008)

Una consulta SQL puede ser varchar(max), pero se muestra limitada a 65,536 * tamaño de paquete de red, pero incluso entonces lo que es más probable que lo haga tropezar son los 2100 parámetros por consulta. Si SQL elige parametrizar los valores literales en la cláusula in, creo que primero alcanzarías ese límite, pero no lo he probado.

Editar: Pruébelo, incluso bajo parametrización forzada sobrevivió. Realicé una prueba rápida y la ejecuté con 30k elementos dentro de la cláusula In. (Servidor SQL 2005)

En 100.000 artículos, tomó algún tiempo y luego cayó con:

Mensaje 8623, nivel 16, estado 1, línea 1 El procesador de consultas se quedó sin recursos internos y no pudo generar un plan de consulta. Este es un evento poco común y solo se espera para consultas extremadamente complejas o consultas que hacen referencia a una gran cantidad de tablas o particiones. Simplifique la consulta. Si cree que recibió este mensaje por error, comuníquese con el Servicio de atención al cliente para obtener más información.

Así que 30k es posible, pero sólo porque puedas hacerlo no significa que debas hacerlo :)

Editar: Continuación debido a una pregunta adicional.

50k funcionaron, pero 60k desaparecieron, así que, por cierto, en algún lugar de mi banco de pruebas.

En términos de cómo hacer esa combinación de valores sin usar una cláusula in grande, personalmente crearía una tabla temporal, insertaría los valores en esa tabla temporal, la indexaría y luego la usaría en una combinación, dándole las mejores oportunidades para optimizar las uniones. (La generación del índice en la tabla temporal creará estadísticas para él, lo que ayudará al optimizador como regla general, aunque 1000 GUID no encontrarán las estadísticas demasiado útiles).

Andrew avatar Dec 08 '2009 20:12 Andrew

Por lote, 65536 * Tamaño del paquete de red , que es 4k, es decir, 256 MB

Sin embargo, IN se detendrá mucho antes, pero no es preciso.

Terminas con errores de memoria pero no recuerdo el error exacto. Un IN enorme será ineficiente de todos modos.

Editar: Remus me recordó: el error es sobre "tamaño de pila"

gbn avatar Dec 08 '2009 20:12 gbn

¿Puedes cargar los GUID en una tabla temporal y luego hacer una

... WHERE var IN SELECT guid FROM #scratchtable
DaveE avatar Dec 08 '2009 21:12 DaveE