La respuesta, como de costumbre (está bien, la mayoría de las veces), se encuentra en el plan de ejecución.
Hay ciertos operadores que requieren que todas las filas lleguen a ellos antes de que puedan comenzar a procesar esas filas y pasarlas aguas abajo, por ejemplo:
- Hash Join (en la construcción de la tabla hash)
- Hash Match
- Ordenar (excepto Hash Flow Distinct)
Se les llama bloqueo o operadores de detención y avance debido a esto, y a menudo se eligen cuando el optimizador piensa que tendrá que procesar una gran cantidad de datos para encontrar sus datos.
Hay otros operadores que pueden comenzar a transmitir o pasar cualquier fila encontrada inmediatamente.
- Bucles anidados
- Index soporta Merge Joins
- Agregados de flujo
Cuando las consultas comienzan a devolver datos de inmediato, pero no terminan de inmediato, generalmente es una señal de que el optimizador eligió un plan para ubicar y devolver algunas filas rápidamente utilizando operadores que tienen un costo inicial más bajo.
Esto puede suceder debido a los objetivos de fila introducidos por usted o por el optimizador.
También puede ocurrir si se elige un mal plan por alguna razón (falta de SARGability, rastreo de parámetros, estadísticas insuficientes, etc.), pero eso requiere más investigación para descubrirlo.
Para obtener más información, consulte el blog de Rob Farley aquí.
Y la serie de Paul White sobre goles en fila aquí , aquí , aquí y aquí .
También debe tenerse en cuenta que, si habla de SSMS, las filas solo aparecen una vez que se ha llenado un búfer completo, no solo de forma involuntaria.
WHERE t.x IN (<complex SELECT subquery>)
IZQUIERDA equivalenteLEFT JOIN (<complex SELECT subquery>) AS r ON r.x = t.x .... WHERE r.x IS NULL
, entonces la subconsulta también tendrá que ser evaluada (así que el mismo plan complejo con el NO EN versión).NOT EXISTS
pero OracleNOT IN
en las consultas. Pero hoy debe considerarse como un error en el generador de planes