
# Join顺序的Hint
#### 功能描述
指明join的顺序，包括内外表顺序。
#### 语法格式
- 单层圆括号()，仅指定join顺序，不指定内外表顺序。
```
leading(join_table_list) 
leading(@block_name join_table_list)
```
- 双层圆括号(())，同时指定join顺序和内外表顺序，内外表顺序仅在最外层生效。
```
leading((join_table_list)) 
leading(@block_name (join_table_list))
```
- 单层方括号\[\]，同时指定\[\]这层的join顺序和内外表顺序。
```
leading[join_table_list]
leading[@block_name join_table_list]
```
- 单层圆括号()和单层方括号\[\]混合使用，同时指定join顺序和任意层内外表顺序。圆括号()这一层只指定join顺序，不指定内外表顺序，方括号\[\]这一层同时指定join顺序和内外表顺序。
```
leading(join_table_list1 [join_table_list2])
leading[join_table_list1 [join_table_list2]]
leading[join_table_list1 (join_table_list2)]
leading(@block_name join_table_list1 [join_table_list2])
leading[@block_name join_table_list1 [join_table_list2]]
leading[@block_name join_table_list1 (join_table_list2)]
```
![](https://support.huaweicloud.com/devg-dws/public_sys-resources/notice_3.0-zh-cn.png)
单层方括号\[\]可以和单层圆括号()混合使用，指定任意层的内外表顺序。不支持单层\[\]和双层(())一起使用。
#### 参数说明
- **join_table_list**
  为表示表join顺序的hint字符串，可以包含当前层的任意个表（别名），或对于子查询提升的场景，也可以包含子查询的hint别名，同时任意表可以使用括号指定优先级，表之间使用空格分隔。
  join table list中指定的表需要满足以下要求，否则会报语义错误：
  - list中的表必须在当前层或提升的子查询中存在。
  
  - list中的表在当前层或提升的子查询中必须是唯一的。如果不唯一，需要使用不同的别名进行区分。
  
  - 同一个表只能在list里出现一次。
  
  - 如果表存在别名，则list中的表必须使用别名。
   
  ![](https://support.huaweicloud.com/devg-dws/public_sys-resources/note_3.0-zh-cn.png)
  表的语法格式如下：
  ```
  [schema.]table[@block_name]
  ```
  表名可以带schema，也可以带所在子查询语句块提升前的block_name。
  子查询语句块在优化器进行优化重写时发生提升，则该block_name会与leading中block_name不同。
  
 
- **block_name**
  语句块的block_name。表示该hint在block_name对应的子查询语句块中生效。
  ![](https://support.huaweicloud.com/devg-dws/public_sys-resources/notice_3.0-zh-cn.png)
  - 默认为语句生成block_name。
  
  
  
  - CN轻量化不生成block_name。
  
  
  
  - create table as select、select into、select、insert、update、delete、merge语句生成block_name。
  
  
  
  - block_name的命名规则：
    - 为select、insert、update、delete、merge语句自动生成blockname，block_name的命名格式分别为sel$n、ins$n、upd$n、del$n、mer$n，n从1开始计数，不同类型语句之间，计数不累加，同一类型语句之间计数累加。 例如：
      ```
      INSERT INTO t SELECT * FROM t1 WHERE a1 IN (select * from t2);
      ```
      --------sel$2-------
      -----------------------sel$1----------------------
      --------------------------------ins$1---------------------------
      
    
    - 在优化器之前递归为每个语句块分配block_name。
      首先为当前语句块根据语句类型分配block_name，然后按照下面的顺序进行遍历，并为其中的语句块分配block_name：
      1. 遍历目标列
      
      2. 遍历merge语句的源表中的目标列
      
      3. 遍历merge语句中的action（update/insert）
      
      4. 遍历returning子句
      
      5. 遍历from中的join条件和where条件（join条件优先于where条件）
      
      6. 如果是集合操作，遍历集合的各个分支（union/intersect/except）
      
      7. 遍历having子句
      
      8. 遍历limit offset子句
      
      9. 遍历limit count子句
      
      10. 遍历cte
      
      11. 遍历from后的表
      
      12. 遍历upsert子句
        
    
    - 在优化器的重写阶段，由于fulljoin、cte inline、物化视图重写、inlist2join、or转换、multi count(distinct)、magicset、lazyagg、子查询/子链接提升等重写优化，都会构造新的子查询，此时会对新构造的子查询也应用上面分配block_name的递归处理，block_name的编号计数在之前的基础上进行累加。
    
    - 优化器重写阶段，发生子查询提升时，内层子查询中的表被提升到外层查询中，内层子查询被消除。此时，被提升的表可能会和外层查询中的表同名，所以在表中记录其原本所属block_name来区分来自不同查询块中的两个相同表。
     
    
例如：
leading(t1 t2 t3 t4 t5)表示：t1, t2, t3, t4, t5先join，五表join顺序及内外表不限。
leading((t1 t2 t3 t4 t5))表示：t1和t2先join，t2做内表；再和t3 join，t3做内表；再和t4 join，t4做内表；再和t5 join，t5做内表。
leading(t1 (t2 t3 t4) t5)表示：t2, t3, t4先join，内外表不限；再和t1, t5 join，内外表不限。
leading((t1 (t2 t3 t4) t5))表示：t2, t3, t4先join，内外表不限；在最外层，t1再和t2, t3, t4的join表join，t1为外表，再和t5 join，t5为内表。
leading((t1 (t2 t3) t4 t5)) leading((t3 t2))表示：t2, t3先join，t2做内表；然后再和t1 join，t2, t3的join表做内表；然后再依次跟t4, t5做join，t4, t5做内表。
leading\[t1 \[t2 t3\]\]等价于leading((t1 (t2 t3))) leading((t2 t3))。
leading(t1 \[t2 t3\])等价于leading(t1 t2 t3) leading((t2 t3))。
leading\[@sel$1 t1@sel$1 \[t2@sel$2 t3@sel$2\]\]表示：t2、t3位于子查询中，子查询被提升后，和t1进行join，其表示先t2和t3 join，t2为外表，t3为内表；然后再和t1 join，t1为外表，t2, t3的join表做内表。
#### 示例
对[示例](https://support.huaweicloud.com/devg-dws/dws_04_0455.html#ZH-CN_TOPIC_0000002053159594__zh-cn_topic_0000001658028034_section671421102912)中原语句使用如下hint:
```
explain
select /*+ leading((((((store_sales store) promotion) item) customer) ad2) store_returns) leading((store store_sales))*/ i_product_name product_name ...
```
该hint表示：表之间的join关系是：store_sales和store先join， store_sales做内表，然后依次跟promotion, item, customer, ad2, store_returns做join。生成计划如下所示：
![](https://support.huaweicloud.com/devg-dws/figure/zh-cn_image_0000001510402845.png "点击放大")
图中计划顶端warning的提示详见[Hint的错误、冲突及告警](https://support.huaweicloud.com/devg-dws/dws_04_0464.html)的说明。
