MDEV-37202 spider sh: add support for single partition read

This commit is contained in:
Yuchen Pei
2025-07-18 18:02:03 +10:00
parent 5bd72e55f1
commit b8f975ece9
4 changed files with 115 additions and 16 deletions

View File

@ -77,6 +77,51 @@ c
5 5
6 6
drop table t1, t2, t3, t4; drop table t1, t2, t3, t4;
# single partition
create table t2 (c int);
create table t1 (c int) ENGINE=Spider
WRAPPER=mysql REMOTE_SERVER=srv
PARTITION BY RANGE (c) (
PARTITION p VALUES LESS THAN MAXVALUE REMOTE_TABLE=t2
);
insert into t1 values (1), (2), (3);
explain
select * from t1;
id select_type table type possible_keys key key_len ref rows Extra
1 PUSHED SELECT NULL NULL NULL NULL NULL NULL NULL NULL
select * from t1;
c
1
2
3
drop table t1, t2;
# multiple partitions
create table t3 (c int);
create table t2 (c int);
create table t1 (c int) ENGINE=Spider
WRAPPER=mysql REMOTE_SERVER=srv
PARTITION BY RANGE (c) (
PARTITION p1 VALUES LESS THAN (3) REMOTE_TABLE=t2,
PARTITION p2 VALUES LESS THAN MAXVALUE REMOTE_TABLE=t3
);
insert into t1 values (1), (2), (3);
## single read partition: sh
explain
select * from t1 partition (p2);
id select_type table type possible_keys key key_len ref rows Extra
1 PUSHED SELECT NULL NULL NULL NULL NULL NULL NULL NULL
select * from t1 partition (p2);
c
3
## single read partition after pruning: gbh (see also MDEV-20250)
explain
select * from t1 where c > 2;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Storage engine handles GROUP BY
select * from t1 where c > 2;
c
3
drop table t1, t2, t3;
# #
# MDEV-37110 Spider select handler: implement one that handles # MDEV-37110 Spider select handler: implement one that handles
# testcases showcasing problems with the gbh # testcases showcasing problems with the gbh

View File

@ -48,6 +48,39 @@ explain select c from t1 union all select c from t3;
select c from t1 union all select c from t3; select c from t1 union all select c from t3;
drop table t1, t2, t3, t4; drop table t1, t2, t3, t4;
--echo # single partition
create table t2 (c int);
create table t1 (c int) ENGINE=Spider
WRAPPER=mysql REMOTE_SERVER=srv
PARTITION BY RANGE (c) (
PARTITION p VALUES LESS THAN MAXVALUE REMOTE_TABLE=t2
);
insert into t1 values (1), (2), (3);
explain
select * from t1;
select * from t1;
drop table t1, t2;
--echo # multiple partitions
create table t3 (c int);
create table t2 (c int);
create table t1 (c int) ENGINE=Spider
WRAPPER=mysql REMOTE_SERVER=srv
PARTITION BY RANGE (c) (
PARTITION p1 VALUES LESS THAN (3) REMOTE_TABLE=t2,
PARTITION p2 VALUES LESS THAN MAXVALUE REMOTE_TABLE=t3
);
insert into t1 values (1), (2), (3);
--echo ## single read partition: sh
explain
select * from t1 partition (p2);
select * from t1 partition (p2);
--echo ## single read partition after pruning: gbh (see also MDEV-20250)
explain
select * from t1 where c > 2;
select * from t1 where c > 2;
drop table t1, t2, t3;
--echo # --echo #
--echo # MDEV-37110 Spider select handler: implement one that handles --echo # MDEV-37110 Spider select handler: implement one that handles
--echo # testcases showcasing problems with the gbh --echo # testcases showcasing problems with the gbh

View File

@ -180,8 +180,7 @@ count(0)
connection child2_1; connection child2_1;
SELECT argument FROM mysql.general_log WHERE command_type != 'Execute' AND argument LIKE '%select %'; SELECT argument FROM mysql.general_log WHERE command_type != 'Execute' AND argument LIKE '%select %';
argument argument
select `id`,`hr_status`,`region_code`,`region` from `auto_test_remote`.`tbl_person` where `id` = '24FC3F0A5119432BAE13DD65AABAA39C' and `region` = 510411 select count(0) `count(0)` from (`auto_test_remote`.`tbl_person` t0 join `auto_test_remote`.`tbl_ncd_cm_person` t1 on (t0.`id` = t1.`person_id`)) where ((1 = 1) and (t0.`hr_status` <> '99') and (t0.`hr_status` <> '2') and (t0.`region_code` like (convert((concat((concat(_latin1'%' , _latin1'51041110620301' , _latin1'%')))) using utf8mb3))) and (t0.`id` = '24FC3F0A5119432BAE13DD65AABAA39C') and (t1.`diseaseKind_id` = '52A0328740914BCE86ED10A4D2521816') and (t0.`region` = 510411))
select count(0) `count(0)` from (select 1) t0 join `auto_test_remote`.`tbl_ncd_cm_person` t1 where ((t1.`person_id` = '24FC3F0A5119432BAE13DD65AABAA39C') and (t1.`diseaseKind_id` = '52A0328740914BCE86ED10A4D2521816'))
SELECT argument FROM mysql.general_log WHERE command_type != 'Execute' AND argument LIKE '%select %' SELECT argument FROM mysql.general_log WHERE command_type != 'Execute' AND argument LIKE '%select %'
SELECT * FROM tbl_person; SELECT * FROM tbl_person;
id hr_status region_code region id hr_status region_code region

View File

@ -20,6 +20,8 @@
#include "partition_element.h" #include "partition_element.h"
/* for spider_set_result_list_param */ /* for spider_set_result_list_param */
#include "spd_table.h" #include "spd_table.h"
#include "partition_info.h"
#include "ha_partition.h"
extern handlerton *spider_hton_ptr; extern handlerton *spider_hton_ptr;
constexpr int LINK_IDX= 0; constexpr int LINK_IDX= 0;
@ -80,13 +82,28 @@ static bool spider_sh_can_handle_query(SELECT_LEX *select_lex,
return true; return true;
} }
/*
Get the spider handler from a table. If the table is partitioned,
get its first read partition handler.
*/
static ha_spider *spider_sh_get_spider(TABLE* table)
{
if (table->part_info)
{
uint part= bitmap_get_first_set(&table->part_info->read_partitions);
ha_partition *partition= (ha_partition *) table->file;
return (ha_spider *) partition->get_child_handlers()[part];
}
return (ha_spider *) table->file;
}
select_handler *spider_create_select_handler(THD *thd, SELECT_LEX *select_lex, select_handler *spider_create_select_handler(THD *thd, SELECT_LEX *select_lex,
SELECT_LEX_UNIT *) SELECT_LEX_UNIT *)
{ {
SPIDER_TABLE_HOLDER *table_holder; SPIDER_TABLE_HOLDER *table_holder;
uint n_tables= 0; uint n_tables= 0;
spider_fields *fields; spider_fields *fields;
ha_spider *spider; ha_spider *spider, *first_spider;
TABLE_LIST *from= select_lex->get_table_list(); TABLE_LIST *from= select_lex->get_table_list();
int dbton_id = -1; int dbton_id = -1;
SPIDER_CONN *common_conn= NULL; SPIDER_CONN *common_conn= NULL;
@ -103,33 +120,38 @@ select_handler *spider_create_select_handler(THD *thd, SELECT_LEX *select_lex,
return NULL; return NULL;
for (TABLE_LIST *tl= from; tl; n_tables++, tl= tl->next_local) for (TABLE_LIST *tl= from; tl; n_tables++, tl= tl->next_local)
{ {
TABLE *table= tl->table;
/* Do not support temporary tables */ /* Do not support temporary tables */
if (!tl->table) if (!table)
return NULL; return NULL;
/* TODO: support partition table with one (read) partition */ /*
if (tl->table->part_info) Do not support partitioned table with more than one (read)
partition
*/
if (table->part_info &&
bitmap_bits_set(&table->part_info->read_partitions) != 1)
return NULL; return NULL;
/* One of the join tables is not a spider table */ /* One of the join tables is not a spider table */
if (tl->table->file->partition_ht() != spider_hton_ptr) if (table->file->partition_ht() != spider_hton_ptr)
return NULL; return NULL;
spider = (ha_spider *) tl->table->file; spider= spider_sh_get_spider(table);
/* needed for table holder (see spider_add_table_holder()) */ /* needed for table holder (see spider_add_table_holder()) */
spider->idx_for_direct_join = n_tables; spider->idx_for_direct_join = n_tables;
/* only create if all tables have common first backend. */ /* Only create if all tables have common first backend. */
uint all_link_idx= spider->conn_link_idx[LINK_IDX];
if (dbton_id == -1) if (dbton_id == -1)
dbton_id= spider->share->use_sql_dbton_ids[0]; dbton_id= spider->share->use_sql_dbton_ids[all_link_idx];
else if (dbton_id != (int) spider->share->use_sql_dbton_ids[0]) else if (dbton_id != (int) spider->share->use_sql_dbton_ids[all_link_idx])
return NULL; return NULL;
} }
if (!spider_sh_can_handle_query(select_lex, first_spider= spider_sh_get_spider(from->table);
((ha_spider *) from->table->file)->share, if (!spider_sh_can_handle_query(select_lex, first_spider->share, thd))
thd))
return NULL; return NULL;
if (!(table_holder= spider_create_table_holder(n_tables))) if (!(table_holder= spider_create_table_holder(n_tables)))
return NULL; return NULL;
for (TABLE_LIST *tl= from; tl; tl= tl->next_local) for (TABLE_LIST *tl= from; tl; tl= tl->next_local)
{ {
spider = (ha_spider *) tl->table->file; spider= spider_sh_get_spider(tl->table);
spider_add_table_holder(spider, table_holder); spider_add_table_holder(spider, table_holder);
/* /*
As in dml_init, wide_handler->lock_mode == -2 is a relic from As in dml_init, wide_handler->lock_mode == -2 is a relic from
@ -183,7 +205,7 @@ select_handler *spider_create_select_handler(THD *thd, SELECT_LEX *select_lex,
spider_check_and_set_trx_isolation( spider_check_and_set_trx_isolation(
common_conn, &spider->need_mons[LINK_IDX]))) common_conn, &spider->need_mons[LINK_IDX])))
goto free_table_holder; goto free_table_holder;
trx= ((ha_spider *) from->table->file)->wide_handler->trx; trx= first_spider->wide_handler->trx;
if (!common_conn->join_trx && !trx->trx_xa) if (!common_conn->join_trx && !trx->trx_xa)
{ {
/* So that spider executes queries that start a transaction. */ /* So that spider executes queries that start a transaction. */