# [FAQ] TiDB v5.x 版本 SQL 是 in 子查询使用 Hint+inl_join(t1) 不生效的原因

## Key Words

SQL in 子查询,hint,inl_join,semi_join

## Description

在 TiDB 的 in 子查询中，默认会将子查询调整为 `semi join` 进行关联，尝试在 v4.0.x 版本中，将子查询 `hint` 调整为 `Index join`，但是没有生效，通过 `explain analyze` 查询执行计划看，还是走的 `semi join`。

![image2022-9-26_11-39-14.png](/images/TiDB/know-issue-tidb-in-hint-ineffact.png)

通过 `show warning` 查询报错 `There are no matching table names for (t1) in optimizer hint /\*+ INL_JOIN(t1) \*/ or /\*+ TiDB_INLJ(t1) \*/. Mayby you can use the table alias name.`

![image2022-9-26_11-38-31.png](/images/TiDB/know-issue-tidb-in-hint-ineffect1.png)

在 v6.2.0 版本测试来看，没有复现问题，所以推测规则已经优化，其实如果没有加 `/\*+ inl_join(t1) \*/` ，实际也可以选择到 `inner join` 的。

![image2022-9-26_11-38-59.png](/images/TiDB/know-issue-tidb-in-hint-ineffect2.png)

## Content

1. TiDB 的 `in` 子查询优化，会将其 `in` 的子查询改写为 `SELECT ... FROM ... GROUP ...` 的形式，然后将 `in` 改写为普通的 `inner join` 的形式（子查询结果集小时效率更高）；

2. 参数 `tidb_opt_insubq_to_join_and_agg1 用来设置是否开` 将 `in` 子查询转化成 `inner join` 和 `aggregation`（子查询结果集比较大时可以调整该参数来获得更好的执行效率）；

3. 当前 case 遇到的情况，正常应该将子查询改写为 `inner join`，但是当前版本子查询常数列为字符串类型时，优化器暂时不支持改写成 `inner join`，所以才选择 `semi join` 方式；

## Reference

子查询优化规则将 semi join 转化为 join 和 aggregation[https://docs.pingcap.com/zh/tidb/v5.2/system-variables#tidb_opt_insubq_to_join_and_agg](https://docs.pingcap.com/zh/tidb/v5.2/system-variables#tidb_opt_insubq_to_join_and_agg)

Semi Join 介绍 [https://docs.pingcap.com/zh/tidb/v5.2/explain-subqueries#semi-join](https://docs.pingcap.com/zh/tidb/v5.2/explain-subqueries#semi-join%E5%85%B3%E8%81%94%E6%9F%A5%E8%AF%A2)

v6.2 支持 Exists 子查询的 Semi join rewrite 改写 [https://docs.pingcap.com/tidb/v6.2/subquery-optimization#exists-subquery-and---select--from-](https://docs.pingcap.com/tidb/v6.2/subquery-optimization#exists-subquery-and---select--from-)

## Affected Versions

< v5.4.1