pingcap / pingcap/tidb

KV Requests is sometimes not well batched when performing uniqueness checks

Open
#55,427 2 comments 0 reactions 0 assignees View on GitHub
report/customer type/enhancement
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

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.