From b99d5256a951d7fd85bca7584e53b050577e74d0 Mon Sep 17 00:00:00 2001 From: yuanyazhi Date: Thu, 12 Dec 2024 10:53:36 +0800 Subject: [PATCH] fix partition index merge --- mysql-test/suite/ctc/r/ctc_dml_ignore.result | 92 ++++++++++++++++++++ mysql-test/suite/ctc/t/ctc_dml_ignore.test | 46 ++++++++++ storage/ctc/ha_ctcpart.cc | 26 ++++++ storage/ctc/ha_ctcpart.h | 6 ++ 4 files changed, 170 insertions(+) diff --git a/mysql-test/suite/ctc/r/ctc_dml_ignore.result b/mysql-test/suite/ctc/r/ctc_dml_ignore.result index 3f8f3da..0cd793d 100644 --- a/mysql-test/suite/ctc/r/ctc_dml_ignore.result +++ b/mysql-test/suite/ctc/r/ctc_dml_ignore.result @@ -468,6 +468,98 @@ count(*) 3 drop table t1; drop table t2; +CREATE TABLE `t2` ( +id int, +a int, +b int, +KEY `idx_a` (a), +KEY `idx_b` (b) +) +PARTITION BY RANGE (`id`) +(PARTITION p0 VALUES LESS THAN (10) ENGINE = CTC, +PARTITION p1 VALUES LESS THAN (20) ENGINE = CTC, +PARTITION p2 VALUES LESS THAN (30) ENGINE = CTC, +PARTITION p4 VALUES LESS THAN MAXVALUE ENGINE = CTC); +insert into t2 values(30, 2, 3), (20, 1, 3), (10, 1, 3), (null, 1, 3); +explain select /*+ INDEX_MERGE(t2 idx_a, idx_b) */ count(*) from t2 where a = 1 and b = 3; +id select_type table partitions type possible_keys key key_len ref rows filtered Extra +1 SIMPLE t2 p0,p1,p2,p4 index_merge idx_a,idx_b idx_a,idx_b 5,5 NULL 1 100.00 Using intersect(idx_a,idx_b); Using where; Using pushed condition ((`test`.`t2`.`b` = 3) and (`test`.`t2`.`a` = 1)); Using index +Warnings: +Note 1003 /* select#1 */ select /*+ INDEX_MERGE(`t2`@`select#1` `idx_a`, `idx_b`) */ count(0) AS `count(*)` from `test`.`t2` where ((`test`.`t2`.`b` = 3) and (`test`.`t2`.`a` = 1)) +select /*+ INDEX_MERGE(t2 idx_a, idx_b) */ count(*) from t2 where a = 1 and b = 3; +count(*) +3 +explain select count(*) from t2 ignore index(idx_b) where a = 1 and b = 3; +id select_type table partitions type possible_keys key key_len ref rows filtered Extra +1 SIMPLE t2 p0,p1,p2,p4 ref idx_a idx_a 5 const 1 33.33 Using where; Using pushed condition (`test`.`t2`.`b` = 3) +Warnings: +Note 1003 /* select#1 */ select count(0) AS `count(*)` from `test`.`t2` IGNORE INDEX (`idx_b`) where ((`test`.`t2`.`b` = 3) and (`test`.`t2`.`a` = 1)) +select count(*) from t2 ignore index(idx_b) where a = 1 and b = 3; +count(*) +3 +explain select /*+ INDEX_MERGE(t2 idx_a, idx_b) */ count(*) from t2 where a = 1 or b = 3; +id select_type table partitions type possible_keys key key_len ref rows filtered Extra +1 SIMPLE t2 p0,p1,p2,p4 index_merge idx_a,idx_b idx_a,idx_b 5,5 NULL 2 100.00 Using union(idx_a,idx_b); Using where; Using pushed condition ((`test`.`t2`.`a` = 1) or (`test`.`t2`.`b` = 3)) +Warnings: +Note 1003 /* select#1 */ select /*+ INDEX_MERGE(`t2`@`select#1` `idx_a`, `idx_b`) */ count(0) AS `count(*)` from `test`.`t2` where ((`test`.`t2`.`a` = 1) or (`test`.`t2`.`b` = 3)) +select /*+ INDEX_MERGE(t2 idx_a, idx_b) */ count(*) from t2 where a = 1 or b = 3; +count(*) +4 +explain select count(*) from t2 ignore index(idx_b) where a = 1 or b = 3; +id select_type table partitions type possible_keys key key_len ref rows filtered Extra +1 SIMPLE t2 p0,p1,p2,p4 ALL idx_a NULL NULL NULL 3 55.56 Using where; Using pushed condition ((`test`.`t2`.`a` = 1) or (`test`.`t2`.`b` = 3)) +Warnings: +Note 1003 /* select#1 */ select count(0) AS `count(*)` from `test`.`t2` IGNORE INDEX (`idx_b`) where ((`test`.`t2`.`a` = 1) or (`test`.`t2`.`b` = 3)) +select count(*) from t2 ignore index(idx_b) where a = 1 or b = 3; +count(*) +4 +drop table t2; +create table t8( +id int, +char_col char(20), +enum_col enum('x-small','small','medium','large','x-large'), +primary key (id), +key idx_char_col (char_col), +key idx_enum_col (enum_col)) +PARTITION BY RANGE (`id`) +(PARTITION p0 VALUES LESS THAN (90) ENGINE = CTC, +PARTITION p1 VALUES LESS THAN (420) ENGINE = CTC, +PARTITION p2 VALUES LESS THAN (510) ENGINE = CTC, +PARTITION p4 VALUES LESS THAN MAXVALUE ENGINE = CTC); +insert into t8 values(84, 'apple', 'x-large'), (417, 'apple' , 'x-large'), (439, 'qpple', 'x-large'), (847, 'apple', 'x-large'); +explain select /*+ INDEX_MERGE(t8 idx_char_col, idx_enum_col) */ count(*) from t8 where enum_col = 'x-large' and char_col = 'apple'; +id select_type table partitions type possible_keys key key_len ref rows filtered Extra +1 SIMPLE t8 p0,p1,p2,p4 index_merge idx_char_col,idx_enum_col idx_char_col,idx_enum_col 81,2 NULL 1 100.00 Using intersect(idx_char_col,idx_enum_col); Using where; Using pushed condition (`test`.`t8`.`char_col` = 'apple'); Using index +Warnings: +Note 1003 /* select#1 */ select /*+ INDEX_MERGE(`t8`@`select#1` `idx_char_col`, `idx_enum_col`) */ count(0) AS `count(*)` from `test`.`t8` where ((`test`.`t8`.`char_col` = 'apple') and (`test`.`t8`.`enum_col` = 'x-large')) +select /*+ INDEX_MERGE(t8 idx_char_col, idx_enum_col) */ count(*) from t8 where enum_col = 'x-large' and char_col = 'apple'; +count(*) +3 +explain select count(*) from t8 ignore index(idx_enum_col) where enum_col = 'x-large' and char_col = 'apple'; +id select_type table partitions type possible_keys key key_len ref rows filtered Extra +1 SIMPLE t8 p0,p1,p2,p4 ref idx_char_col idx_char_col 81 const 1 33.33 Using where; Using pushed condition (`test`.`t8`.`char_col` = 'apple') +Warnings: +Note 1003 /* select#1 */ select count(0) AS `count(*)` from `test`.`t8` IGNORE INDEX (`idx_enum_col`) where ((`test`.`t8`.`char_col` = 'apple') and (`test`.`t8`.`enum_col` = 'x-large')) +select count(*) from t8 ignore index(idx_enum_col) where enum_col = 'x-large' and char_col = 'apple'; +count(*) +3 +explain select /*+ INDEX_MERGE(t8 idx_char_col, idx_enum_col) */ count(*) from t8 where enum_col = 'x-large' or char_col = 'apple'; +id select_type table partitions type possible_keys key key_len ref rows filtered Extra +1 SIMPLE t8 p0,p1,p2,p4 index_merge idx_char_col,idx_enum_col idx_enum_col,idx_char_col 2,81 NULL 2 100.00 Using union(idx_enum_col,idx_char_col); Using where +Warnings: +Note 1003 /* select#1 */ select /*+ INDEX_MERGE(`t8`@`select#1` `idx_char_col`, `idx_enum_col`) */ count(0) AS `count(*)` from `test`.`t8` where ((`test`.`t8`.`enum_col` = 'x-large') or (`test`.`t8`.`char_col` = 'apple')) +select /*+ INDEX_MERGE(t8 idx_char_col, idx_enum_col) */ count(*) from t8 where enum_col = 'x-large' or char_col = 'apple'; +count(*) +4 +explain select count(*) from t8 ignore index(idx_enum_col) where enum_col = 'x-large' or char_col = 'apple'; +id select_type table partitions type possible_keys key key_len ref rows filtered Extra +1 SIMPLE t8 p0,p1,p2,p4 ALL idx_char_col NULL NULL NULL 3 55.56 Using where +Warnings: +Note 1003 /* select#1 */ select count(0) AS `count(*)` from `test`.`t8` IGNORE INDEX (`idx_enum_col`) where ((`test`.`t8`.`enum_col` = 'x-large') or (`test`.`t8`.`char_col` = 'apple')) +select count(*) from t8 ignore index(idx_enum_col) where enum_col = 'x-large' or char_col = 'apple'; +count(*) +4 +drop table t8; CREATE TABLE `test` ( `a` int NOT NULL, `b` int NOT NULL, diff --git a/mysql-test/suite/ctc/t/ctc_dml_ignore.test b/mysql-test/suite/ctc/t/ctc_dml_ignore.test index 57c833f..fb464b6 100644 --- a/mysql-test/suite/ctc/t/ctc_dml_ignore.test +++ b/mysql-test/suite/ctc/t/ctc_dml_ignore.test @@ -221,6 +221,52 @@ select /*+ INDEX_MERGE(t2 idx_char_col,idx_enum_col) */ count(*) from t2 where e drop table t1; drop table t2; +CREATE TABLE `t2` ( + id int, + a int, + b int, + KEY `idx_a` (a), + KEY `idx_b` (b) +) +PARTITION BY RANGE (`id`) +(PARTITION p0 VALUES LESS THAN (10) ENGINE = CTC, +PARTITION p1 VALUES LESS THAN (20) ENGINE = CTC, +PARTITION p2 VALUES LESS THAN (30) ENGINE = CTC, +PARTITION p4 VALUES LESS THAN MAXVALUE ENGINE = CTC); +insert into t2 values(30, 2, 3), (20, 1, 3), (10, 1, 3), (null, 1, 3); +explain select /*+ INDEX_MERGE(t2 idx_a, idx_b) */ count(*) from t2 where a = 1 and b = 3; +select /*+ INDEX_MERGE(t2 idx_a, idx_b) */ count(*) from t2 where a = 1 and b = 3; +explain select count(*) from t2 ignore index(idx_b) where a = 1 and b = 3; +select count(*) from t2 ignore index(idx_b) where a = 1 and b = 3; +explain select /*+ INDEX_MERGE(t2 idx_a, idx_b) */ count(*) from t2 where a = 1 or b = 3; +select /*+ INDEX_MERGE(t2 idx_a, idx_b) */ count(*) from t2 where a = 1 or b = 3; +explain select count(*) from t2 ignore index(idx_b) where a = 1 or b = 3; +select count(*) from t2 ignore index(idx_b) where a = 1 or b = 3; +drop table t2; + +create table t8( + id int, + char_col char(20), + enum_col enum('x-small','small','medium','large','x-large'), + primary key (id), + key idx_char_col (char_col), + key idx_enum_col (enum_col)) +PARTITION BY RANGE (`id`) +(PARTITION p0 VALUES LESS THAN (90) ENGINE = CTC, +PARTITION p1 VALUES LESS THAN (420) ENGINE = CTC, +PARTITION p2 VALUES LESS THAN (510) ENGINE = CTC, +PARTITION p4 VALUES LESS THAN MAXVALUE ENGINE = CTC); +insert into t8 values(84, 'apple', 'x-large'), (417, 'apple' , 'x-large'), (439, 'qpple', 'x-large'), (847, 'apple', 'x-large'); +explain select /*+ INDEX_MERGE(t8 idx_char_col, idx_enum_col) */ count(*) from t8 where enum_col = 'x-large' and char_col = 'apple'; +select /*+ INDEX_MERGE(t8 idx_char_col, idx_enum_col) */ count(*) from t8 where enum_col = 'x-large' and char_col = 'apple'; +explain select count(*) from t8 ignore index(idx_enum_col) where enum_col = 'x-large' and char_col = 'apple'; +select count(*) from t8 ignore index(idx_enum_col) where enum_col = 'x-large' and char_col = 'apple'; +explain select /*+ INDEX_MERGE(t8 idx_char_col, idx_enum_col) */ count(*) from t8 where enum_col = 'x-large' or char_col = 'apple'; +select /*+ INDEX_MERGE(t8 idx_char_col, idx_enum_col) */ count(*) from t8 where enum_col = 'x-large' or char_col = 'apple'; +explain select count(*) from t8 ignore index(idx_enum_col) where enum_col = 'x-large' or char_col = 'apple'; +select count(*) from t8 ignore index(idx_enum_col) where enum_col = 'x-large' or char_col = 'apple'; +drop table t8; + CREATE TABLE `test` ( `a` int NOT NULL, `b` int NOT NULL, diff --git a/storage/ctc/ha_ctcpart.cc b/storage/ctc/ha_ctcpart.cc index 183fa4a..b814540 100644 --- a/storage/ctc/ha_ctcpart.cc +++ b/storage/ctc/ha_ctcpart.cc @@ -404,6 +404,32 @@ void ha_ctcpart::position_in_last_part(uchar *ref_arg, const uchar *record) { reset_partition(part_id); } +int ha_ctcpart::key_and_rowid_cmp(KEY **key_info, uchar *a, uchar *b) { + int cmp = key_rec_cmp(key_info, a, b); + if (cmp != 0) { + return (cmp); + } + + /* We must compare by rowid, which is added before the record, in the priority queue. */ + return (ctc_cmp_cantian_rowid((rowid_t *)(a - ROW_ID_LENGTH), (rowid_t *)(b - ROW_ID_LENGTH))); +} + +int ha_ctcpart::extra(enum ha_extra_function operation) { + if (operation == HA_EXTRA_SECONDARY_SORT_ROWID) { + m_ref_usage = Partition_helper::REF_USED_FOR_SORT; + m_queue->m_fun = key_and_rowid_cmp; + return (0); + } + return (ha_ctc::extra(operation)); +} + +int ha_ctcpart::cmp_ref(const uchar *ref1, const uchar *ref2) const { + DBUG_TRACE; + int cmp = ha_ctc::cmp_ref(ref1 + PARTITION_BYTES_IN_POS, ref2 + PARTITION_BYTES_IN_POS); + + return (cmp); +} + /** Get a row from a position. Fetches a row from the table based on a row reference. diff --git a/storage/ctc/ha_ctcpart.h b/storage/ctc/ha_ctcpart.h index 8f010e1..e4c99ac 100644 --- a/storage/ctc/ha_ctcpart.h +++ b/storage/ctc/ha_ctcpart.h @@ -213,6 +213,12 @@ class ha_ctcpart : public ha_ctc, const uchar *key, key_part_map keypart_map, enum ha_rkey_function find_flag) override; + static int key_and_rowid_cmp(KEY **key_info, uchar *a, uchar *b); + + int extra(enum ha_extra_function operation) override; + + int cmp_ref(const uchar *ref1, const uchar *ref2) const override; + /** Open an CTC table. @param[in] name table name @param[in] mode access mode -- Gitee