关于buckets问题

你好

提供的统计信息目前相同,希望配置在贵司测试环境复现,需要提供下:

  1. ANALYZE TABLE tab1 index index_tab1_cid WITH 10 BUCKETS 时,命令行执行 explain sql 语句返回的文本信息提供下并导出执行计划。
  2. ANALYZE TABLE tab1 操作相同,提供贵司执行计划不同的信息,并导出执行计划。
  1. 每一次执行 ANALYZE TABLE tab1; 走错索引了,再执行ANALYZE TABLE tab1 index index_tab1_cid WITH 10 BUCKETS 没有用了,还是走错索引,我把统计信息导出来了文件no_bucket_20200604.jason

  2. 执行drop stats tab1 后再执行 ANALYZE TABLE tab1就能走对了索引,我导出执行计划为:dropstats_20200604.jason,这是我在测试环境模似的结果,之后再多次执行 ANALYZE TABLE tab1都对走对索引

:ok_hand:

@frankliu747 你好,我是 TiDB 的研发同学,我用 dropstats.jason 和 no-bucket.jason 在你的版本都复现了一下, 都是选用的 index_designmaterial_organid_cid (organid,categoryid) 这个索引。

根据你之前的回复,你应该是想让优化器选用 index_designmaterial_cid (categoryid) 这个索引?

我后面用 hint use index(index_designmaterial_cid) ,让优化器选中了这个索引,其代价如下:


可以看到上图用了 (categoryid) 索引,且代价为 2657444。

而如果不加这个 hint,会选中 index_designmaterial_organid_cid 这个索引,结果如下:

可见优化器对这俩的代价估计,是较为接近的,统计信息中 bucket 的大小改变后,可能会一些随机的误差波动,导致选中的索引在这俩间切换,这就是加或者不加 bucket 参数造成计划变动的原因。

而观察你的 query,里面主要的两个条件:

  1. categoryId IN (...)
  2. organId IN ('C00000868', 'C00000868')

如果用 index_designmaterial_cid 索引,其实只能把条件 1 给用上,如果用 index_designmaterial_organid_cid 的话,能把这俩条件都用上。

所以选 index_designmaterial_organid_cid,是比 index_designmaterial_cid 更优的,因为他利用了更多的条件,能够通过索引过滤更多的数据。

所以更新统计信息后,索引选择从 index_designmaterial_cid 变成了 index_designmaterial_organid_cid 其实并不算是"走错"。

你看看这样能回答你的问题吗?@frankliu747

那个走错索引是用了idx_designmaterial_oid_ptime这个索引,index_designmaterial_organid_cid这个索引是我后来加上去的,在给你模似时,收集统计信息之前我把它删除了,奇怪了,你还能看到。

我这边实际问题是正常原来走index_designmaterial_cid,异常时走idx_designmaterial_oid_ptime,异常时比正常的慢10倍左右,所以之前一次全部走错,tidb直接被拖挂了

你好,

这边根据你提供的统计信息只能得出目前的结论。希望可以正确提供下走错索引的执行计划,这边可以在帮忙看下。提供之前希望验证下,减少沟通成本。

不好意思,但奇怪了,我给的统计信息都是出错和正常的统计信息,而且执行计划都从新收集过,在模似前我就把 index_designmaterial_organid_cid索引删除掉了。我再重新弄一下

辛苦辛苦

步骤1.zip (1.4 MB) 步骤2.zip (1.4 MB) 已按你的要求重新收集了,执行2 analyze table designmaterial 后会走错索引idx_designmaterial_oid_ptime 或 index_organid_modelflag,重新执行ANALYZE TABLE designmaterial index index_designmaterial_cid WITH 10 BUCKETS; 或ANALYZE TABLE designmaterial index index_organid_modelflag WITH 10 BUCKETS; 就可恢复正常

感谢反馈~

新的数据已经重发了,请问一下还需要收集其它数据吗?

你好,

有信息收集这边会及时联系,辛苦看下私信

问题原因:

organId 后面 IN 的值太多,CMSKetch 点查累加起来误差变大。 最后导致没选包含 organid 的索引,而选了 categoryid 的索引。

已提供两个解法:

  1. 用 SQL Binding;
  2. 创建一个 organid + categoryid 的复合索引,让 organid 的索引被优化器的 skyline pruning 剪枝掉;