---
title: 数据倾斜导致的 Hash Join 性能问题-OceanBase数据库使用指南
description: 了解OceanBase数据库在实际应用中关于 数据倾斜导致的 Hash Join 性能问题相关的常见问题和使用技巧，帮助您快速解决 数据倾斜导致的 Hash Join 性能问题的难题。
---
切换语言

- 中文站 - 简体中文
- International - English
- 日本站 - 日本語

划线反馈

# 数据倾斜导致的 Hash Join 性能问题

更新时间：2026-05-14 09:21

适用版本： V2.1.x、V2.2.x、V3.1.x、V3.2.x 内容类型：Troubleshoot  

## 适用版本

OceanBase 数据库 V2.x、V3.x 版本。

## 问题现象

两个表的 LEFT OUTER JOIN 在 OceanBase 数据库中的执行时间比在 Oracle 中慢很多倍，其在 Oracle 和 OceanBase 数据库中的执行计划基本相同，均使用了 Hash Join。

问题 SQL：

```shell
SELECT count(*)
FROM CUST_INFO T1  LEFT JOIN CUST_DATA T4
ON T1.ORG_CODE=T4.ORG_CODE
AND T4.DATA_DATE='20220621'
WHERE T1.DATA_DATE='20220621';

```

注：两个表均使用 DATA_DATE 作为分区列。

Oracle 数据库中的执行计划：

| Description | Object owner | Object name | Cost | Cardinality |
| --- | --- | --- | --- | --- |
| SELECT STATEMENT. GOAL = ALL ROWS |  |  | 35625 | 1 |
| SORT AGGREGATE |  |  |  | 1 |
| HASH JOIN OUTER |  |  | 35625 | 444719 |
| PARTITIONLIST SINGLE |  |  | 5511 | 442181 |
| TABLE ACCESS FULL | ECRM_U1 | CUST_INFO | 5511 | 442181 |
| PARTITIONLIST SINGLE |  |  | 18748 | 5639974 |
| TABLE ACCESS FULL | ECRM_U1 | CUST_DATA | 18748 | 5639974 |

OceanBase 数据库中的执行计划：

| ID | OPERATOR | NAME | EST. ROWS | COST |
| --- | --- | --- | --- | --- |
| 0 | SCALAR GROUP BY |  | 1 | 7037748 |
| 1 | HASH JOIN OUTER |  | 222403 | 7029260 |
| 2 | TABLE SCAN | T1 | 441844 | 204241 |
| 3 | TABLE SCAN | 4T | 5640168 | 2798618 |

## 问题原因

OceanBase 数据库下性能较差的原因：

HASH JOIN 的关联条件为 `T1.ORG_CODE=T4.ORG_CODE`，`ORG_CODE` 字段在 T1 表和 T4 表中默认值为 NULL，两表中均存在大量的记录为 NULL。Hahs Join 时 T1 表中 `ORG_CODE` 为 NULL 的大量记录倾斜在 Hash Table 中，T4 表中大量 `ORG_CODE` 为 NULL 的记录去 Join Hash Table，执行效率低下。

Oracle 下性能较好的原因：

根据 SQL 规范，对 NULL 值的判断应该用 COL IS NULL 或者 COL IS NOT NULL，COL = NULL 或者 NULL = NULL 的结果是 False。在本案例中，LEFT OUTER JOIN 的关联条件 T1.ORG_CODE=T4.ORG_CODE 隐含着 T4.ORG_CODE IS NOT NULL 的语义。Oracle 数据库会自动增加 T4.ORG_CODE IS NOT NULL，因而在 Hash Join 时可以避免使用 NULL 值的记录去匹配 Hash Table。

## 解决方法

OceanBase 数据库 V4.x 版本对 Hash Join 做了优化，对于本案例中的场景会自动增加 COL IS NOT NULL 的条件，同时对于存在数据倾斜的场景也进行了自适应的 Join 方式的改进，来提升 Hash Join 的性能。

在 OceanBase 数据库 V2.x、V3.x 版本，可以通过以下方式来提升 SQL 性能。

1. 改写 SQL，增加 IS NOT NULL 的判定。添加 IS NOT NULL 判断需要遵守以下原则。

      - 对于 INNER JOIN，可以在关联条件中（ON 或 WHERE）对左表和右表同时添加 IS NOT NULL。
      - 对于 LEFT JOIN，只可以在关联条件（ON）对右表添加 IS NOT NULL，不能对左表添加 IS NOT NULL，否则可能会导致结果集不正确。

       ```shell
       SELECT count(*)
       FROM CUST_INFO T1  LEFT JOIN CUST_DATA T4
       ON T1.ORG_CODE=T4.ORG_CODE
       AND T4.DATA_DATE='20220621'
       AND T4.ORG_CODE IS NOT NULL       # 新增
       WHERE T1.DATA_DATE='20220621';

       ```
 2. 考虑使用 Nest-loop Join 或 Merge Join 来代替 Hash Join。

   ```shell
   SELECT /*+ user_nlj(t4) leading(t1 t4)*/count(*)
   FROM CUST_INFO T1  LEFT JOIN CUST_DATA T4
   ON T1.ORG_CODE=T4.ORG_CODE
   AND T4.DATA_DATE='20220621'
   WHERE T1.DATA_DATE='20220621';

   SELECT /*+ user_merge(t4) leading(t1 t4)*/count(*)
   FROM CUST_INFO T1  LEFT JOIN CUST_DATA T4
   ON T1.ORG_CODE=T4.ORG_CODE
   AND T4.DATA_DATE='20220621'
   WHERE T1.DATA_DATE='20220621';

   ```

上一篇

[因并行大导致 SQL 跑不出来的原因和解决方法](https://www.oceanbase.com/knowledge-base/oceanbase-database-1000000002397184)

下一篇

[如何排查 PX 执行卡住](https://www.oceanbase.com/knowledge-base/oceanbase-database-1000000000693224) ![有帮助](https://gw.alipayobjects.com/mdn/ob_asset/afts/img/A*y6ocSqN8cqsAAAAAAAAAAAAAARQnAQ)![无帮助](https://gw.alipayobjects.com/mdn/ob_asset/afts/img/A*BG9IQJyLHF8AAAAAAAAAAAAAARQnAQ)![反馈](https://gw.alipayobjects.com/mdn/ob_asset/afts/img/A*eTWdQKCRKHwAAAAAAAAAAAAAARQnAQ)[AI](https://www.oceanbase.com/obi) 咨询热线
