Todos os produtos
Search
Central de documentação

MaxCompute:SUBQUERY_MAPJOIN HINT

Última atualização: Jun 26, 2026

Use o hint SUBQUERY_MAPJOIN para forçar o MAPJOIN em subconsultas que o MaxCompute converte em JOINs durante a execução. Esse recurso melhora o desempenho da consulta quando o resultado da subconsulta é pequeno.

Limitações

  • Tipos de subconsulta compatíveis: escalar, IN, NOT IN, EXISTS e NOT EXISTS. Subconsultas básicas (tabelas derivadas como SELECT * FROM (subquery) alias) não são compatíveis.

  • O sistema usa automaticamente o resultado da subconsulta como tabela pequena no MAPJOIN. Não é necessário especificar a tabela manualmente.

  • Se o resultado da subconsulta for grande, o MAPJOIN poderá gerar um erro de Out of Memory (OOM). Verifique se o resultado da subconsulta é uma tabela pequena antes de usar este hint. Para obter os limites de tamanho do MAPJOIN, consulte Limites.

  • Em alguns cenários, o MaxCompute não converte a subconsulta em JOIN, como na aplicação de poda de partição. Nesses casos, adicionar o hint gera um aviso, mas a consulta ainda retorna resultados. Consulte Exemplo 5: Aviso quando uma subconsulta não é convertida em JOIN.

Sintaxe

Insira /*+ subquery_mapjoin */ imediatamente após o parêntese de abertura da subconsulta. O hint deve ser o primeiro token dentro do parêntese.

Considere duas tabelas:

CREATE TABLE t1(a BIGINT, b BIGINT);
CREATE TABLE t2(a BIGINT, b BIGINT);

Veja a seguir o posicionamento correto para cada tipo de subconsulta compatível.

Subconsulta escalar

SELECT a,
       (/*+ subquery_mapjoin */ SELECT b FROM t2 WHERE a = t1.a)
FROM t1;

Subconsultas IN e NOT IN

SELECT * FROM t1 WHERE a IN     (/*+ subquery_mapjoin */ SELECT a FROM t2 WHERE b = t1.b);
SELECT * FROM t1 WHERE a NOT IN (/*+ subquery_mapjoin */ SELECT a FROM t2 WHERE b = t1.b);

Subconsultas EXISTS e NOT EXISTS

SELECT * FROM t1 WHERE EXISTS     (/*+ subquery_mapjoin */ SELECT * FROM t2 WHERE b = t1.b);
SELECT * FROM t1 WHERE NOT EXISTS (/*+ subquery_mapjoin */ SELECT * FROM t2 WHERE b = t1.b);

Posicionamento incorreto

-- Wrong: hint is inside the SELECT clause, not immediately after the opening parenthesis
SELECT * FROM t1 WHERE a IN (SELECT /*+ subquery_mapjoin */ a FROM t2 WHERE b = t1.b);

Dados de exemplo

Os exemplos abaixo usam duas tabelas: sale_detail (tabela particionada) e shop_detail. Execute os comandos a seguir para criá-las e carregar dados de amostra.

-- Create a partitioned table
CREATE TABLE IF NOT EXISTS sale_detail
(
  shop_name     STRING,
  customer_id   STRING,
  total_price   DOUBLE
)
PARTITIONED BY (sale_date STRING, region STRING);

-- Add partitions
ALTER TABLE sale_detail
  ADD PARTITION (sale_date='2013', region='china')
  PARTITION (sale_date='2014', region='shanghai');

-- Load data
INSERT INTO sale_detail PARTITION (sale_date='2013', region='china')
  VALUES ('s1','c1',100.1), ('s2','c2',100.2), ('s3','c3',100.3);
INSERT INTO sale_detail PARTITION (sale_date='2014', region='shanghai')
  VALUES ('null','c5',null), ('s6','c6',100.4), ('s7','c7',100.5);

-- Create shop_detail from the 2013 partition
SET odps.sql.allow.fullscan=true;
CREATE TABLE shop_detail AS
  SELECT shop_name, customer_id, total_price
  FROM sale_detail
  WHERE sale_date='2013' AND region='china';

Conteúdo de sale_detail

+------------+-------------+-------------+------------+------------+
| shop_name  | customer_id | total_price | sale_date  | region     |
+------------+-------------+-------------+------------+------------+
| s1         | c1          | 100.1       | 2013       | china      |
| s2         | c2          | 100.2       | 2013       | china      |
| s3         | c3          | 100.3       | 2013       | china      |
| null       | c5          | NULL        | 2014       | shanghai   |
| s6         | c6          | 100.4       | 2014       | shanghai   |
| s7         | c7          | 100.5       | 2014       | shanghai   |
+------------+-------------+-------------+------------+------------+

Conteúdo de shop_detail

+------------+-------------+-------------+
| shop_name  | customer_id | total_price |
+------------+-------------+-------------+
| s1         | c1          | 100.1       |
| s2         | c2          | 100.2       |
| s3         | c3          | 100.3       |
+------------+-------------+-------------+

Exemplos

Exemplo 1: Subconsulta escalar

Retorne todas as linhas de shop_detail com pelo menos uma linha correspondente em sale_detail.

SET odps.sql.allow.fullscan=true;
SELECT * FROM shop_detail
WHERE (/*+ subquery_mapjoin */ SELECT COUNT(*) FROM sale_detail
       WHERE sale_detail.shop_name = shop_detail.shop_name) >= 1;

Resultado:

+------------+-------------+-------------+
| shop_name  | customer_id | total_price |
+------------+-------------+-------------+
| s1         | c1          | 100.1       |
| s2         | c2          | 100.2       |
| s3         | c3          | 100.3       |
+------------+-------------+-------------+

Exemplo 2: Subconsulta IN

Obtenha as linhas de sale_detail cujo total_price aparece em shop_detail.

SET odps.sql.allow.fullscan=true;
SELECT * FROM sale_detail
WHERE total_price IN (/*+ subquery_mapjoin */ SELECT total_price FROM shop_detail
                      WHERE customer_id = shop_detail.customer_id);

Resultado:

+------------+-------------+-------------+------------+------------+
| shop_name  | customer_id | total_price | sale_date  | region     |
+------------+-------------+-------------+------------+------------+
| s1         | c1          | 100.1       | 2013       | china      |
| s2         | c2          | 100.2       | 2013       | china      |
| s3         | c3          | 100.3       | 2013       | china      |
+------------+-------------+-------------+------------+------------+

Exemplo 3: Subconsulta EXISTS

Selecione as linhas de sale_detail com customer_id correspondente em shop_detail.

SET odps.sql.allow.fullscan=true;
SELECT * FROM sale_detail
WHERE EXISTS (/*+ subquery_mapjoin */ SELECT * FROM shop_detail
              WHERE customer_id = sale_detail.customer_id);

Resultado:

+------------+-------------+-------------+------------+------------+
| shop_name  | customer_id | total_price | sale_date  | region     |
+------------+-------------+-------------+------------+------------+
| s1         | c1          | 100.1       | 2013       | china      |
| s2         | c2          | 100.2       | 2013       | china      |
| s3         | c3          | 100.3       | 2013       | china      |
+------------+-------------+-------------+------------+------------+

Exemplo 4: Subconsultas básicas não são compatíveis

Este hint não funciona com subconsultas básicas (tabelas derivadas). A consulta a seguir falha.

SET odps.sql.allow.fullscan=true;
SELECT * FROM (/*+ subquery_mapjoin */ SELECT shop_name FROM sale_detail) a;

Erro:

FAILED: ODPS-0130161:[1,16] Parse exception - invalid subquery_mapjoin hint, should only be used for scalar/in/exists subquery

Exemplo 5: Aviso quando uma subconsulta não é convertida em JOIN

Quando uma subconsulta filtra por uma coluna de partição, o MaxCompute a mantém como subconsulta para permitir a poda de partição, em vez de convertê-la em JOIN. Nesse caso, o hint não tem efeito e o sistema emite um aviso, mas a consulta ainda retorna resultados.

Primeiro, adicione uma coluna sale_date à tabela shop_detail e recarregue os dados:

ALTER TABLE shop_detail ADD COLUMNS IF NOT EXISTS (sale_date STRING);
INSERT OVERWRITE TABLE shop_detail
  VALUES ('s1','c1',100.1,'2013'), ('s2','c2',100.2,'2013'), ('s3','c3',100.3,'2013');

Em seguida, execute a consulta com avisos ativados:

-- Enable warning output (skip this if your project already outputs warnings)
SET odps.compiler.warning.disable=false;

-- sale_date is a partition column of sale_detail.
-- MaxCompute keeps this subquery as-is (no JOIN conversion) to support partition pruning.
-- The hint is ignored and the system issues a warning.
SELECT * FROM sale_detail
WHERE sale_date IN (/*+ subquery_mapjoin */ SELECT sale_date FROM shop_detail);

Resultado:

+------------+-------------+-------------+------------+------------+
| shop_name  | customer_id | total_price | sale_date  | region     |
+------------+-------------+-------------+------------+------------+
| s1         | c1          | 100.1       | 2013       | china      |
| s2         | c2          | 100.2       | 2013       | china      |
| s3         | c3          | 100.3       | 2013       | china      |
+------------+-------------+-------------+------------+------------+

Aviso:

WARNING:[1,47]  subquery_mapjoin hint does not work because the subquery is not converted to join

Próximos passos

  • Subconsultas — visão geral dos tipos de subconsulta compatíveis com o SQL do MaxCompute

  • Limites do MAPJOIN — restrições de tamanho de tabela pequena para MAPJOIN