在了解IndexLookUp的执行过程之前,先介绍mysql索引扫描的执行作为对比(这里借用网络图),当执行一条SQL时,存储引擎端首先读取符合条件的记录在index主键(可能会涉及ICP,联合索引的某些列等),然后根据主键从表中读取记录,然后将记录返回给server层,再由server层进行过滤他们根据其他条件返回给客户。上述过程中,索引扫描和回表操作都是在存储引擎端完成的。IndexLookUp算子是一个扫描过程,tidb扫描索引,通过rowid返回表。它包括两个子操作符IndexScan和TableRowidscan。IndexLookUpoperator的执行计划任务列为root,说明该operator在tidbserver端执行,有两个子operatorsub-task列为cop[tikv],说明推送协处理器任务下到tikv执行。在执行计划中,算子的执行顺序是先执行子算子,再返回数据给父算子。先执行(build端),再用返回结果执行另一个算子(probe端),但在执行过程中并不严格要求所有算子执行后返回结果或者所有子算子执行完毕才上报给parent运算符返回结果。官方文档对IndexLookUp的描述是这样的:首先在Build端汇总TiKV扫描到的RowID,然后根据这些RowID去Probe端准确读取TiKV上的数据。Build端是IndexFullScan或IndexRangeScan类型的算子,Probe端是TableRowIDScan类型的算子。一直以来,由于TiKV中子算子(IndexScan和TableRowidscan)的执行,理所当然地认为索引扫描是在像mysql这样的存储引擎侧完成的,导致对执行过程的错误理解的IndexLookUp:在TiKV端通过索引扫描得到rowid后,使用TiKV中的rowid查询表,最后将结果返回给TiDB服务端重新过滤或者返回给客户端。实际上,IndexLookUp的执行过程是这样的:(1)tidbserver根据SQL条件构造indexscancoptask,在tikv端扫描index获取符合条件的rowids。(2)扫描到的rowid返回给tidbserver进行汇总,tidbserver使用rowid构造Key和cop任务执行回表操作(3)tikv使用TableRowIDScan将数据扫描回表,然后将数据返回给tidb。执行计划中的时间包括网络时间。与mysql直接在引擎中查询表相比,tidbIndexLookUp在执行过程中需要多进行两次网络交互,难免会造成延迟。因此,网络性能和TiDB服务器处理能力对IndexLookUp性能有一定的影响。TiDB有相关参数控制indexlookup的性能:tidb\_index\_lookup\_size:使用rowid扫表时的批处理数tidb\_index\_lookup\_concurrency:使用rowid扫表时的并发数。测试一:tidb\_index\_lookup\_concurrency影响并发数从5到1,执行时间从6.15秒增加到26.57秒测试二:tidb\_index\_lookup\_size影响并发数tidb\_index\_lookup\_concurrency改善效果不是很明显原作者:@h5n1发表于:2022/4/8
