# [FAQ] 带有 NOT IN 子查询的 SQL 执行慢

## Key Words

CARTESIAN，笛卡尔积，Null-Aware

## Description

包含 NOT IN 子查询的 SQL，可能存在执行较慢或长时间跑不出结果的情况，查看执行计划发现子查询被转换为 CARTESIAN anti semi join，如下例所示：

```sql
mysql> create table t1(a int, b int);
mysql> create table t2(a int not null, b int);
mysql> explain select * from t1 where a not in (select a from t2);
+-----------------------------+----------+-----------+---------------+---------------------------------------------------------------+
| id                          | estRows  | task      | access object | operator info                                                 |
+-----------------------------+----------+-----------+---------------+---------------------------------------------------------------+
| HashJoin_8                  | 8000.00  | root      |               | CARTESIAN anti semi join, other cond:eq(test.t1.a, test.t2.a) |
| ├─TableReader_12(Build)     | 10000.00 | root      |               | data:TableFullScan_11                                         |
| │ └─TableFullScan_11        | 10000.00 | cop[tikv] | table:t2      | keep order:false, stats:pseudo                                |
| └─TableReader_10(Probe)     | 10000.00 | root      |               | data:TableFullScan_9                                          |
|   └─TableFullScan_9         | 10000.00 | cop[tikv] | table:t1      | keep order:false, stats:pseudo                                |
+-----------------------------+----------+-----------+---------------+---------------------------------------------------------------+
```

## Content

由于 NOT IN 具有特殊的三值属性（true、false 和 NULL），如果两侧的 Join key 可能存在 NULL 的情况，转换为 Join 时需要对 NULL 进行特殊处理。v6.3 版本之前 TiDB 还不支持 Null-Aware 优化，所以实现上采用了笛卡尔积加过滤 (filter) 的方式，执行效率不高。

v6.3 版本对于 NOT IN 子查询产生的 ANTI JOIN 支持 Null Aware Hash Join 的执行方式，通过开启变量 tidb_enable_null_aware_anti_join 使用该特性。

下推到 TiFlash 的 HashJoin 算子也包括 CARTESIAN anti semi join（v6.5 版本 TiFlash 还不支持 Null-Aware 优化）的执行方式，且存在内存放大的已知问题 [https://github.com/pingcap/tiflash/issues/6730](https://github.com/pingcap/tiflash/issues/6730) 可能导致 OOM，该问题影响所有支持 mpp 的历史版本，后续会陆续修复。 
