KV Requests is sometimes not well batched when performing uniqueness checks
- Dominant language
- Go
- Stars
- 40.5k
- Forks
- 6.2k
- PR merge metrics
- PR metrics pending
Description
## Enhancement
See the following example:
```sql
/* init */ set @@tidb_slow_log_threshold = 300;
/* init */ drop table if exists t1, t2;
/* init */ create table t1 (id int primary key, a int, b int, c int, d int, e int, unique key (a, b), unique key (a, c), unique key (a, d));
/* init */ create table t2 (id int primary key, a int, b int, c int, d int, e int, key (a, b), key (a, c), key (a, d));
/* init */ insert into t1 values (1, 1, 1, 1, 1, 1), (2, 1, 2, 2, 2, 2), (3, 1, 3, 3, 3, 3), (4, 1, 4, 4, 4, 4), (5, 1, 5, 5, 5, 5);
/* init */ insert into t2 select * from t1;
/* init */ set @@tidb_slow_log_threshold = 0;
/* t1 */ update t1 set a = 2 where a = 1;
/* t1 */ select query, plan from information_schema.slow_query where conn_id = connection_id();
/* t2 */ update t2 set a = 2 where a = 1;
/* t2 */ select query, plan from information_schema.slow_query where conn_id = connection_id();
```
We can expect that for the update statement to t1, it needs to perform uniqueness checks. However, it seems these check operations are not well batched. See the execution result of the SQLs above:
```sql
/* init */ set @@tidb_slow_log_threshold = 300;
-- init >> 0 rows affected
/* init */ drop table if exists t1, t2;
-- init >> 0 rows affected
/* init */ create table t1 (id int primary key, a int, b int, c int, d int, e int, unique key (a, b), unique key (a, c), unique key (a, d));
-- init >> 0 rows affected
/* init */ create table t2 (id int primary key, a int, b int, c int, d int, e int, key (a, b), key (a, c), key (a, d));
-- init >> 0 rows affected
/* init */ insert into t1 values (1, 1, 1, 1, 1, 1), (2, 1, 2, 2, 2, 2), (3, 1, 3, 3, 3, 3), (4, 1, 4, 4, 4, 4), (5, 1, 5, 5, 5, 5);
-- init >> 5 rows affected
/* init */ insert into t2 select * from t1;
-- init >> 5 rows affected
/* init */ set @@tidb_slow_log_threshold = 0;
-- init >> 0 rows affected
/* t1 */ update t1 set a = 2 where a = 1;
-- t1 >> 5 rows affected
/* t1 */ select query, plan from information_schema.slow_query where conn_id = connection_id();
-- t1 >> +-------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
-- t1 | query | plan |
-- t1 +-------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
-- t1 | /* t1 */ update t1 set a = 2 where a = 1; | id task estRows operator info actRows execution info memory disk |
-- t1 | | Update_4 root 0 N/A 0 time:8.53ms, loops:1, Get:{num_rpc:15, total_time:5.74ms}, time_detail: {total_process_time: 770.9µs, total_wait_time: 1.06ms, total_kv_read_wall_time: 1.95ms, tikv_wall_time: 2.44ms}, scan_detail: {total_keys: 15, get_snapshot_time: 275.9µs, rocksdb: {block: {}}}, commit_txn: {prewrite:1.93ms, slowest_prewrite_rpc: {total: 0.002s, region_id: 136, store: 127.0.0.1:20160, time_detail: {tikv_wall_time: 1.53ms}, scan_detail: {get_snapshot_time: 13.8µs, rocksdb: {block: {}}}, write_detail: {store_batch_wait: 31µs, propose_send_wait: 0s, persist_log: {total: 370.8µs, write_leader_wait: 115ns, sync_log: 294.7µs, write_memtable: 3.12µs}, commit_log: 401.6µs, apply_batch_wait: 23.9µs, apply: {total:266.4µs, mutex_lock: 0s, write_leader_wait: 0s, write_wal: 48µs, write_memtable: 90.3µs}}}, region_num:1, write_keys:35, write_byte:1455} 2.23 KB N/A |
-- t1 | | └─IndexLookUp_11 root 10 5 time:1.83ms, loops:2, index_task: {total_time: 723.4µs, fetch_handle: 718.9µs, build: 1.54µs, wait: 2.93µs}, table_task: {total_time: 903.6µs, num: 1, concurrency: 5}, next: {wait_index: 902.7µs, wait_table_lookup_build: 102.9µs, wait_table_lookup_resp: 782.7µs} 19.3 KB N/A |
-- t1 | | ├─IndexRangeScan_9(Build) cop[tikv] 10 table:t1, index:a(a, b), range:[1,1], keep order:false, stats:pseudo 5 time:711.4µs, loops:3, cop_task: {num: 1, max: 601.7µs, proc_keys: 5, tot_proc: 76.6µs, tot_wait: 55.7µs, copr_cache_hit_ratio: 0.00, build_task_duration: 33.4µs, max_distsql_concurrency: 1}, rpc_info:{Cop:{num_rpc:1, total_time:573.1µs}}, tikv_task:{time:0s, loops:1}, scan_detail: {total_process_keys: 5, total_process_keys_size: 265, total_keys: 6, get_snapshot_time: 19.1µs, rocksdb: {key_skipped_count: 5, block: {}}}, time_detail: {total_process_time: 76.6µs, total_wait_time: 55.7µs, tikv_wall_time: 243.5µs} N/A N/A |
-- t1 | | └─TableRowIDScan_10(Probe) cop[tikv] 10 table:t1, keep order:false, stats:pseudo 5 time:741µs, loops:2, cop_task: {num: 1, max: 639.1µs, proc_keys: 5, tot_proc: 107.1µs, tot_wait: 60.1µs, copr_cache_hit_ratio: 0.00, build_task_duration: 49.3µs, max_distsql_concurrency: 1, max_extra_concurrency: 1}, rpc_info:{Cop:{num_rpc:1, total_time:619.8µs}}, tikv_task:{time:1ms, loops:1}, scan_detail: {total_process_keys: 5, total_process_keys_size: 265, total_keys: 6, get_snapshot_time: 24.4µs, rocksdb: {key_skipped_count: 5, block: {}}}, time_detail: {total_process_time: 107.1µs, total_wait_time: 60.1µs, total_kv_read_wall_time: 1ms, tikv_wall_time: 340.2µs} N/A N/A |
-- t1 +-------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
/* t2 */ update t2 set a = 2 where a = 1;
-- t2 >> 5 rows affected
/* t2 */ select query, plan from information_schema.slow_query where conn_id = connection_id();
-- t2 >> +-------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
-- t2 | query | plan |
-- t2 +-------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
-- t2 | /* t2 */ update t2 set a = 2 where a = 1; | id task estRows operator info actRows execution info memory disk |
-- t2 | | Update_4 root 0 N/A 0 time:2.08ms, loops:1, commit_txn: {prewrite:2.64ms, slowest_prewrite_rpc: {total: 0.003s, region_id: 22, store: 127.0.0.1:20160, time_detail: {tikv_wall_time: 2.23ms}, scan_detail: {get_snapshot_time: 26.7µs, rocksdb: {block: {}}}, write_detail: {store_batch_wait: 88.8µs, propose_send_wait: 0s, persist_log: {total: 521.7µs, write_leader_wait: 211ns, sync_log: 421.7µs, write_memtable: 3.89µs}, commit_log: 598µs, apply_batch_wait: 23.9µs, apply: {total:352µs, mutex_lock: 0s, write_leader_wait: 0s, write_wal: 47.7µs, write_memtable: 127.5µs}}}, region_num:1, write_keys:35, write_byte:1620} 2.23 KB N/A |
-- t2 | | └─IndexLookUp_11 root 10 5 time:1.93ms, loops:2, index_task: {total_time: 953.5µs, fetch_handle: 941.5µs, build: 747ns, wait: 11.3µs}, table_task: {total_time: 863µs, num: 1, concurrency: 5}, next: {wait_index: 1.03ms, wait_table_lookup_build: 109.3µs, wait_table_lookup_resp: 752.9µs} 19.3 KB N/A |
-- t2 | | ├─IndexRangeScan_9(Build) cop[tikv] 10 table:t2, index:a(a, b), range:[1,1], keep order:false, stats:pseudo 5 time:937µs, loops:3, cop_task: {num: 1, max: 868.3µs, proc_keys: 5, tot_proc: 158.4µs, tot_wait: 114.5µs, copr_cache_hit_ratio: 0.00, build_task_duration: 21.3µs, max_distsql_concurrency: 1}, rpc_info:{Cop:{num_rpc:1, total_time:844.2µs}}, tikv_task:{time:1ms, loops:1}, scan_detail: {total_process_keys: 5, total_process_keys_size: 275, total_keys: 6, get_snapshot_time: 68.3µs, rocksdb: {key_skipped_count: 5, block: {}}}, time_detail: {total_process_time: 158.4µs, total_wait_time: 114.5µs, total_kv_read_wall_time: 1ms, tikv_wall_time: 512µs} N/A N/A |
-- t2 | | └─TableRowIDScan_10(Probe) cop[tikv] 10 table:t2, keep order:false, stats:pseudo 5 time:733µs, loops:2, cop_task: {num: 1, max: 674.3µs, proc_keys: 5, tot_proc: 115.8µs, tot_wait: 81.6µs, copr_cache_hit_ratio: 0.00, build_task_duration: 41.2µs, max_distsql_concurrency: 1, max_extra_concurrency: 1}, rpc_info:{Cop:{num_rpc:1, total_time:656.5µs}}, tikv_task:{time:0s, loops:1}, scan_detail: {total_process_keys: 5, total_process_keys_size: 265, total_keys: 6, get_snapshot_time: 28µs, rocksdb: {key_skipped_count: 5, block: {}}}, time_detail: {total_process_time: 115.8µs, total_wait_time: 81.6µs, tikv_wall_time: 389.1µs} N/A N/A |
-- t2 +-------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
```
It can be seen that the statement on t1 performed 15 `Get` requests, while it can actually be batched to one `BatchGet` request theoretically (as the data is in the same region for the small table). It might not be easy to implement in the current architecture, though.
Contributor guide
Assessment
This issue has not been assessed yet.