Una combinación hash por lo general (siempre?) Utiliza una exploración o al menos un rango de exploración. Una combinación hash funciona escaneando tablas de combinación izquierda y derecha (o un rango en las tablas) y construyendo una tabla hash en memoria que contiene todos los valores 'vistos' por los escaneos.
Lo que sucedió en su caso es esto: la QO notó que puede obtener todos los valores de una columna C de un índice no agrupado que contiene esta columna (como clave o como columna incluida). Ser un índice no agrupado es probablemente bastante limitado, por lo que la cantidad total de IO para escanear todo el índice no agrupado no es exagerado. El QO también consideró que el sistema tiene suficiente RAM para almacenar una tabla hash en la memoria. Cuando se compara el costo de esta consulta (un escaneo de un índice no agrupado de extremo a extremo para, digamos, 10000 páginas) con el costo de un ciclo anidado que usa búsquedas (digamos 5000 sondeos de 2-3 páginas cada una) El escaneo ganó porque requiere menos IO. Por supuesto, es en gran parte especulación de mi parte, pero estoy tratando de presentar el caso desde el punto de vista de QO, y el plan es probablemente óptimo.
Los factores que contribuyeron a esta elección plan en particular serían:
- un gran número de candidatos estimados en el lado derecho de la unión
- disponibilidad de la columna de combinación en un índice reducido no agrupado para el lado izquierdo
- montón de memoria RAM
Para una gran estimación del número de candidatos, una mejor opción que la combinación hash sólo es la fusión a unirse, y que uno requiere que la entrada sea clasificada previamente. Si el lado izquierdo puede ofrecer una ruta de acceso que garantice un pedido en la columna unida y el lado derecho tiene una posibilidad similar, entonces puede terminar con la combinación de fusión, que es la unión más rápida.
Una coincidencia hash no utiliza necesariamente un escaneo. Puede involucrar fácilmente una Búsqueda en registros particulares y luego usar los resultados de esa Búsqueda en la Partida Hash. Para un bucle anidado, está manejando un registro a la vez, por lo que es más probable que prefiera una búsqueda, pero eso no significa que un hash prefiera un escaneo, solo necesita obtener todas las filas que sean posibles. Si está filtrando en ambas tablas involucradas y tiene un índice de cobertura pero también un cálculo, puede reproducir este comportamiento. –
@Rob: No estoy vendido en eso. Me tomó un tiempo encontrar una referencia pública disponible, pero lea http://blogs.msdn.com/craigfr/archive/2006/08/10/687630.aspx sobre cómo funciona el Hash-Join, tanto la compilación como la sonda fase * lea la entrada completa en una pasada * qué tipo de reglas busca. Además, el pseudo-algoritmo establece claramente que no existe una correlación entre los lados izquierdo y derecho que determina el filtrado de la sonda. –
Derecha ... consideremos primero la instalación. Crea dos tablas, con dos campos cada una. Índice uno en el campo de filtro, incluida la columna de campo de unión. A continuación, los llenaremos con números. crear tabla dbo.table1 (id int identity (1,1) clave principal , joinfield int , filterfield int ); ir create table dbo.table2 (id int identity (1,1) clave principal , joinfield int , filterfield int ); ir crear índice ix1 en dbo.table1 (filterfield) include (joinfield); crear índice ix2 en dbo.table2 (filterfield) include (joinfield); ir –