一个简单的查询执行计划走偏-2

【 TiDB 使用环境】生产环境
【 TiDB 版本】v7.1.3
【遇到的问题:问题现象及影响】
t 表主键 ob_object_id
t2表有唯一性索引 F1_6511+F2_6511

执行计划异常:
当t表指定一条具体数据的时候,执行计划正常,t t2 关联走 index_join
当t表指定一条数据(来自一个子查询时),执行计划异常,t t2关联走hash_join

index_join:

mysql> explain analyze
    ->   SELECT t.* FROM
    ->   WIND.TB_OBJECT_6757 t,wind.tb_object_6511 t2
    -> WHERE t.ob_object_id in('5efcb925-d53b-4676-ac90-7353391ac49e')
    ->   AND f9_6757 = 1
    ->   and f1_6511 = f1_6757 
    ->   AND f3_6511 = '2010400017';
+---------------------------------+------------+---------+-----------+----------------------------------------------------+
| id                              | estRows    | actRows | task      | access object                                      |
+---------------------------------+------------+---------+-----------+----------------------------------------------------+
| IndexJoin_12                    | 0.87       | 0       | root      |                                                    |
| ├─Selection_25(Build)           | 0.84       | 0       | root      |                                                   
| │ └─Point_Get_24                | 1.00       | 1       | root      | table:TB_OBJECT_6757, index:PRIMARY(OB_OBJECT_ID)
| └─IndexLookUp_11(Probe)         | 0.87       | 0       | root      |                                                   
|   ├─IndexRangeScan_8(Build)     | 5006121.81 | 0       | cop[tikv] | table:t2, index:UIDX_TB6511_F1F2(F1_6511, F2_6511)
|   └─Selection_10(Probe)         | 0.87       | 0       | cop[tikv] |                                                   
|     └─TableRowIDScan_9          | 5006121.81 | 0       | cop[tikv] | table:t2                                          
+---------------------------------+------------+---------+-----------+----------------------------------------------------+
**7 rows in set (0.00 sec)**

hash_join 导致全表扫描:

mysql>   explain analyze
    ->   SELECT t.* FROM
    ->   WIND.TB_OBJECT_6757 t,wind.tb_object_6511 t2
    -> WHERE t.ob_object_id in(SELECT REC_ID FROM wind_replicator.wind_tb_object_6757_oplog limit 1)
    ->   AND f9_6757 = 1
    ->   and f1_6511 = f1_6757
    ->   AND f3_6511 = '2010400017';
+------------------------------------+--------------+-----------+-----------+--------------------------------------------------------------------------------+
| id                                 | estRows      | actRows   | task      | access object                                                                  |
+------------------------------------+--------------+-----------+-----------+--------------------------------------------------------------------------------+
| HashJoin_18                        | 1.00         | 0         | root      |                                                                                |
| ├─HashAgg_72(Build)                | 1.00         | 1         | root      |                                                                               
| │ └─Limit_73                       | 1.00         | 1         | root      |                                                                              
| │   └─IndexReader_78               | 1.00         | 1         | root      | partition:all                                                                
| │     └─Limit_77                   | 1.00         | 1         | cop[tikv] |                                                                              
| │       └─IndexFullScan_76         | 1.00         | 1         | cop[tikv] | table:WIND_TB_OBJECT_6757_OPLOG, index:idx_WINDTBOBJECT6757OPLOG_RECID(REC_ID
| └─IndexHashJoin_27(Probe)          | 115.71       | 2275499   | root      |                                                                               
|   ├─TableReader_68(Build)          | 44.35        | 663505    | root      |                                                                               
|   │ └─Selection_67                 | 44.35        | 663505    | cop[tikv] |                                                                              
|   │   └─TableFullScan_66           | 254688690.00 | 254669900 | cop[tikv] | table:t2                                                                     
|   └─IndexLookUp_24(Probe)          | 115.71       | 2275499   | root      |                                                                               
|     ├─IndexRangeScan_21(Build)     | 137.79       | 5290761   | cop[tikv] | table:t, index:IDX_TB6757_F1(F1_6757)                                         
|     └─Selection_23(Probe)          | 115.71       | 2275499   | cop[tikv] |                                                                               
|       └─TableRowIDScan_22          | 137.79       | 5290761   | cop[tikv] | table:t                                                                       
+------------------------------------+--------------+-----------+-----------+--------------------------------------------------------------------------------+
**14 rows in set (18.99 sec)**

你用in肯定要表关联

– 使用 NO_DECORRELATE() 行不
explain select * from t1 where t1.a < (select /*+ NO_DECORRELATE() */ sum(t2.a) from t2 where t2.b = t1.b);

in 是为了圈定t的数据范围,再和t2关联, 现在的问题是t 和 t2的关联走了hash_join, 但是t2明明有索引

不行,还是hash_join, t2 全表扫描

limit 1去掉 ,改成max(Id)试试

根据这个优化一下把 子查询相关的优化 | PingCAP 文档中心

子查询改成 select max(rec_id) from wind_replicator.wind_tb_object_6757_oplog ,问题依旧

改写成join吧,别用in

把子查询拉平,改成join, t2继续全表扫描
如果只有t和t1关联,就没问题

把子查询拉平,改成join, t2继续全表扫描

看下统计信息模型是什么


如果是 1 试试改为 2 统计信息都收集一遍。

tidb_cost_model_version 1
tidb_row_format_version 2

生产环境能随便更改吗? 会不会引起性能瓶颈? 是否可以先用这几张表试试?

最好是测试下。

试了一下,设置tidb_cost_model_version为2,重新分析了下表,问题依旧

用hint让t表和子查询那张表先关联试试

t表和子查询直接关联没问题,不需要hint

请把执行计划详细信息文本和表结构贴出来看下,可以用代码块,

类似这样的

TiDB没有no_merge这样的hint吗

补充上去了