> ## Documentation Index
> Fetch the complete documentation index at: https://private-7c7dfe99-parallel-read-in-order-multi-part.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# ajustes de sesión join_*

> Ajustes de sesión de ClickHouse en el grupo generado join_*.

export const VersionHistory = ({rows = []}) => {
  if (rows.length === 0) {
    return null;
  }
  const headers = ["Versión", "Valor predeterminado", "Comentario"];
  const border = "1px solid rgba(128, 128, 128, 0.3)";
  const cell = {
    border,
    padding: "0.25rem 0.5rem",
    textAlign: "start",
    verticalAlign: "top"
  };
  return <details className="not-prose" style={{
    border,
    borderRadius: "0.5rem",
    margin: "0.5rem 0",
    padding: "0.5rem 0.75rem",
    fontSize: "0.8125rem",
    lineHeight: "1.125rem"
  }}>
      <summary style={{
    cursor: "pointer",
    fontWeight: 600,
    opacity: 0.72
  }}>
        Historial de versiones
      </summary>
      <table style={{
    borderCollapse: "collapse",
    width: "100%",
    margin: "0.5rem 0 0"
  }}>
        <thead>
          <tr>
            {headers.map(header => <th key={header} style={{
    ...cell,
    fontWeight: 600,
    opacity: 0.72
  }}>
                {header}
              </th>)}
          </tr>
        </thead>
        <tbody>
          {rows.map((row, row_index) => <tr key={row.id ?? row_index}>
              {(row.items ?? []).map((item, item_index) => <td key={item_index} style={{
    ...cell,
    overflowWrap: "anywhere"
  }}>
                  {item?.label}
                </td>)}
            </tr>)}
        </tbody>
      </table>
    </details>;
};

export const SettingsInfoBlock = ({type, default_value, changeable_without_restart}) => {
  return <div className="not-prose" style={{
    display: "flex",
    flexWrap: "wrap",
    alignItems: "baseline",
    columnGap: "0.5rem",
    rowGap: "0.125rem",
    margin: "0.375rem 0",
    fontSize: "0.8125rem",
    lineHeight: "1.125rem"
  }}>
      <div style={{
    fontWeight: 600,
    opacity: 0.72
  }}>Tipo</div>
      <div style={{
    overflowWrap: "anywhere"
  }}>{type}</div>
      <div style={{
    fontWeight: 600,
    opacity: 0.72,
    marginInlineStart: "0.5rem"
  }}>Predeterminado</div>
      <div style={{
    overflowWrap: "anywhere"
  }}>{default_value}</div>
      {changeable_without_restart && <div style={{
    fontWeight: 600,
    opacity: 0.72,
    marginInlineStart: "0.5rem"
  }}>
          Modificable sin reiniciar
        </div>}
      {changeable_without_restart && <div style={{
    overflowWrap: "anywhere"
  }}>
          {changeable_without_restart}
        </div>}
    </div>;
};

Estas configuraciones están disponibles en [system.settings](/es/reference/system-tables/settings) y se autogeneran a partir del [código fuente](https://github.com/ClickHouse/ClickHouse/blob/master/src/Core/Settings.cpp).

## join\_algorithm

<SettingsInfoBlock type="JoinAlgorithm" default_value="direct,parallel_hash,hash,ie_join" />

<VersionHistory rows={[{"id": "row-1","items": [{"label": "26.8"},{"label": "direct,parallel_hash,hash,ie_join"},{"label": "Se añadió `ie_join` a la lista predeterminada, por lo que un join cuya sección `ON` solo tiene condiciones de desigualdad se ejecuta con IEJoin en lugar de un `CROSS JOIN` con un filtro. Al estar al final, solo se utiliza cuando no se aplican los demás algoritmos."}]}, {"id": "row-2","items": [{"label": "24.12"},{"label": "direct,parallel_hash,hash"},{"label": "'default' quedó obsoleto en favor de algoritmos join especificados explícitamente; además, ahora se prefiere parallel_hash a hash"}]}]} />

Especifica qué algoritmo [JOIN](/es/reference/statements/select/join) se utiliza.

Se pueden especificar varios algoritmos, y se elegirá uno disponible para una consulta concreta en función de tipo/estrictez y del motor de tabla.

Que un algoritmo basado en hash vuelque a disco no forma parte de esta elección: [`max_bytes_before_external_join`](/es/reference/settings/session-settings/max-bytes#max_bytes_before_external_join) / [`max_bytes_ratio_before_external_join`](/es/reference/settings/session-settings/max-bytes#max_bytes_ratio_before_external_join) son el umbral de volcado para todos ellos (y una vez que uno de los dos es distinto de cero, `enable_adaptive_memory_spill_scheduler` puede volcar el join incluso antes, bajo memory pressure), y [`max_rows_in_join`](/es/reference/settings/session-settings/max-rows#max_rows_in_join) / [`max_bytes_in_join`](/es/reference/settings/session-settings/max-bytes#max_bytes_in_join) un límite estricto para todos ellos, salvo que `legacy_join_size_limits_trigger_spilling` convierta de nuevo ambos límites en disparadores de volcado a disco. El valor que elija determina cómo vuelca un join: `grace_hash` particiona la tabla derecha desde el primer bloque, mientras que `hash` y `parallel_hash` la recopilan en memoria y cambian de estrategia una vez superado el umbral.

La mayoría de los algoritmos afectan a una consulta solo cuando son los seleccionados para ella. Sin embargo, algunos cambian la planificación simplemente por estar incluidos —incluso como alternativa de menor prioridad que finalmente no se selecciona—, porque la decisión se toma antes de elegir el algoritmo. Hay dos efectos de este tipo:

* La inferencia de tipos de las join keys se vuelve más estricta (un merge join no puede combinar claves de tipos diferentes, por ejemplo, `String` y `Nullable(String)`). Esto puede cambiar los tipos de resultado de las columnas `USING` y puede hacer que un join en una tabla con motor `Join` falle con `TYPE_MISMATCH`. Se activa con `full_sorting_merge` y `parallel_full_sorting_merge`.
* `ORDER BY ... LIMIT` en el lado preservado de un join obtiene una ordenación explícita en lugar de una lectura en orden de clave primaria, porque se supone que el join interrumpe la lectura ordenada (un merge join inserta su propia ordenación previa al join; un partial merge join vuelve a ordenar los bloques izquierdos; un join que puede producir bloques retrasados tampoco propaga la lectura ordenada). El resultado es el mismo, pero el plan es menos eficiente. Se activa con `full_sorting_merge`, `parallel_full_sorting_merge`, `partial_merge`, `prefer_partial_merge`, `grace_hash` y `auto`, y también con un valor distinto de cero de `max_bytes_before_external_join` / `max_bytes_ratio_before_external_join`.

Ambos se aplican incluso cuando la consulta finalmente se ejecuta con `hash` u otro algoritmo. Si esto no es deseable, no incluya los algoritmos anteriores en `join_algorithm` para las consultas afectadas.

Valores posibles:

* grace\_hash

Se utiliza [Grace hash join](https://en.wikipedia.org/wiki/Hash_join#Grace_hash_join). Grace hash ofrece una opción de algoritmo que permite realizar joins complejos con buen rendimiento y limitar el uso de memoria.

`grace_hash` es externo desde el primer bloque: la tabla derecha se particiona de inmediato, mientras que `hash` y `parallel_hash` la recopilan primero en memoria y solo la particionan cuando supera el umbral de volcado. Elíjalo cuando ya sepa que el lado derecho no cabrá en memoria y quiera omitir la fase en memoria. El umbral de volcado es el mismo que utiliza cualquier algoritmo hash, [`max_bytes_before_external_join`](/es/reference/settings/session-settings/max-bytes#max_bytes_before_external_join) / [`max_bytes_ratio_before_external_join`](/es/reference/settings/session-settings/max-bytes#max_bytes_ratio_before_external_join), y uno de los dos debe ser distinto de cero salvo que `legacy_join_size_limits_trigger_spilling` esté activado. Sin un umbral, `grace_hash` se omite en favor del siguiente algoritmo de la lista, y se rechaza si es el único.

La primera fase de un grace join lee la tabla derecha y la divide en N buckets según el valor hash de las columnas clave (inicialmente, N es `grace_hash_join_initial_buckets`). Esto se hace de forma que cada bucket pueda procesarse de manera independiente. Las filas del primer bucket se añaden a una hash table en memoria, mientras que las demás se guardan en disco. Si la hash table crece por encima del umbral de volcado, se incrementa el número de buckets junto con el bucket asignado a cada fila. Todas las filas que no pertenecen al bucket actual se vuelcan y se reasignan.

Admite `INNER/LEFT/RIGHT/FULL ALL/ANY JOIN`.

* hash

Se utiliza el [algoritmo hash join](https://en.wikipedia.org/wiki/Hash_join). Es la implementación más genérica, compatible con todas las combinaciones de tipo y estrictez y con múltiples join keys combinadas con `OR` en la sección `JOIN ON`.

Al usar el algoritmo `hash`, la parte derecha del `JOIN` se carga en la RAM.

* parallel\_hash

Una variante del `hash` join que divide los datos en buckets y construye varias hashtables en lugar de una sola de forma concurrente para acelerar este proceso.

Al usar el algoritmo `parallel_hash`, la parte derecha del `JOIN` se carga en la RAM.

* partial\_merge

Una variante del [algoritmo sort-merge](https://en.wikipedia.org/wiki/Sort-merge_join), en la que solo la tabla derecha se ordena por completo.

`RIGHT JOIN` y `FULL JOIN` solo son compatibles con la estrictez `ALL` (`SEMI`, `ANTI`, `ANY` y `ASOF` no son compatibles).

Al usar el algoritmo `partial_merge`, ClickHouse ordena los datos y los vuelca al disco. El algoritmo `partial_merge` de ClickHouse difiere ligeramente de la implementación clásica. Primero, ClickHouse ordena la tabla derecha por las claves de combinación en bloques y crea un índice min-max para los bloques ordenados. Luego ordena partes de la tabla izquierda por la `join key` y las combina con la tabla derecha. El índice min-max también se utiliza para omitir bloques innecesarios de la tabla derecha.

* direct

El algoritmo `direct` (también conocido como nested loop) realiza una lookup en la tabla derecha usando como claves las filas de la tabla izquierda.
Es compatible con almacenamientos especiales como [Dictionary](/es/reference/engines/table-engines/special/dictionary), [EmbeddedRocksDB](/es/reference/engines/table-engines/integrations/embedded-rocksdb) y tablas [MergeTree](/es/reference/engines/table-engines/mergetree-family/mergetree).

Para las tablas MergeTree, el algoritmo envía los filtros de join key directamente a la storage layer. Esto puede ser más eficiente cuando la clave puede usar el primary key index de la tabla para lookups; de lo contrario, realiza escaneos completos de la tabla derecha para cada bloque de la tabla izquierda.

Admite joins `INNER` y `LEFT`, y solo join keys de igualdad de una sola columna sin otras condiciones.

* auto

Cuando se establece en `auto`, primero se prueba `hash` join y el algoritmo cambia dinámicamente a otro algoritmo si se supera el memory limit.

* full\_sorting\_merge

[Algoritmo sort-merge](https://en.wikipedia.org/wiki/Sort-merge_join) con ordenación completa de las tablas combinadas antes de realizar el join.

* ie\_join

El algoritmo [IEJoin](https://vldb.org/pvldb/vol8/p2074-khayyat.pdf) basado en ordenación para un `JOIN` cuya sección `ON` tiene dos comparaciones de desigualdad (`<`, `<=`, `>`, `>=`) entre expresiones de las tablas combinadas. Admite `ALL INNER/LEFT/RIGHT/FULL JOIN` y `SEMI`/`ANTI` `LEFT/RIGHT JOIN`.

La posición en la lista establece la prioridad: si aparece después de otros algoritmos, como en el valor predeterminado, IEJoin se usa solo cuando estos no se aplican (la sección `ON` no tiene condiciones de igualdad); si aparece primero, se usa siempre que la sección `ON` tenga dos condiciones de desigualdad. Las condiciones restantes (incluidas las igualdades) se aplican como filtro sobre el resultado del join para `ALL INNER JOIN`, y se evalúan dentro del operador como una condición residual que afecta a la coincidencia para los demás tipos. Cuando la sección `ON` tiene más de dos condiciones de desigualdad aptas, las dos que utiliza el algoritmo se eligen según su selectividad estimada a partir de las estadísticas min/max de las columnas (consulte el tipo `basic` en [Estadísticas de columnas](/es/reference/engines/table-engines/mergetree-family/mergetree#column-statistics)); cuando las estimaciones no están disponibles (no hay estadísticas o [`use_statistics`](/es/reference/settings/session-settings/use-statistics#use_statistics) está desactivado), se utilizan las dos primeras en el orden sintáctico. Sin `ie_join` en la lista, un `INNER JOIN` con solo condiciones de desigualdad se ejecuta como un `CROSS JOIN` con un filtro, y los demás tipos no son compatibles.

Ambas entradas se acumulan en memoria antes de realizar el join: [`max_rows_in_join`](/es/reference/settings/session-settings/max-rows#max_rows_in_join) y [`max_bytes_in_join`](/es/reference/settings/session-settings/max-bytes#max_bytes_in_join) limitan la entrada acumulada de ambos lados en conjunto (no solo la del lado derecho), y la acción en caso de desbordamiento se define mediante [`join_overflow_mode`](/es/reference/settings/session-settings/join#join_overflow_mode); los índices de ordenación que el operador construye sobre la entrada acumulada no se contabilizan en el límite. El propio operador de join se ejecuta en un único thread; solo las ordenaciones de las entradas previas al join se paralelizan.

* parallel\_full\_sorting\_merge

Igual que `full_sorting_merge`, pero los joins de igualdad compatibles con hash se segmentan según el hash de las join keys en merge joins independientes por segmento que se ejecutan en paralelo (hasta `max_threads`), en lugar de un único merge join. Esto mantiene el bajo consumo de memoria en streaming de un merge join a la vez que aprovecha todos los threads, y el resultado no queda ordenado.

La segmentación por hash según las join keys se aplica únicamente a joins de igualdad simples sobre tipos de clave cuyo hash concuerde con la comparación del merge join, y solo cuando ninguno de los lados esté ya ordenado. Se omite en estos casos:

* Joins `ASOF` y tipos de clave de coma flotante / `JSON` / `Object` / `Dynamic`: sus hashes no son coherentes con la comparación del merge join, por lo que claves iguales podrían terminar en segmentos diferentes.
* Lados que ya están ordenados (una lectura de MergeTree en orden o cualquier entrada preordenada): una dispersión que preserve el orden en los merges por segmento puede bloquear la canalización. En su lugar se conservan la lectura en orden y su optimización `read_in_order_use_virtual_row`.
* Mientras el iniciador crea un plan distribuido (`make_distributed_plan`), porque la ordenación dispersa no se puede serializar para la ejecución remota. El plan local de un solo fragmento y los fragmentos por trabajador se vuelven a optimizar con esa configuración desactivada, por lo que aún pueden segmentarse.

Omitirla desactiva solo esta reescritura, no el paralelismo en general: el join se ejecuta como un único `full_sorting_merge`, y los lados MergeTree que leen en orden aún pueden segmentarse en el origen mediante rangos de clave primaria (que se ordenan por la misma comparación que usa el join, por lo que las claves iguales permanecen juntas) cuando `query_plan_join_shard_by_pk_ranges` está habilitado.

* prefer\_partial\_merge

ClickHouse siempre intenta usar el join `partial_merge` si es posible; de lo contrario, usa `hash`. *Obsoleto*, igual que `partial_merge,hash`.

* default (obsoleto)

Valor heredado; no lo utilice más.
Igual que `direct,hash`, es decir, intenta usar un direct join y un hash join (en este orden).

## join\_any\_take\_last\_row

<SettingsInfoBlock type="Bool" default_value="0" />

Cambia el comportamiento de las operaciones JOIN con estrictez `ANY` cuando la tabla derecha tiene más de una fila coincidente para una clave.

<Note>
  Esta configuración se aplica a las tablas con motor [`Join`](/es/reference/engines/table-engines/special/join) y a los algoritmos de join basados en hash.

  Si un join se construye en paralelo, el orden de las filas puede no ser determinista. Esto significa que `join_any_take_last_row = 1` puede devolver una fila no determinista en las consultas `ANY JOIN`.
</Note>

Valores posibles:

* 0 — Si la tabla derecha tiene más de una fila coincidente, solo se une la primera fila encontrada.
* 1 — Si la tabla derecha tiene más de una fila coincidente, solo se une la última fila encontrada.

Véase también:

* [cláusula JOIN](/es/reference/statements/select/join)
* [motor de tabla Join](/es/reference/engines/table-engines/special/join)
* [join\_default\_strictness](/es/reference/settings/session-settings/join#join_default_strictness)

## join\_default\_strictness

<SettingsInfoBlock type="JoinStrictness" default_value="ALL" />

Establece la estrictez predeterminada para las [cláusulas JOIN](/es/reference/statements/select/join).

Valores posibles:

* `ALL` — Si la tabla de la derecha tiene varias filas coincidentes, ClickHouse crea un [producto cartesiano](https://en.wikipedia.org/wiki/Cartesian_product) a partir de las filas coincidentes. Este es el comportamiento normal de `JOIN` en standard SQL.
* `ANY` — Si la tabla de la derecha tiene varias filas coincidentes, solo se combina la primera que se encuentra. Si la tabla de la derecha tiene solo una fila coincidente, los resultados de `ANY` y `ALL` son los mismos.
* `ASOF` — Para combinar secuencias con una coincidencia incierta.
* `Cadena vacía` — Si no se especifica `ALL` o `ANY` en la consulta, ClickHouse lanza una excepción.

## join\_on\_disk\_max\_files\_to\_merge

<SettingsInfoBlock type="UInt64" default_value="64" />

Limita el número de archivos que se pueden usar para la ordenación paralela en operaciones MergeJoin cuando se ejecutan en disco.

Cuanto mayor sea el valor de esta configuración, más RAM se usará y menos operaciones de E/S en disco se necesitarán.

Valores posibles:

* Cualquier entero positivo a partir de 2.

## join\_output\_by\_rowlist\_perkey\_rows\_threshold

<SettingsInfoBlock type="UInt64" default_value="5" />

<VersionHistory rows={[{"id": "row-1","items": [{"label": "24.9"},{"label": "5"},{"label": "El límite inferior del promedio de filas por clave en la tabla de la derecha para determinar si la salida debe generarse como una lista de filas en hash join."}]}]} />

El límite inferior del promedio de filas por clave en la tabla de la derecha para determinar si la salida debe generarse como una lista de filas en hash join.

## join\_overflow\_mode

<SettingsInfoBlock type="OverflowMode" default_value="throw" />

Define qué acción realiza ClickHouse cuando una operación JOIN alcanza cualquiera de los siguientes límites:

* [max\_bytes\_in\_join](/es/reference/settings/session-settings/max-bytes#max_bytes_in_join)
* [max\_rows\_in\_join](/es/reference/settings/session-settings/max-rows#max_rows_in_join)

Todos los valores de [`join_algorithm`](/es/reference/settings/session-settings/join#join_algorithm)
basados en hash aplican esta configuración, incluidos los que vuelcan a disco: alcanzar el
límite detiene la consulta en lugar de provocar un volcado. La excepción es
`legacy_join_size_limits_trigger_spilling`: con esta opción activada, la parte de un join que
ya se ejecuta en disco sigue volcando en vez de actuar según esta configuración.
`ie_join` también la aplica, sobre la entrada que acumula de ambos lados. `partial_merge` sigue
gestionando los límites cambiando de estrategia; consulte
[`join_algorithm`](/es/reference/settings/session-settings/join#join_algorithm).

Valores posibles:

* `THROW` — ClickHouse lanza una excepción y detiene la consulta.
* `BREAK` — ClickHouse detiene la consulta y no lanza ninguna excepción.

Valor predeterminado: `THROW`.

**Véase también**

* [cláusula JOIN](/es/reference/statements/select/join)
* [motor de tabla Join](/es/reference/engines/table-engines/special/join)

## join\_use\_nulls

<SettingsInfoBlock type="Bool" default_value="0" />

Establece el comportamiento de [JOIN](/es/reference/statements/select/join). Al combinar tablas, pueden aparecer celdas vacías. ClickHouse las rellena de forma distinta según esta configuración.

Valores posibles:

* 0 — Las celdas vacías se rellenan con el valor predeterminado del tipo del campo correspondiente.
* 1 — `JOIN` se comporta igual que en SQL estándar. El tipo del campo correspondiente se convierte en [Nullable](/es/reference/data-types/nullable), y las celdas vacías se rellenan con [NULL](/es/reference/syntax).
