mirror of
https://github.com/MariaDB/server.git
synced 2025-07-30 16:24:05 +03:00
Added rowid_filter support to Aria
This includes: - cleanup and optimization of filtering and pushdown engine code. - Adjusted costs for rowid filters (based on extensive testing and profiling). This made a small two changes to the handler_rowid_filter_is_active() API: - One should not call it with a zero pointer! - One does not need to call handler_rowid_filter_is_active() for every row anymore. It is enough to check if filter is active by calling it call it during index_init() or when handler::rowid_filter_changed() is called The changes was to avoid unnecessary function calls and checks if pushdown conditions and rowid_filter is not used. Updated costs for rowid_filter_lookup() to be closer to reality. The old cost was based only on rowid_compare_cost. This is now changed to take into account the overhead in checking the rowid. Changed the Range_rowid_filter class to use DYNAMIC_ARRAY directly instead of Dynamic_array<>. This was done to be able to use the new append_dynamic() functions which gives a notable speed improvment compared to the old code. Removing the abstraction also makes the code easier to understand. The cost of filtering is now slightly lower than before, which is reflected in some test cases that is now using rowid filters.
This commit is contained in:
@ -154,6 +154,5 @@ typedef enum check_result {
|
||||
|
||||
typedef check_result_t (*index_cond_func_t)(void *param);
|
||||
typedef check_result_t (*rowid_filter_func_t)(void *param);
|
||||
typedef int (*rowid_filter_is_active_func_t)(void *param);
|
||||
|
||||
#endif /* _my_compare_h */
|
||||
|
@ -353,6 +353,14 @@ typedef struct st_dynamic_array
|
||||
myf malloc_flags;
|
||||
} DYNAMIC_ARRAY;
|
||||
|
||||
|
||||
typedef struct st_dynamic_array_append
|
||||
{
|
||||
DYNAMIC_ARRAY *array;
|
||||
uchar *pos, *end;
|
||||
} DYNAMIC_ARRAY_APPEND;
|
||||
|
||||
|
||||
typedef struct st_my_tmpdir
|
||||
{
|
||||
DYNAMIC_ARRAY full_list;
|
||||
@ -856,6 +864,10 @@ extern void freeze_size(DYNAMIC_ARRAY *array);
|
||||
#define push_dynamic(A,B) insert_dynamic((A),(B))
|
||||
#define reset_dynamic(array) ((array)->elements= 0)
|
||||
#define sort_dynamic(A,cmp) my_qsort((A)->buffer, (A)->elements, (A)->size_of_element, (cmp))
|
||||
extern void init_append_dynamic(DYNAMIC_ARRAY_APPEND *append,
|
||||
DYNAMIC_ARRAY *array);
|
||||
extern my_bool append_dynamic(DYNAMIC_ARRAY_APPEND *append,
|
||||
const void * element);
|
||||
|
||||
extern my_bool init_dynamic_string(DYNAMIC_STRING *str, const char *init_str,
|
||||
size_t init_alloc,size_t alloc_increment);
|
||||
|
@ -12239,16 +12239,16 @@ explain select * from t1 where a<10 and b between 10 and 50 and c < 10 {
|
||||
"rowid_filter_index": "b",
|
||||
"index_only_cost": 0.001515222,
|
||||
"filter_startup_cost": 3.004222e-4,
|
||||
"find_key_and_filter_lookup_cost": 6.445451e-4,
|
||||
"find_key_and_filter_lookup_cost": 7.827422e-4,
|
||||
"filter_selectivity": 0.021,
|
||||
"original_rows": 9,
|
||||
"new_rows": 0.189,
|
||||
"original_access_cost": 0.011516778,
|
||||
"with_filter_access_cost": 0.0023698,
|
||||
"with_filter_access_cost": 0.002507997,
|
||||
"original_found_rows_cost": 0.010001556,
|
||||
"with_filter_found_rows_cost": 2.100327e-4,
|
||||
"org_cost": 0.011804778,
|
||||
"filter_cost": 0.00267627,
|
||||
"filter_cost": 0.002814467,
|
||||
"filter_used": true
|
||||
},
|
||||
"access_type": "range",
|
||||
@ -12256,7 +12256,7 @@ explain select * from t1 where a<10 and b between 10 and 50 and c < 10 {
|
||||
"rows": 9,
|
||||
"rows_after_filter": 0.189,
|
||||
"rows_out": 0.017766,
|
||||
"cost": 0.00267627,
|
||||
"cost": 0.002814467,
|
||||
"chosen": true
|
||||
}
|
||||
],
|
||||
@ -12264,7 +12264,7 @@ explain select * from t1 where a<10 and b between 10 and 50 and c < 10 {
|
||||
"type": "range",
|
||||
"rows_read": 0.189,
|
||||
"rows_out": 0.017766,
|
||||
"cost": 0.00267627,
|
||||
"cost": 0.002814467,
|
||||
"uses_join_buffering": false,
|
||||
"rowid_filter_index": "b"
|
||||
}
|
||||
@ -12276,7 +12276,7 @@ explain select * from t1 where a<10 and b between 10 and 50 and c < 10 {
|
||||
"plan_prefix": "",
|
||||
"table": "t1",
|
||||
"rows_for_plan": 0.017766,
|
||||
"cost_for_plan": 0.00267627,
|
||||
"cost_for_plan": 0.002814467,
|
||||
"pushdown_cond_selectivity": 0.094,
|
||||
"filtered": 0.1974,
|
||||
"rows_out": 0.017766
|
||||
@ -12286,7 +12286,7 @@ explain select * from t1 where a<10 and b between 10 and 50 and c < 10 {
|
||||
{
|
||||
"best_join_order": ["t1"],
|
||||
"rows": 0.017766,
|
||||
"cost": 0.00267627
|
||||
"cost": 0.002814467
|
||||
},
|
||||
{
|
||||
"table": "t1",
|
||||
@ -12674,20 +12674,20 @@ explain format=json select * from three, t1 where t1.a=three.a and t1.b<5000 and
|
||||
"rowid_filter_index": "b",
|
||||
"index_only_cost": 0.092006157,
|
||||
"filter_startup_cost": 0.149564727,
|
||||
"find_key_and_filter_lookup_cost": 0.085742374,
|
||||
"find_key_and_filter_lookup_cost": 0.129350121,
|
||||
"filter_selectivity": 0.4312,
|
||||
"original_rows": 1000,
|
||||
"new_rows": 431.2,
|
||||
"original_access_cost": 1.203290157,
|
||||
"with_filter_access_cost": 0.656934192,
|
||||
"with_filter_access_cost": 0.700541939,
|
||||
"original_found_rows_cost": 1.111284,
|
||||
"with_filter_found_rows_cost": 0.479185661,
|
||||
"org_cost": 3.705870471,
|
||||
"filter_cost": 2.161762502,
|
||||
"filter_cost": 2.292585745,
|
||||
"filter_used": true
|
||||
},
|
||||
"rows": 431.2,
|
||||
"cost": 2.161762502,
|
||||
"cost": 2.292585745,
|
||||
"chosen": true
|
||||
},
|
||||
{
|
||||
|
@ -329,7 +329,7 @@ set optimizer_trace='enabled=on';
|
||||
# 3-way ROR-intersection
|
||||
explain select key1,key2,key3 from t1 where key1=100 and key2=100 and key3=100;
|
||||
id select_type table type possible_keys key key_len ref rows Extra
|
||||
1 SIMPLE t1 ref|filter key1,key2,key3 key1|key2 5|5 const 2243 (3%) Using where; Using rowid filter
|
||||
1 SIMPLE t1 index_merge key1,key2,key3 key1,key2 5,5 NULL 77 Using intersect(key1,key2); Using where
|
||||
select JSON_DETAILED(JSON_EXTRACT(trace, '$**.analyzing_range_alternatives')) from INFORMATION_SCHEMA.OPTIMIZER_TRACE;
|
||||
JSON_DETAILED(JSON_EXTRACT(trace, '$**.analyzing_range_alternatives'))
|
||||
[
|
||||
@ -423,22 +423,6 @@ JSON_DETAILED(JSON_EXTRACT(trace, '$**.analyzing_range_alternatives'))
|
||||
},
|
||||
"analyzing_index_merge_union":
|
||||
[]
|
||||
},
|
||||
{
|
||||
"range_scan_alternatives":
|
||||
[
|
||||
{
|
||||
"index": "key2",
|
||||
"ranges":
|
||||
["(100) <= (key2) <= (100)"],
|
||||
"rowid_ordered": true,
|
||||
"using_mrr": false,
|
||||
"index_only": true,
|
||||
"rows": 2243,
|
||||
"cost": 0.312832109,
|
||||
"chosen": true
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
select JSON_DETAILED(JSON_EXTRACT(trace, '$**.chosen_range_access_summary')) from INFORMATION_SCHEMA.OPTIMIZER_TRACE;
|
||||
@ -473,19 +457,6 @@ JSON_DETAILED(JSON_EXTRACT(trace, '$**.chosen_range_access_summary'))
|
||||
"rows_for_plan": 77,
|
||||
"cost_for_plan": 0.572490756,
|
||||
"chosen": true
|
||||
},
|
||||
{
|
||||
"range_access_plan":
|
||||
{
|
||||
"type": "range_scan",
|
||||
"index": "key2",
|
||||
"rows": 2243,
|
||||
"ranges":
|
||||
["(100) <= (key2) <= (100)"]
|
||||
},
|
||||
"rows_for_plan": 2243,
|
||||
"cost_for_plan": 0.312832109,
|
||||
"chosen": true
|
||||
}
|
||||
]
|
||||
# ROR-union(ROR-intersection, ROR-range)
|
||||
|
@ -31,8 +31,8 @@ OPTIMIZER_DISK_READ_RATIO 0.020000
|
||||
OPTIMIZER_ROW_COPY_COST 0.060866
|
||||
OPTIMIZER_ROW_LOOKUP_COST 0.130839
|
||||
OPTIMIZER_ROW_NEXT_FIND_COST 0.045916
|
||||
OPTIMIZER_ROWID_COMPARE_COST 0.001000
|
||||
OPTIMIZER_ROWID_COPY_COST 0.001000
|
||||
OPTIMIZER_ROWID_COMPARE_COST 0.002653
|
||||
OPTIMIZER_ROWID_COPY_COST 0.002653
|
||||
ENGINE default
|
||||
OPTIMIZER_DISK_READ_COST 10.240000
|
||||
OPTIMIZER_INDEX_BLOCK_COPY_COST 0.035600
|
||||
|
@ -1967,7 +1967,7 @@ select count(*) from t2 left join t1
|
||||
on (t1.key1 < 3 or t1.key1 between 920 and 930) and t1.key2 < 1000;
|
||||
id select_type table type possible_keys key key_len ref rows Extra
|
||||
1 SIMPLE t2 ALL NULL NULL NULL NULL 64
|
||||
1 SIMPLE t1 range|filter i1,i2 i1|i2 4|4 NULL 12 (89%) Using where; Using join buffer (flat, BNL join); Using rowid filter
|
||||
1 SIMPLE t1 range i1,i2 i1 4 NULL 12 Using where; Using join buffer (flat, BNL join)
|
||||
select count(*) from t2 left join t1
|
||||
on (t1.key1 < 3 or t1.key1 between 920 and 930) and t1.key2 < 1000;
|
||||
count(*)
|
||||
|
@ -2214,695 +2214,3 @@ ALTER TABLE orders DROP COLUMN o_totaldiscount;
|
||||
DROP VIEW v1;
|
||||
DROP DATABASE dbt3_s001;
|
||||
use test;
|
||||
#
|
||||
# MDEV-18816: potential range filter for one join table with
|
||||
# impossible WHERE for another
|
||||
#
|
||||
create table t1 (
|
||||
pk int not null primary key, c2 varchar(10) , i1 int,key (c2)
|
||||
) engine=myisam;
|
||||
insert into t1 values (1,'a',-5),(2,'a',null);
|
||||
create table t2 (
|
||||
pk int, i1 int, c1 varchar(30) , key c1 (c1(30)), key i1 (i1)
|
||||
) engine=myisam;
|
||||
insert into t2 values
|
||||
(1,-5,'a'),(2,null,'a'),(3,null,'a'),(4,null,'a'),(5,5,'a'),(6,null,'a'),
|
||||
(7,4,'a'),(8,55,'a'),(9,null,'a'),(10,null,'a'),(11,null,'a'),(12,-5,'a'),
|
||||
(13,-5,'a'),(14,null,'a'),(15,null,'a'),(16,-5,'a'),(17,-5,'a');
|
||||
select 1
|
||||
from t1
|
||||
left join
|
||||
t2 join t1 as t1_a on t2.i1 = t1_a.pk
|
||||
on t1.c2 = t2.c1
|
||||
where t1_a.pk is null and t1_a.i1 != 3;
|
||||
1
|
||||
explain extended select 1
|
||||
from t1
|
||||
left join
|
||||
t2 join t1 as t1_a on t2.i1 = t1_a.pk
|
||||
on t1.c2 = t2.c1
|
||||
where t1_a.pk is null and t1_a.i1 != 3;
|
||||
id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||
1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
|
||||
Warnings:
|
||||
Note 1003 select 1 AS `1` from `test`.`t1` join `test`.`t2` join `test`.`t1` `t1_a` where 0
|
||||
drop table t1,t2;
|
||||
#
|
||||
# MDEV-18640: TABLE::prune_range_rowid_filters: Conditional jump or
|
||||
# move depends on uninitialized value
|
||||
#
|
||||
CREATE TABLE t1 (
|
||||
pk INT, i INT, PRIMARY KEY (pk), KEY (pk,i)
|
||||
) ENGINE=MyISAM;
|
||||
INSERT INTO t1 VALUES (1,10), (7,70), (2,20);
|
||||
SELECT * FROM t1 WHERE pk < 5;
|
||||
pk i
|
||||
1 10
|
||||
2 20
|
||||
DROP TABLE t1;
|
||||
#
|
||||
# MDEV-18956: Possible rowid filter for subquery for which
|
||||
# in_to_exists strategy has been chosen
|
||||
#
|
||||
CREATE TABLE t1 (pk int) engine=myisam ;
|
||||
INSERT INTO t1 VALUES (1),(2);
|
||||
CREATE TABLE t2 (
|
||||
pk int auto_increment PRIMARY KEY,
|
||||
i1 int, i2 int, c2 varchar(1),
|
||||
KEY (i1), KEY (i2)
|
||||
) engine=myisam;
|
||||
INSERT INTO t2 VALUES
|
||||
(1,8,6,'t'),(2,5,7,'i'),(3,4,4,'h'),(4,207,38,'d'),(5,183,206,'b'),
|
||||
(6,7,null,'o'),(7,1,2,'j'),(8,17,36,'s'),(9,4,5,'q'),(10,0,6,'l'),
|
||||
(11,1,9,'j'),(12,5,6,'y'),(13,null,0,'i'),(14,7,7,'x'),(15,5,2,'u');
|
||||
SELECT * FROM t1 HAVING (7, 9) IN (SELECT t2.i1, t2.i2 FROM t2 WHERE t2.i1 = 3);
|
||||
pk
|
||||
EXPLAIN EXTENDED
|
||||
SELECT * FROM t1 HAVING (7, 9) IN (SELECT t2.i1, t2.i2 FROM t2 WHERE t2.i1 = 3);
|
||||
id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||
1 PRIMARY NULL NULL NULL NULL NULL NULL NULL NULL Impossible HAVING
|
||||
2 SUBQUERY NULL NULL NULL NULL NULL NULL NULL NULL no matching row in const table
|
||||
Warnings:
|
||||
Note 1003 /* select#1 */ select `test`.`t1`.`pk` AS `pk` from `test`.`t1` having 0
|
||||
DROP TABLE t1,t2;
|
||||
#
|
||||
# MDEV-19255: rowid range filter built for range condition
|
||||
# that uses in expensive subquery
|
||||
#
|
||||
CREATE TABLE t1 (
|
||||
pk1 INT PRIMARY KEY, a1 INT, b1 VARCHAR(1), KEY(a1), KEY(b1)
|
||||
) ENGINE=MyISAM;
|
||||
INSERT INTO t1 VALUES
|
||||
(10,0,'z'),(11,3,'j'),(12,8,'f'),(13,8,'p'),(14,6,'w'),(15,0,'c'),(16,1,'j'),
|
||||
(17,1,'f'),(18,5,'v'),(19,3,'f'),(20,2,'q'),(21,8,'y'),(22,0,'a'),(23,9,'w'),
|
||||
(24,3,'e'),(25,1,'b'),(26,9,'r'),(27,2,'k'),(28,5,'c'),(29,3,'k'),(30,9,'b'),
|
||||
(31,8,'j'),(32,1,'t'),(33,8,'n'),(34,3,'z'),(35,0,'u'),(36,3,'a'),(37,3,'g'),
|
||||
(38,1,'f'),(39,6,'p'),(40,6,'m'),(41,6,'t'),(42,7,'i'),(43,4,'h'),(44,3,'d'),
|
||||
(45,2,'b'),(46,1,'o'),(47,2,'j'),(48,6,'s'),(49,5,'q'),(50,6,'l'),(51,9,'j'),
|
||||
(52,6,'y'),(53,0,'i'),(54,7,'x'),(55,2,'u'),(56,6,'t'),(57,4,'b'),(58,5,'m'),
|
||||
(59,4,'x'),(60,8,'x'),(61,6,'v'),(62,8,'m'),(63,4,'j'),(64,8,'z'),(65,2,'a'),
|
||||
(66,9,'i'),(67,4,'g'),(68,8,'h'),(69,1,'p'),(70,8,'a'),(71,0,'x'),(72,2,'s'),
|
||||
(73,6,'k'),(74,0,'m'),(75,6,'e'),(76,9,'y'),(77,7,'d'),(78,7,'w'),(79,6,'y'),
|
||||
(80,9,'s'),(81,9,'x'),(82,6,'l'),(83,9,'f'),(84,8,'x'),(85,1,'p'),(86,7,'y'),
|
||||
(87,6,'p'),(88,1,'g'),(89,3,'c'),(90,5,'h'),(91,3,'p'),(92,2,'b'),(93,1,NULL),
|
||||
(94,3,NULL),(95,2,'y'),(96,7,'s'),(97,7,'x'),(98,6,'i'),(99,9,'t'),(100,5,'j'),
|
||||
(101,0,'u'),(102,7,'r'),(103,2,'x'),(104,8,'e'),(105,8,'i'),(106,5,'q'),
|
||||
(107,8,'z'),(108,3,'k'),(109,65,NULL);
|
||||
CREATE TABLE t2 (pk2 INT PRIMARY KEY, a2 INT, b2 VARCHAR(1)) ENGINE=MyISAM;
|
||||
INSERT INTO t2 VALUES (1,1,'i');
|
||||
INSERT INTO t2 SELECT * FROM t1;
|
||||
INSERT INTO t1 SELECT pk1+200, a1, b1 FROM t1;
|
||||
INSERT INTO t1 SELECT pk1+400, a1, b1 FROM t1;
|
||||
ANALYZE TABLE t1,t2 PERSISTENT FOR ALL;
|
||||
Table Op Msg_type Msg_text
|
||||
test.t1 analyze status Engine-independent statistics collected
|
||||
test.t1 analyze status OK
|
||||
test.t2 analyze status Engine-independent statistics collected
|
||||
test.t2 analyze status OK
|
||||
SELECT * FROM t1 INNER JOIN t2 ON ( pk1+1 = pk2+2 AND a1 = a2 )
|
||||
WHERE b1 <= ( SELECT MAX(b2) FROM t2 WHERE pk2 <= 1 );
|
||||
pk1 a1 b1 pk2 a2 b2
|
||||
17 1 f 16 1 j
|
||||
37 3 g 36 3 a
|
||||
105 8 i 104 8 e
|
||||
EXPLAIN EXTENDED SELECT * FROM t1 INNER JOIN t2 ON ( pk1+1 = pk2+2 AND a1 = a2 )
|
||||
WHERE b1 <= ( SELECT MAX(b2) FROM t2 WHERE pk2 <= 1 );
|
||||
id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||
1 PRIMARY t2 ALL NULL NULL NULL NULL 101 100.00
|
||||
1 PRIMARY t1 ALL a1,b1 NULL NULL NULL 400 2.61 Using where; Using join buffer (flat, BNL join)
|
||||
2 SUBQUERY t2 range PRIMARY PRIMARY 4 NULL 1 100.00 Using index condition
|
||||
Warnings:
|
||||
Note 1003 /* select#1 */ select `test`.`t1`.`pk1` AS `pk1`,`test`.`t1`.`a1` AS `a1`,`test`.`t1`.`b1` AS `b1`,`test`.`t2`.`pk2` AS `pk2`,`test`.`t2`.`a2` AS `a2`,`test`.`t2`.`b2` AS `b2` from `test`.`t1` join `test`.`t2` where `test`.`t1`.`a1` = `test`.`t2`.`a2` and `test`.`t1`.`b1` <= (/* select#2 */ select max(`test`.`t2`.`b2`) from `test`.`t2` where `test`.`t2`.`pk2` <= 1) and `test`.`t1`.`pk1` + 1 = `test`.`t2`.`pk2` + 2
|
||||
set @@optimizer_where_cost=0.0356*4;
|
||||
EXPLAIN EXTENDED SELECT * FROM t1 INNER JOIN t2 ON ( pk1+1 = pk2+2 AND a1 = a2 )
|
||||
WHERE b1 <= ( SELECT MAX(b2) FROM t2 WHERE pk2 <= 1 );
|
||||
id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||
1 PRIMARY t2 ALL NULL NULL NULL NULL 101 100.00 Using where
|
||||
1 PRIMARY t1 ref|filter a1,b1 a1|b1 5|4 test.t2.a2 36 (29%) 28.75 Using where; Using rowid filter
|
||||
2 SUBQUERY t2 range PRIMARY PRIMARY 4 NULL 1 100.00 Using index condition
|
||||
Warnings:
|
||||
Note 1003 /* select#1 */ select `test`.`t1`.`pk1` AS `pk1`,`test`.`t1`.`a1` AS `a1`,`test`.`t1`.`b1` AS `b1`,`test`.`t2`.`pk2` AS `pk2`,`test`.`t2`.`a2` AS `a2`,`test`.`t2`.`b2` AS `b2` from `test`.`t1` join `test`.`t2` where `test`.`t1`.`a1` = `test`.`t2`.`a2` and `test`.`t1`.`b1` <= (/* select#2 */ select max(`test`.`t2`.`b2`) from `test`.`t2` where `test`.`t2`.`pk2` <= 1) and `test`.`t1`.`pk1` + 1 = `test`.`t2`.`pk2` + 2
|
||||
EXPLAIN FORMAT=JSON SELECT * FROM t1 INNER JOIN t2 ON ( pk1+1 = pk2+2 AND a1 = a2 )
|
||||
WHERE b1 <= ( SELECT MAX(b2) FROM t2 WHERE pk2 <= 1 );
|
||||
EXPLAIN
|
||||
{
|
||||
"query_block": {
|
||||
"select_id": 1,
|
||||
"nested_loop": [
|
||||
{
|
||||
"table": {
|
||||
"table_name": "t2",
|
||||
"access_type": "ALL",
|
||||
"rows": 101,
|
||||
"filtered": 100,
|
||||
"attached_condition": "t2.a2 is not null"
|
||||
}
|
||||
},
|
||||
{
|
||||
"table": {
|
||||
"table_name": "t1",
|
||||
"access_type": "ref",
|
||||
"possible_keys": ["a1", "b1"],
|
||||
"key": "a1",
|
||||
"key_length": "5",
|
||||
"used_key_parts": ["a1"],
|
||||
"ref": ["test.t2.a2"],
|
||||
"rowid_filter": {
|
||||
"range": {
|
||||
"key": "b1",
|
||||
"used_key_parts": ["b1"]
|
||||
},
|
||||
"rows": 115,
|
||||
"selectivity_pct": 28.75
|
||||
},
|
||||
"rows": 36,
|
||||
"filtered": 28.75,
|
||||
"attached_condition": "t1.b1 <= (subquery#2) and t1.pk1 + 1 = t2.pk2 + 2"
|
||||
}
|
||||
}
|
||||
],
|
||||
"subqueries": [
|
||||
{
|
||||
"query_block": {
|
||||
"select_id": 2,
|
||||
"nested_loop": [
|
||||
{
|
||||
"table": {
|
||||
"table_name": "t2",
|
||||
"access_type": "range",
|
||||
"possible_keys": ["PRIMARY"],
|
||||
"key": "PRIMARY",
|
||||
"key_length": "4",
|
||||
"used_key_parts": ["pk2"],
|
||||
"rows": 1,
|
||||
"filtered": 100,
|
||||
"index_condition": "t2.pk2 <= 1"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
set @@optimizer_where_cost=default;
|
||||
DROP TABLE t1,t2;
|
||||
#
|
||||
# MDEV-21794: Optimizer flag rowid_filter leads to long query
|
||||
#
|
||||
create table t10(a int);
|
||||
insert into t10 values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9);
|
||||
create table t11(a int);
|
||||
insert into t11 select A.a + B.a* 10 + C.a * 100 from t10 A, t10 B, t10 C;
|
||||
CREATE TABLE t1 (
|
||||
el_id int(10) unsigned NOT NULL ,
|
||||
el_index blob NOT NULL,
|
||||
el_index_60 varbinary(60) NOT NULL,
|
||||
filler blob,
|
||||
PRIMARY KEY (el_id),
|
||||
KEY el_index (el_index(60)),
|
||||
KEY el_index_60 (el_index_60,el_id)
|
||||
);
|
||||
insert into t1
|
||||
select
|
||||
A.a+1000*B.a,
|
||||
A.a+1000*B.a + 10000,
|
||||
A.a+1000*B.a + 10000,
|
||||
'filler-data-filler-data'
|
||||
from
|
||||
t11 A, t10 B;
|
||||
analyze table t1 persistent for all;
|
||||
Table Op Msg_type Msg_text
|
||||
test.t1 analyze status Engine-independent statistics collected
|
||||
test.t1 analyze Warning Engine-independent statistics are not collected for column 'el_index'
|
||||
test.t1 analyze Warning Engine-independent statistics are not collected for column 'filler'
|
||||
test.t1 analyze status Table is already up to date
|
||||
# This must not use rowid_filter with key=el_index|el_index_60:
|
||||
explain
|
||||
select * from t1
|
||||
where el_index like '10%' and (el_index_60 like '10%' or el_index_60 like '20%');
|
||||
id select_type table type possible_keys key key_len ref rows Extra
|
||||
1 SIMPLE t1 range el_index,el_index_60 el_index 62 NULL 645 Using where
|
||||
drop table t10, t11, t1;
|
||||
#
|
||||
# MDEV-22160: SIGSEGV in st_join_table::save_explain_data on SELECT
|
||||
#
|
||||
set @save_optimizer_switch= @@optimizer_switch;
|
||||
SET @@optimizer_switch="index_merge_sort_union=OFF";
|
||||
CREATE TABLE t1 (a INT, b INT, INDEX(a), INDEX(b));
|
||||
INSERT INTO t1 VALUES (0,0),(0,0),(1,0),(-1,1), (-2,1), (-2,3), (-3,4), (-2,4),(3,3),(3,4),(3,5),(8,8),(8,9),(1,0),(2,0),(0,0),(0,0);
|
||||
explain
|
||||
SELECT * FROM t1 WHERE a > 0 AND b=0;
|
||||
id select_type table type possible_keys key key_len ref rows Extra
|
||||
1 SIMPLE t1 ref|filter a,b b|a 5|5 const 7 (47%) Using where; Using rowid filter
|
||||
SELECT * FROM t1 WHERE a > 0 AND b=0;
|
||||
a b
|
||||
1 0
|
||||
1 0
|
||||
2 0
|
||||
drop table t1;
|
||||
SET @@optimizer_switch=@save_optimizer_switch;
|
||||
#
|
||||
# MDEV-28846: Poor performance when rowid filter contains no elements
|
||||
#
|
||||
create table t1 (
|
||||
pk int primary key auto_increment,
|
||||
nm varchar(32),
|
||||
fl1 tinyint default 0,
|
||||
fl2 tinyint default 0,
|
||||
index idx1(nm, fl1),
|
||||
index idx2(fl2)
|
||||
) engine=myisam;
|
||||
create table name (
|
||||
pk int primary key auto_increment,
|
||||
nm bigint
|
||||
) engine=myisam;
|
||||
create table flag2 (
|
||||
pk int primary key auto_increment,
|
||||
fl2 tinyint
|
||||
) engine=myisam;
|
||||
insert into name(nm) select seq from seq_1_to_1000 order by rand(17);
|
||||
insert into flag2(fl2) select seq mod 2 from seq_1_to_1000 order by rand(19);
|
||||
insert into t1(nm,fl2)
|
||||
select nm, fl2 from name, flag2 where name.pk = flag2.pk;
|
||||
analyze table t1 persistent for all;
|
||||
Table Op Msg_type Msg_text
|
||||
test.t1 analyze status Engine-independent statistics collected
|
||||
test.t1 analyze status Table is already up to date
|
||||
select '500%' as a;
|
||||
a
|
||||
500%
|
||||
set optimizer_switch='rowid_filter=on';
|
||||
explain
|
||||
select * from t1 where nm like '500%' AND fl2 = 0;
|
||||
id select_type table type possible_keys key key_len ref rows Extra
|
||||
1 SIMPLE t1 range idx1,idx2 idx1 35 NULL 1 Using index condition; Using where
|
||||
analyze format=json
|
||||
select * from t1 where nm like '500%' AND fl2 = 0;
|
||||
ANALYZE
|
||||
{
|
||||
"query_optimization": {
|
||||
"r_total_time_ms": "REPLACED"
|
||||
},
|
||||
"query_block": {
|
||||
"select_id": 1,
|
||||
"r_loops": 1,
|
||||
"r_total_time_ms": "REPLACED",
|
||||
"nested_loop": [
|
||||
{
|
||||
"table": {
|
||||
"table_name": "t1",
|
||||
"access_type": "range",
|
||||
"possible_keys": ["idx1", "idx2"],
|
||||
"key": "idx1",
|
||||
"key_length": "35",
|
||||
"used_key_parts": ["nm"],
|
||||
"r_loops": 1,
|
||||
"rows": 1,
|
||||
"r_rows": 1,
|
||||
"r_table_time_ms": "REPLACED",
|
||||
"r_other_time_ms": "REPLACED",
|
||||
"filtered": 49.20000076,
|
||||
"r_filtered": 100,
|
||||
"index_condition": "t1.nm like '500%'",
|
||||
"attached_condition": "t1.fl2 = 0"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
select * from t1 where nm like '500%' AND fl2 = 0;
|
||||
pk nm fl1 fl2
|
||||
517 500 0 0
|
||||
truncate table name;
|
||||
truncate table flag2;
|
||||
truncate table t1;
|
||||
insert into name(nm) select seq from seq_1_to_1000 order by rand(17);
|
||||
insert into flag2(fl2) select seq mod 2 from seq_1_to_1000 order by rand(19);
|
||||
insert into t1(nm,fl2)
|
||||
select nm, fl2 from name, flag2 where name.pk = flag2.pk;
|
||||
analyze table t1 persistent for all;
|
||||
Table Op Msg_type Msg_text
|
||||
test.t1 analyze status Engine-independent statistics collected
|
||||
test.t1 analyze status Table is already up to date
|
||||
set optimizer_switch='rowid_filter=off';
|
||||
explain
|
||||
select * from t1 where nm like '500%' AND fl2 = 0;
|
||||
id select_type table type possible_keys key key_len ref rows Extra
|
||||
1 SIMPLE t1 range idx1,idx2 idx1 35 NULL 1 Using index condition; Using where
|
||||
analyze format=json
|
||||
select * from t1 where nm like '500%' AND fl2 = 0;
|
||||
ANALYZE
|
||||
{
|
||||
"query_optimization": {
|
||||
"r_total_time_ms": "REPLACED"
|
||||
},
|
||||
"query_block": {
|
||||
"select_id": 1,
|
||||
"r_loops": 1,
|
||||
"r_total_time_ms": "REPLACED",
|
||||
"nested_loop": [
|
||||
{
|
||||
"table": {
|
||||
"table_name": "t1",
|
||||
"access_type": "range",
|
||||
"possible_keys": ["idx1", "idx2"],
|
||||
"key": "idx1",
|
||||
"key_length": "35",
|
||||
"used_key_parts": ["nm"],
|
||||
"r_loops": 1,
|
||||
"rows": 1,
|
||||
"r_rows": 1,
|
||||
"r_table_time_ms": "REPLACED",
|
||||
"r_other_time_ms": "REPLACED",
|
||||
"filtered": 49.20000076,
|
||||
"r_filtered": 100,
|
||||
"index_condition": "t1.nm like '500%'",
|
||||
"attached_condition": "t1.fl2 = 0"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
select * from t1 where nm like '500%' AND fl2 = 0;
|
||||
pk nm fl1 fl2
|
||||
517 500 0 0
|
||||
truncate table name;
|
||||
truncate table flag2;
|
||||
truncate table t1;
|
||||
insert into name(nm) select seq from seq_1_to_1000 order by rand(17);
|
||||
insert into flag2(fl2) select seq mod 10 from seq_1_to_1000 order by rand(19);
|
||||
insert into t1(nm,fl2)
|
||||
select nm, fl2 from name, flag2 where name.pk = flag2.pk;
|
||||
analyze table t1 persistent for all;
|
||||
Table Op Msg_type Msg_text
|
||||
test.t1 analyze status Engine-independent statistics collected
|
||||
test.t1 analyze status Table is already up to date
|
||||
select '607%' as a;
|
||||
a
|
||||
607%
|
||||
set optimizer_switch='rowid_filter=on';
|
||||
explain
|
||||
select * from t1 where nm like '607%' AND fl2 = 0;
|
||||
id select_type table type possible_keys key key_len ref rows Extra
|
||||
1 SIMPLE t1 range idx1,idx2 idx1 35 NULL 1 Using index condition; Using where
|
||||
select * from t1 where nm like '607%' AND fl2 = 0;
|
||||
pk nm fl1 fl2
|
||||
721 607 0 0
|
||||
truncate table name;
|
||||
truncate table flag2;
|
||||
truncate table t1;
|
||||
insert into name(nm) select seq from seq_1_to_10000 order by rand(17);
|
||||
insert into flag2(fl2) select seq mod 100 from seq_1_to_10000 order by rand(19);
|
||||
insert into t1(nm,fl2)
|
||||
select nm, fl2 from name, flag2 where name.pk = flag2.pk;
|
||||
analyze table t1 persistent for all;
|
||||
Table Op Msg_type Msg_text
|
||||
test.t1 analyze status Engine-independent statistics collected
|
||||
test.t1 analyze status Table is already up to date
|
||||
select '75%' as a;
|
||||
a
|
||||
75%
|
||||
set optimizer_switch='rowid_filter=on';
|
||||
explain
|
||||
select * from t1 where nm like '75%' AND fl2 = 0;
|
||||
id select_type table type possible_keys key key_len ref rows Extra
|
||||
1 SIMPLE t1 ref|filter idx1,idx2 idx2|idx1 2|35 const 55 (1%) Using where; Using rowid filter
|
||||
analyze format=json
|
||||
select * from t1 where nm like '75%' AND fl2 = 0;
|
||||
ANALYZE
|
||||
{
|
||||
"query_optimization": {
|
||||
"r_total_time_ms": "REPLACED"
|
||||
},
|
||||
"query_block": {
|
||||
"select_id": 1,
|
||||
"r_loops": 1,
|
||||
"r_total_time_ms": "REPLACED",
|
||||
"nested_loop": [
|
||||
{
|
||||
"table": {
|
||||
"table_name": "t1",
|
||||
"access_type": "ref",
|
||||
"possible_keys": ["idx1", "idx2"],
|
||||
"key": "idx2",
|
||||
"key_length": "2",
|
||||
"used_key_parts": ["fl2"],
|
||||
"ref": ["const"],
|
||||
"rowid_filter": {
|
||||
"range": {
|
||||
"key": "idx1",
|
||||
"used_key_parts": ["nm"]
|
||||
},
|
||||
"rows": 115,
|
||||
"selectivity_pct": 1.15,
|
||||
"r_rows": 111,
|
||||
"r_lookups": 100,
|
||||
"r_selectivity_pct": 2,
|
||||
"r_buffer_size": "REPLACED",
|
||||
"r_filling_time_ms": "REPLACED"
|
||||
},
|
||||
"r_loops": 1,
|
||||
"rows": 55,
|
||||
"r_rows": 2,
|
||||
"r_table_time_ms": "REPLACED",
|
||||
"r_other_time_ms": "REPLACED",
|
||||
"filtered": 1.149999976,
|
||||
"r_filtered": 100,
|
||||
"attached_condition": "t1.nm like '75%'"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
select * from t1 where nm like '75%' AND fl2 = 0;
|
||||
pk nm fl1 fl2
|
||||
4543 7503 0 0
|
||||
7373 7518 0 0
|
||||
drop table name, flag2;
|
||||
drop table t1;
|
||||
create table t1 (
|
||||
pk int primary key auto_increment,
|
||||
nm char(255),
|
||||
fl1 tinyint default 0,
|
||||
fl2 int default 0,
|
||||
index idx1(nm, fl1),
|
||||
index idx2(fl2)
|
||||
) engine=myisam;
|
||||
create table name (
|
||||
pk int primary key auto_increment,
|
||||
nm bigint
|
||||
) engine=myisam;
|
||||
create table flag2 (
|
||||
pk int primary key auto_increment,
|
||||
fl2 int
|
||||
) engine=myisam;
|
||||
insert into name(nm) select seq from seq_1_to_10000 order by rand(17);
|
||||
insert into flag2(fl2) select seq mod 10 from seq_1_to_10000 order by rand(19);
|
||||
insert into t1(nm,fl2)
|
||||
select nm, fl2 from name, flag2 where name.pk = flag2.pk;
|
||||
analyze table t1 persistent for all;
|
||||
Table Op Msg_type Msg_text
|
||||
test.t1 analyze status Engine-independent statistics collected
|
||||
test.t1 analyze status Table is already up to date
|
||||
select * from t1
|
||||
where
|
||||
(
|
||||
nm like '3400%' or nm like '3402%' or nm like '3403%' or
|
||||
nm like '3404%' or nm like '3405%' or nm like '3406%' or nm like '3407%' or
|
||||
nm like '3409%' or
|
||||
nm like '3411%' or nm like '3412%' or nm like '3413%' or
|
||||
nm like '3414%' or nm like '3415%' or nm like '3416%' or nm like '3417%' or
|
||||
nm like '3418%' or nm like '3419%' or
|
||||
nm like '3421%' or nm like '3422%' or nm like '3423%' or
|
||||
nm like '3424%' or nm like '3425%' or nm like '3426%' or nm like '3427%' or
|
||||
nm like '3428%' or nm like '3429%' or
|
||||
nm like '3430%' or nm like '3431%' or nm like '3432%' or nm like '3433%' or
|
||||
nm like '3434%' or nm like '3435%' or nm like '3436%' or nm like '3437%' or
|
||||
nm like '3439%' or
|
||||
nm like '3440%' or nm like '3441%' or nm like '3442%' or nm like '3443%' or
|
||||
nm like '3444%' or nm like '3445%' or nm like '3446%' or nm like '3447%' or
|
||||
nm like '3448%'
|
||||
) and fl2 = 0;
|
||||
pk nm fl1 fl2
|
||||
analyze format=json select * from t1
|
||||
where
|
||||
(
|
||||
nm like '3400%' or nm like '3402%' or nm like '3403%' or
|
||||
nm like '3404%' or nm like '3405%' or nm like '3406%' or nm like '3407%' or
|
||||
nm like '3409%' or
|
||||
nm like '3411%' or nm like '3412%' or nm like '3413%' or
|
||||
nm like '3414%' or nm like '3415%' or nm like '3416%' or nm like '3417%' or
|
||||
nm like '3418%' or nm like '3419%' or
|
||||
nm like '3421%' or nm like '3422%' or nm like '3423%' or
|
||||
nm like '3424%' or nm like '3425%' or nm like '3426%' or nm like '3427%' or
|
||||
nm like '3428%' or nm like '3429%' or
|
||||
nm like '3430%' or nm like '3431%' or nm like '3432%' or nm like '3433%' or
|
||||
nm like '3434%' or nm like '3435%' or nm like '3436%' or nm like '3437%' or
|
||||
nm like '3439%' or
|
||||
nm like '3440%' or nm like '3441%' or nm like '3442%' or nm like '3443%' or
|
||||
nm like '3444%' or nm like '3445%' or nm like '3446%' or nm like '3447%' or
|
||||
nm like '3448%'
|
||||
) and fl2 = 0;
|
||||
ANALYZE
|
||||
{
|
||||
"query_optimization": {
|
||||
"r_total_time_ms": "REPLACED"
|
||||
},
|
||||
"query_block": {
|
||||
"select_id": 1,
|
||||
"r_loops": 1,
|
||||
"r_total_time_ms": "REPLACED",
|
||||
"nested_loop": [
|
||||
{
|
||||
"table": {
|
||||
"table_name": "t1",
|
||||
"access_type": "range",
|
||||
"possible_keys": ["idx1", "idx2"],
|
||||
"key": "idx1",
|
||||
"key_length": "256",
|
||||
"used_key_parts": ["nm"],
|
||||
"rowid_filter": {
|
||||
"range": {
|
||||
"key": "idx2",
|
||||
"used_key_parts": ["fl2"]
|
||||
},
|
||||
"rows": 863,
|
||||
"selectivity_pct": 8.63,
|
||||
"r_rows": 1000,
|
||||
"r_lookups": 44,
|
||||
"r_selectivity_pct": 0,
|
||||
"r_buffer_size": "REPLACED",
|
||||
"r_filling_time_ms": "REPLACED"
|
||||
},
|
||||
"r_loops": 1,
|
||||
"rows": 44,
|
||||
"r_rows": 0,
|
||||
"r_table_time_ms": "REPLACED",
|
||||
"r_other_time_ms": "REPLACED",
|
||||
"filtered": 8.630000114,
|
||||
"r_filtered": 100,
|
||||
"index_condition": "t1.nm like '3400%' or t1.nm like '3402%' or t1.nm like '3403%' or t1.nm like '3404%' or t1.nm like '3405%' or t1.nm like '3406%' or t1.nm like '3407%' or t1.nm like '3409%' or t1.nm like '3411%' or t1.nm like '3412%' or t1.nm like '3413%' or t1.nm like '3414%' or t1.nm like '3415%' or t1.nm like '3416%' or t1.nm like '3417%' or t1.nm like '3418%' or t1.nm like '3419%' or t1.nm like '3421%' or t1.nm like '3422%' or t1.nm like '3423%' or t1.nm like '3424%' or t1.nm like '3425%' or t1.nm like '3426%' or t1.nm like '3427%' or t1.nm like '3428%' or t1.nm like '3429%' or t1.nm like '3430%' or t1.nm like '3431%' or t1.nm like '3432%' or t1.nm like '3433%' or t1.nm like '3434%' or t1.nm like '3435%' or t1.nm like '3436%' or t1.nm like '3437%' or t1.nm like '3439%' or t1.nm like '3440%' or t1.nm like '3441%' or t1.nm like '3442%' or t1.nm like '3443%' or t1.nm like '3444%' or t1.nm like '3445%' or t1.nm like '3446%' or t1.nm like '3447%' or t1.nm like '3448%'",
|
||||
"attached_condition": "t1.fl2 = 0"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
create table t0 select * from t1 where nm like '34%';
|
||||
delete from t1 using t1,t0 where t1.nm=t0.nm;
|
||||
analyze format=json select * from t1
|
||||
where
|
||||
(
|
||||
nm like '3400%' or nm like '3402%' or nm like '3403%' or
|
||||
nm like '3404%' or nm like '3405%' or nm like '3406%' or nm like '3407%' or
|
||||
nm like '3409%' or
|
||||
nm like '3411%' or nm like '3412%' or nm like '3413%' or
|
||||
nm like '3414%' or nm like '3415%' or nm like '3416%' or nm like '3417%' or
|
||||
nm like '3418%' or nm like '3419%' or
|
||||
nm like '3421%' or nm like '3422%' or nm like '3423%' or
|
||||
nm like '3424%' or nm like '3425%' or nm like '3426%' or nm like '3427%' or
|
||||
nm like '3428%' or nm like '3429%' or
|
||||
nm like '3430%' or nm like '3431%' or nm like '3432%' or nm like '3433%' or
|
||||
nm like '3434%' or nm like '3435%' or nm like '3436%' or nm like '3437%' or
|
||||
nm like '3439%' or
|
||||
nm like '3440%' or nm like '3441%' or nm like '3442%' or nm like '3443%' or
|
||||
nm like '3444%' or nm like '3445%' or nm like '3446%' or nm like '3447%' or
|
||||
nm like '3448%'
|
||||
) and fl2 = 0;
|
||||
ANALYZE
|
||||
{
|
||||
"query_optimization": {
|
||||
"r_total_time_ms": "REPLACED"
|
||||
},
|
||||
"query_block": {
|
||||
"select_id": 1,
|
||||
"r_loops": 1,
|
||||
"r_total_time_ms": "REPLACED",
|
||||
"nested_loop": [
|
||||
{
|
||||
"table": {
|
||||
"table_name": "t1",
|
||||
"access_type": "range",
|
||||
"possible_keys": ["idx1", "idx2"],
|
||||
"key": "idx1",
|
||||
"key_length": "256",
|
||||
"used_key_parts": ["nm"],
|
||||
"rowid_filter": {
|
||||
"range": {
|
||||
"key": "idx2",
|
||||
"used_key_parts": ["fl2"]
|
||||
},
|
||||
"rows": 853,
|
||||
"selectivity_pct": 8.53,
|
||||
"r_rows": 987,
|
||||
"r_lookups": 0,
|
||||
"r_selectivity_pct": 0,
|
||||
"r_buffer_size": "REPLACED",
|
||||
"r_filling_time_ms": "REPLACED"
|
||||
},
|
||||
"r_loops": 1,
|
||||
"rows": 44,
|
||||
"r_rows": 0,
|
||||
"r_table_time_ms": "REPLACED",
|
||||
"r_other_time_ms": "REPLACED",
|
||||
"filtered": 8.529999733,
|
||||
"r_filtered": 100,
|
||||
"index_condition": "t1.nm like '3400%' or t1.nm like '3402%' or t1.nm like '3403%' or t1.nm like '3404%' or t1.nm like '3405%' or t1.nm like '3406%' or t1.nm like '3407%' or t1.nm like '3409%' or t1.nm like '3411%' or t1.nm like '3412%' or t1.nm like '3413%' or t1.nm like '3414%' or t1.nm like '3415%' or t1.nm like '3416%' or t1.nm like '3417%' or t1.nm like '3418%' or t1.nm like '3419%' or t1.nm like '3421%' or t1.nm like '3422%' or t1.nm like '3423%' or t1.nm like '3424%' or t1.nm like '3425%' or t1.nm like '3426%' or t1.nm like '3427%' or t1.nm like '3428%' or t1.nm like '3429%' or t1.nm like '3430%' or t1.nm like '3431%' or t1.nm like '3432%' or t1.nm like '3433%' or t1.nm like '3434%' or t1.nm like '3435%' or t1.nm like '3436%' or t1.nm like '3437%' or t1.nm like '3439%' or t1.nm like '3440%' or t1.nm like '3441%' or t1.nm like '3442%' or t1.nm like '3443%' or t1.nm like '3444%' or t1.nm like '3445%' or t1.nm like '3446%' or t1.nm like '3447%' or t1.nm like '3448%'",
|
||||
"attached_condition": "t1.fl2 = 0"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
drop table t0;
|
||||
set optimizer_switch='rowid_filter=default';
|
||||
drop table name, flag2;
|
||||
drop table t1;
|
||||
set @@use_stat_tables=@save_use_stat_tables;
|
||||
#
|
||||
# MDEV-21633
|
||||
# Assertion `tmp >= 0' failed in best_access_path with rowid_filter=ON
|
||||
#
|
||||
set @save_optimizer_switch= @@optimizer_switch;
|
||||
SET optimizer_switch='rowid_filter=on';
|
||||
CREATE TABLE t1 (
|
||||
pk INT AUTO_INCREMENT,
|
||||
a INT,
|
||||
b VARCHAR(8),
|
||||
KEY(a),
|
||||
PRIMARY KEY(pk),
|
||||
KEY (a,pk)
|
||||
) ENGINE=MyISAM;
|
||||
INSERT INTO t1 (a,b) VALUES
|
||||
(NULL,'d'),(9,'b'),(2,'x'),(5,'k'),(NULL,'d'),(3,'s'),(5,'k'),(1,'r'),
|
||||
(8,'l'),(3,'z'),(1,'c'),(1,'q'),(NULL,'x'),(NULL,'p'),(NULL,'z'),(7,'a'),
|
||||
(0,'i'),(3,'s'),(NULL,'h'),(4,'p'),(1,'i'),(4,'f'),(1,'c'),(NULL,'a'),
|
||||
(NULL,'x'),(1,'b'),(NULL,'n'),(NULL,'h'),(5,'i'),(6,'e'),(NULL,'i'),
|
||||
(7,'e'),(1,'r'),(NULL,'z'),(1,'i'),(14,'c'),(6,'u'),(3,'b'),(4,'z'),
|
||||
(2,'c'),(70,'d'),(NULL,'p'),(21,'j'),(6,'e'),(5,'c'),(13,'i'),(42,'d'),
|
||||
(80,'s'),(14,'t'),(9,'a'),(0,'2'),(0,NULL),(0,NULL),(0,NULL),(0,''),
|
||||
(0,''),(0,'1'),(0,''),(0,''),(0,''),(0,''),(0,NULL),(0,''),(0,''),(0,''),
|
||||
(0,NULL),(0,''),(0,''),(0,''),(0,''),(0,''),(0,''),(0,NULL),(0,NULL),
|
||||
(0,NULL),(0,''),(0,''),(0,''),(0,''),(0,NULL),(0,''),(0,NULL),(0,NULL),
|
||||
(0,''),(0,''),(0,''),(0,NULL),(0,''),(0,NULL),(0,''),(0,''),(0,''),(0,''),
|
||||
(0,''),(0,''),(0,''),(0,NULL),(0,''),(0,NULL),(0,'');
|
||||
CREATE TABLE t2 (c INT) ENGINE=MyISAM;
|
||||
INSERT INTO t2 VALUES (1),(2),(3),(4),(5),(6);
|
||||
SELECT * FROM t1 JOIN t2 WHERE a = c AND pk BETWEEN 4 AND 7 AND a BETWEEN 2 AND 12 AND b != 'foo';
|
||||
pk a b c
|
||||
6 3 s 3
|
||||
4 5 k 5
|
||||
7 5 k 5
|
||||
explain SELECT * FROM t1 JOIN t2 WHERE a = c AND pk BETWEEN 4 AND 7 AND a BETWEEN 2 AND 12 AND b != 'foo';
|
||||
id select_type table type possible_keys key key_len ref rows Extra
|
||||
1 SIMPLE t1 range|filter PRIMARY,a,a_2 PRIMARY|a 4|5 NULL 4 (11%) Using index condition; Using where; Using rowid filter
|
||||
1 SIMPLE t2 ALL NULL NULL NULL NULL 6 Using where; Using join buffer (flat, BNL join)
|
||||
SET optimizer_switch='rowid_filter=off';
|
||||
SELECT * FROM t1 JOIN t2 WHERE a = c AND pk BETWEEN 4 AND 7 AND a BETWEEN 2 AND 12 AND b != 'foo';
|
||||
pk a b c
|
||||
6 3 s 3
|
||||
4 5 k 5
|
||||
7 5 k 5
|
||||
SET @@optimizer_switch=@save_optimizer_switch;
|
||||
DROP TABLE t1, t2;
|
||||
|
@ -250,411 +250,3 @@ DROP VIEW v1;
|
||||
DROP DATABASE dbt3_s001;
|
||||
|
||||
use test;
|
||||
|
||||
--echo #
|
||||
--echo # MDEV-18816: potential range filter for one join table with
|
||||
--echo # impossible WHERE for another
|
||||
--echo #
|
||||
|
||||
create table t1 (
|
||||
pk int not null primary key, c2 varchar(10) , i1 int,key (c2)
|
||||
) engine=myisam;
|
||||
insert into t1 values (1,'a',-5),(2,'a',null);
|
||||
|
||||
create table t2 (
|
||||
pk int, i1 int, c1 varchar(30) , key c1 (c1(30)), key i1 (i1)
|
||||
) engine=myisam;
|
||||
insert into t2 values
|
||||
(1,-5,'a'),(2,null,'a'),(3,null,'a'),(4,null,'a'),(5,5,'a'),(6,null,'a'),
|
||||
(7,4,'a'),(8,55,'a'),(9,null,'a'),(10,null,'a'),(11,null,'a'),(12,-5,'a'),
|
||||
(13,-5,'a'),(14,null,'a'),(15,null,'a'),(16,-5,'a'),(17,-5,'a');
|
||||
|
||||
let $q=
|
||||
select 1
|
||||
from t1
|
||||
left join
|
||||
t2 join t1 as t1_a on t2.i1 = t1_a.pk
|
||||
on t1.c2 = t2.c1
|
||||
where t1_a.pk is null and t1_a.i1 != 3;
|
||||
|
||||
eval $q;
|
||||
eval explain extended $q;
|
||||
|
||||
drop table t1,t2;
|
||||
|
||||
--echo #
|
||||
--echo # MDEV-18640: TABLE::prune_range_rowid_filters: Conditional jump or
|
||||
--echo # move depends on uninitialized value
|
||||
--echo #
|
||||
|
||||
CREATE TABLE t1 (
|
||||
pk INT, i INT, PRIMARY KEY (pk), KEY (pk,i)
|
||||
) ENGINE=MyISAM;
|
||||
INSERT INTO t1 VALUES (1,10), (7,70), (2,20);
|
||||
|
||||
SELECT * FROM t1 WHERE pk < 5;
|
||||
|
||||
DROP TABLE t1;
|
||||
|
||||
--echo #
|
||||
--echo # MDEV-18956: Possible rowid filter for subquery for which
|
||||
--echo # in_to_exists strategy has been chosen
|
||||
--echo #
|
||||
|
||||
CREATE TABLE t1 (pk int) engine=myisam ;
|
||||
INSERT INTO t1 VALUES (1),(2);
|
||||
|
||||
CREATE TABLE t2 (
|
||||
pk int auto_increment PRIMARY KEY,
|
||||
i1 int, i2 int, c2 varchar(1),
|
||||
KEY (i1), KEY (i2)
|
||||
) engine=myisam;
|
||||
|
||||
INSERT INTO t2 VALUES
|
||||
(1,8,6,'t'),(2,5,7,'i'),(3,4,4,'h'),(4,207,38,'d'),(5,183,206,'b'),
|
||||
(6,7,null,'o'),(7,1,2,'j'),(8,17,36,'s'),(9,4,5,'q'),(10,0,6,'l'),
|
||||
(11,1,9,'j'),(12,5,6,'y'),(13,null,0,'i'),(14,7,7,'x'),(15,5,2,'u');
|
||||
|
||||
SELECT * FROM t1 HAVING (7, 9) IN (SELECT t2.i1, t2.i2 FROM t2 WHERE t2.i1 = 3);
|
||||
EXPLAIN EXTENDED
|
||||
SELECT * FROM t1 HAVING (7, 9) IN (SELECT t2.i1, t2.i2 FROM t2 WHERE t2.i1 = 3);
|
||||
|
||||
DROP TABLE t1,t2;
|
||||
|
||||
--echo #
|
||||
--echo # MDEV-19255: rowid range filter built for range condition
|
||||
--echo # that uses in expensive subquery
|
||||
--echo #
|
||||
|
||||
CREATE TABLE t1 (
|
||||
pk1 INT PRIMARY KEY, a1 INT, b1 VARCHAR(1), KEY(a1), KEY(b1)
|
||||
) ENGINE=MyISAM;
|
||||
INSERT INTO t1 VALUES
|
||||
(10,0,'z'),(11,3,'j'),(12,8,'f'),(13,8,'p'),(14,6,'w'),(15,0,'c'),(16,1,'j'),
|
||||
(17,1,'f'),(18,5,'v'),(19,3,'f'),(20,2,'q'),(21,8,'y'),(22,0,'a'),(23,9,'w'),
|
||||
(24,3,'e'),(25,1,'b'),(26,9,'r'),(27,2,'k'),(28,5,'c'),(29,3,'k'),(30,9,'b'),
|
||||
(31,8,'j'),(32,1,'t'),(33,8,'n'),(34,3,'z'),(35,0,'u'),(36,3,'a'),(37,3,'g'),
|
||||
(38,1,'f'),(39,6,'p'),(40,6,'m'),(41,6,'t'),(42,7,'i'),(43,4,'h'),(44,3,'d'),
|
||||
(45,2,'b'),(46,1,'o'),(47,2,'j'),(48,6,'s'),(49,5,'q'),(50,6,'l'),(51,9,'j'),
|
||||
(52,6,'y'),(53,0,'i'),(54,7,'x'),(55,2,'u'),(56,6,'t'),(57,4,'b'),(58,5,'m'),
|
||||
(59,4,'x'),(60,8,'x'),(61,6,'v'),(62,8,'m'),(63,4,'j'),(64,8,'z'),(65,2,'a'),
|
||||
(66,9,'i'),(67,4,'g'),(68,8,'h'),(69,1,'p'),(70,8,'a'),(71,0,'x'),(72,2,'s'),
|
||||
(73,6,'k'),(74,0,'m'),(75,6,'e'),(76,9,'y'),(77,7,'d'),(78,7,'w'),(79,6,'y'),
|
||||
(80,9,'s'),(81,9,'x'),(82,6,'l'),(83,9,'f'),(84,8,'x'),(85,1,'p'),(86,7,'y'),
|
||||
(87,6,'p'),(88,1,'g'),(89,3,'c'),(90,5,'h'),(91,3,'p'),(92,2,'b'),(93,1,NULL),
|
||||
(94,3,NULL),(95,2,'y'),(96,7,'s'),(97,7,'x'),(98,6,'i'),(99,9,'t'),(100,5,'j'),
|
||||
(101,0,'u'),(102,7,'r'),(103,2,'x'),(104,8,'e'),(105,8,'i'),(106,5,'q'),
|
||||
(107,8,'z'),(108,3,'k'),(109,65,NULL);
|
||||
|
||||
CREATE TABLE t2 (pk2 INT PRIMARY KEY, a2 INT, b2 VARCHAR(1)) ENGINE=MyISAM;
|
||||
INSERT INTO t2 VALUES (1,1,'i');
|
||||
INSERT INTO t2 SELECT * FROM t1;
|
||||
|
||||
INSERT INTO t1 SELECT pk1+200, a1, b1 FROM t1;
|
||||
INSERT INTO t1 SELECT pk1+400, a1, b1 FROM t1;
|
||||
|
||||
ANALYZE TABLE t1,t2 PERSISTENT FOR ALL;
|
||||
|
||||
let $q=
|
||||
SELECT * FROM t1 INNER JOIN t2 ON ( pk1+1 = pk2+2 AND a1 = a2 )
|
||||
WHERE b1 <= ( SELECT MAX(b2) FROM t2 WHERE pk2 <= 1 );
|
||||
|
||||
eval $q;
|
||||
eval EXPLAIN EXTENDED $q;
|
||||
set @@optimizer_where_cost=0.0356*4;
|
||||
eval EXPLAIN EXTENDED $q;
|
||||
eval EXPLAIN FORMAT=JSON $q;
|
||||
set @@optimizer_where_cost=default;
|
||||
|
||||
DROP TABLE t1,t2;
|
||||
|
||||
--echo #
|
||||
--echo # MDEV-21794: Optimizer flag rowid_filter leads to long query
|
||||
--echo #
|
||||
create table t10(a int);
|
||||
insert into t10 values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9);
|
||||
|
||||
create table t11(a int);
|
||||
insert into t11 select A.a + B.a* 10 + C.a * 100 from t10 A, t10 B, t10 C;
|
||||
|
||||
CREATE TABLE t1 (
|
||||
el_id int(10) unsigned NOT NULL ,
|
||||
el_index blob NOT NULL,
|
||||
el_index_60 varbinary(60) NOT NULL,
|
||||
filler blob,
|
||||
|
||||
PRIMARY KEY (el_id),
|
||||
KEY el_index (el_index(60)),
|
||||
KEY el_index_60 (el_index_60,el_id)
|
||||
);
|
||||
|
||||
insert into t1
|
||||
select
|
||||
A.a+1000*B.a,
|
||||
A.a+1000*B.a + 10000,
|
||||
A.a+1000*B.a + 10000,
|
||||
'filler-data-filler-data'
|
||||
from
|
||||
t11 A, t10 B;
|
||||
analyze table t1 persistent for all;
|
||||
|
||||
--echo # This must not use rowid_filter with key=el_index|el_index_60:
|
||||
explain
|
||||
select * from t1
|
||||
where el_index like '10%' and (el_index_60 like '10%' or el_index_60 like '20%');
|
||||
|
||||
drop table t10, t11, t1;
|
||||
|
||||
|
||||
--echo #
|
||||
--echo # MDEV-22160: SIGSEGV in st_join_table::save_explain_data on SELECT
|
||||
--echo #
|
||||
|
||||
set @save_optimizer_switch= @@optimizer_switch;
|
||||
SET @@optimizer_switch="index_merge_sort_union=OFF";
|
||||
CREATE TABLE t1 (a INT, b INT, INDEX(a), INDEX(b));
|
||||
INSERT INTO t1 VALUES (0,0),(0,0),(1,0),(-1,1), (-2,1), (-2,3), (-3,4), (-2,4),(3,3),(3,4),(3,5),(8,8),(8,9),(1,0),(2,0),(0,0),(0,0);
|
||||
explain
|
||||
SELECT * FROM t1 WHERE a > 0 AND b=0;
|
||||
SELECT * FROM t1 WHERE a > 0 AND b=0;
|
||||
drop table t1;
|
||||
SET @@optimizer_switch=@save_optimizer_switch;
|
||||
|
||||
--echo #
|
||||
--echo # MDEV-28846: Poor performance when rowid filter contains no elements
|
||||
--echo #
|
||||
|
||||
--source include/have_sequence.inc
|
||||
|
||||
create table t1 (
|
||||
pk int primary key auto_increment,
|
||||
nm varchar(32),
|
||||
fl1 tinyint default 0,
|
||||
fl2 tinyint default 0,
|
||||
index idx1(nm, fl1),
|
||||
index idx2(fl2)
|
||||
) engine=myisam;
|
||||
|
||||
create table name (
|
||||
pk int primary key auto_increment,
|
||||
nm bigint
|
||||
) engine=myisam;
|
||||
|
||||
create table flag2 (
|
||||
pk int primary key auto_increment,
|
||||
fl2 tinyint
|
||||
) engine=myisam;
|
||||
|
||||
insert into name(nm) select seq from seq_1_to_1000 order by rand(17);
|
||||
insert into flag2(fl2) select seq mod 2 from seq_1_to_1000 order by rand(19);
|
||||
|
||||
insert into t1(nm,fl2)
|
||||
select nm, fl2 from name, flag2 where name.pk = flag2.pk;
|
||||
|
||||
analyze table t1 persistent for all;
|
||||
|
||||
let $a=
|
||||
`select concat((select nm from t1 where fl2=0 order by RAND(13) limit 1),'%')`;
|
||||
eval select '$a' as a;
|
||||
|
||||
set optimizer_switch='rowid_filter=on';
|
||||
eval
|
||||
explain
|
||||
select * from t1 where nm like '$a' AND fl2 = 0;
|
||||
--source include/analyze-format.inc
|
||||
eval
|
||||
analyze format=json
|
||||
select * from t1 where nm like '$a' AND fl2 = 0;
|
||||
eval
|
||||
select * from t1 where nm like '$a' AND fl2 = 0;
|
||||
|
||||
truncate table name;
|
||||
truncate table flag2;
|
||||
truncate table t1;
|
||||
|
||||
insert into name(nm) select seq from seq_1_to_1000 order by rand(17);
|
||||
insert into flag2(fl2) select seq mod 2 from seq_1_to_1000 order by rand(19);
|
||||
|
||||
insert into t1(nm,fl2)
|
||||
select nm, fl2 from name, flag2 where name.pk = flag2.pk;
|
||||
|
||||
analyze table t1 persistent for all;
|
||||
|
||||
set optimizer_switch='rowid_filter=off';
|
||||
eval
|
||||
explain
|
||||
select * from t1 where nm like '$a' AND fl2 = 0;
|
||||
--source include/analyze-format.inc
|
||||
eval
|
||||
analyze format=json
|
||||
select * from t1 where nm like '$a' AND fl2 = 0;
|
||||
eval
|
||||
select * from t1 where nm like '$a' AND fl2 = 0;
|
||||
|
||||
truncate table name;
|
||||
truncate table flag2;
|
||||
truncate table t1;
|
||||
|
||||
insert into name(nm) select seq from seq_1_to_1000 order by rand(17);
|
||||
insert into flag2(fl2) select seq mod 10 from seq_1_to_1000 order by rand(19);
|
||||
|
||||
insert into t1(nm,fl2)
|
||||
select nm, fl2 from name, flag2 where name.pk = flag2.pk;
|
||||
|
||||
analyze table t1 persistent for all;
|
||||
|
||||
let $a=
|
||||
`select concat((select nm from t1 where fl2=0 order by RAND(13) limit 1),'%')`;
|
||||
eval select '$a' as a;
|
||||
|
||||
set optimizer_switch='rowid_filter=on';
|
||||
eval
|
||||
explain
|
||||
select * from t1 where nm like '$a' AND fl2 = 0;
|
||||
eval
|
||||
select * from t1 where nm like '$a' AND fl2 = 0;
|
||||
|
||||
truncate table name;
|
||||
truncate table flag2;
|
||||
truncate table t1;
|
||||
|
||||
insert into name(nm) select seq from seq_1_to_10000 order by rand(17);
|
||||
insert into flag2(fl2) select seq mod 100 from seq_1_to_10000 order by rand(19);
|
||||
|
||||
insert into t1(nm,fl2)
|
||||
select nm, fl2 from name, flag2 where name.pk = flag2.pk;
|
||||
|
||||
analyze table t1 persistent for all;
|
||||
|
||||
let $a=
|
||||
`select concat(left((select nm from t1 where fl2=0 order by RAND(13) limit 1),2),'%')`;
|
||||
eval select '$a' as a;
|
||||
|
||||
set optimizer_switch='rowid_filter=on';
|
||||
eval
|
||||
explain
|
||||
select * from t1 where nm like '$a' AND fl2 = 0;
|
||||
--source include/analyze-format.inc
|
||||
eval
|
||||
analyze format=json
|
||||
select * from t1 where nm like '$a' AND fl2 = 0;
|
||||
eval
|
||||
select * from t1 where nm like '$a' AND fl2 = 0;
|
||||
|
||||
drop table name, flag2;
|
||||
drop table t1;
|
||||
|
||||
# This test shows that if the container is empty there are no lookups into it
|
||||
|
||||
create table t1 (
|
||||
pk int primary key auto_increment,
|
||||
nm char(255),
|
||||
fl1 tinyint default 0,
|
||||
fl2 int default 0,
|
||||
index idx1(nm, fl1),
|
||||
index idx2(fl2)
|
||||
) engine=myisam;
|
||||
|
||||
create table name (
|
||||
pk int primary key auto_increment,
|
||||
nm bigint
|
||||
) engine=myisam;
|
||||
|
||||
create table flag2 (
|
||||
pk int primary key auto_increment,
|
||||
fl2 int
|
||||
) engine=myisam;
|
||||
|
||||
insert into name(nm) select seq from seq_1_to_10000 order by rand(17);
|
||||
insert into flag2(fl2) select seq mod 10 from seq_1_to_10000 order by rand(19);
|
||||
|
||||
insert into t1(nm,fl2)
|
||||
select nm, fl2 from name, flag2 where name.pk = flag2.pk;
|
||||
|
||||
analyze table t1 persistent for all;
|
||||
|
||||
let $q=
|
||||
select * from t1
|
||||
where
|
||||
(
|
||||
nm like '3400%' or nm like '3402%' or nm like '3403%' or
|
||||
nm like '3404%' or nm like '3405%' or nm like '3406%' or nm like '3407%' or
|
||||
nm like '3409%' or
|
||||
nm like '3411%' or nm like '3412%' or nm like '3413%' or
|
||||
nm like '3414%' or nm like '3415%' or nm like '3416%' or nm like '3417%' or
|
||||
nm like '3418%' or nm like '3419%' or
|
||||
nm like '3421%' or nm like '3422%' or nm like '3423%' or
|
||||
nm like '3424%' or nm like '3425%' or nm like '3426%' or nm like '3427%' or
|
||||
nm like '3428%' or nm like '3429%' or
|
||||
nm like '3430%' or nm like '3431%' or nm like '3432%' or nm like '3433%' or
|
||||
nm like '3434%' or nm like '3435%' or nm like '3436%' or nm like '3437%' or
|
||||
nm like '3439%' or
|
||||
nm like '3440%' or nm like '3441%' or nm like '3442%' or nm like '3443%' or
|
||||
nm like '3444%' or nm like '3445%' or nm like '3446%' or nm like '3447%' or
|
||||
nm like '3448%'
|
||||
) and fl2 = 0;
|
||||
|
||||
eval $q;
|
||||
--source include/analyze-format.inc
|
||||
eval analyze format=json $q;
|
||||
|
||||
create table t0 select * from t1 where nm like '34%';
|
||||
delete from t1 using t1,t0 where t1.nm=t0.nm;
|
||||
--source include/analyze-format.inc
|
||||
eval analyze format=json $q;
|
||||
|
||||
drop table t0;
|
||||
|
||||
set optimizer_switch='rowid_filter=default';
|
||||
|
||||
drop table name, flag2;
|
||||
drop table t1;
|
||||
|
||||
set @@use_stat_tables=@save_use_stat_tables;
|
||||
|
||||
--echo #
|
||||
--echo # MDEV-21633
|
||||
--echo # Assertion `tmp >= 0' failed in best_access_path with rowid_filter=ON
|
||||
--echo #
|
||||
|
||||
set @save_optimizer_switch= @@optimizer_switch;
|
||||
SET optimizer_switch='rowid_filter=on';
|
||||
|
||||
CREATE TABLE t1 (
|
||||
pk INT AUTO_INCREMENT,
|
||||
a INT,
|
||||
b VARCHAR(8),
|
||||
KEY(a),
|
||||
PRIMARY KEY(pk),
|
||||
KEY (a,pk)
|
||||
) ENGINE=MyISAM;
|
||||
|
||||
INSERT INTO t1 (a,b) VALUES
|
||||
(NULL,'d'),(9,'b'),(2,'x'),(5,'k'),(NULL,'d'),(3,'s'),(5,'k'),(1,'r'),
|
||||
(8,'l'),(3,'z'),(1,'c'),(1,'q'),(NULL,'x'),(NULL,'p'),(NULL,'z'),(7,'a'),
|
||||
(0,'i'),(3,'s'),(NULL,'h'),(4,'p'),(1,'i'),(4,'f'),(1,'c'),(NULL,'a'),
|
||||
(NULL,'x'),(1,'b'),(NULL,'n'),(NULL,'h'),(5,'i'),(6,'e'),(NULL,'i'),
|
||||
(7,'e'),(1,'r'),(NULL,'z'),(1,'i'),(14,'c'),(6,'u'),(3,'b'),(4,'z'),
|
||||
(2,'c'),(70,'d'),(NULL,'p'),(21,'j'),(6,'e'),(5,'c'),(13,'i'),(42,'d'),
|
||||
(80,'s'),(14,'t'),(9,'a'),(0,'2'),(0,NULL),(0,NULL),(0,NULL),(0,''),
|
||||
(0,''),(0,'1'),(0,''),(0,''),(0,''),(0,''),(0,NULL),(0,''),(0,''),(0,''),
|
||||
(0,NULL),(0,''),(0,''),(0,''),(0,''),(0,''),(0,''),(0,NULL),(0,NULL),
|
||||
(0,NULL),(0,''),(0,''),(0,''),(0,''),(0,NULL),(0,''),(0,NULL),(0,NULL),
|
||||
(0,''),(0,''),(0,''),(0,NULL),(0,''),(0,NULL),(0,''),(0,''),(0,''),(0,''),
|
||||
(0,''),(0,''),(0,''),(0,NULL),(0,''),(0,NULL),(0,'');
|
||||
|
||||
CREATE TABLE t2 (c INT) ENGINE=MyISAM;
|
||||
INSERT INTO t2 VALUES (1),(2),(3),(4),(5),(6);
|
||||
|
||||
SELECT * FROM t1 JOIN t2 WHERE a = c AND pk BETWEEN 4 AND 7 AND a BETWEEN 2 AND 12 AND b != 'foo';
|
||||
|
||||
explain SELECT * FROM t1 JOIN t2 WHERE a = c AND pk BETWEEN 4 AND 7 AND a BETWEEN 2 AND 12 AND b != 'foo';
|
||||
|
||||
SET optimizer_switch='rowid_filter=off';
|
||||
|
||||
SELECT * FROM t1 JOIN t2 WHERE a = c AND pk BETWEEN 4 AND 7 AND a BETWEEN 2 AND 12 AND b != 'foo';
|
||||
|
||||
SET @@optimizer_switch=@save_optimizer_switch;
|
||||
|
||||
# Cleanup
|
||||
DROP TABLE t1, t2;
|
||||
|
2217
mysql-test/main/rowid_filter_aria.result
Normal file
2217
mysql-test/main/rowid_filter_aria.result
Normal file
File diff suppressed because it is too large
Load Diff
9
mysql-test/main/rowid_filter_aria.test
Normal file
9
mysql-test/main/rowid_filter_aria.test
Normal file
@ -0,0 +1,9 @@
|
||||
#
|
||||
# Test rowid filters with Aria
|
||||
#
|
||||
|
||||
SET SESSION DEFAULT_STORAGE_ENGINE='Aria';
|
||||
|
||||
#set global aria.optimizer_rowid_compare_cost=0.00001;
|
||||
#set global aria.optimizer_rowid_copy_cost=0.00001;
|
||||
--source rowid_filter.test
|
@ -2141,698 +2141,6 @@ ALTER TABLE orders DROP COLUMN o_totaldiscount;
|
||||
DROP VIEW v1;
|
||||
DROP DATABASE dbt3_s001;
|
||||
use test;
|
||||
#
|
||||
# MDEV-18816: potential range filter for one join table with
|
||||
# impossible WHERE for another
|
||||
#
|
||||
create table t1 (
|
||||
pk int not null primary key, c2 varchar(10) , i1 int,key (c2)
|
||||
) engine=myisam;
|
||||
insert into t1 values (1,'a',-5),(2,'a',null);
|
||||
create table t2 (
|
||||
pk int, i1 int, c1 varchar(30) , key c1 (c1(30)), key i1 (i1)
|
||||
) engine=myisam;
|
||||
insert into t2 values
|
||||
(1,-5,'a'),(2,null,'a'),(3,null,'a'),(4,null,'a'),(5,5,'a'),(6,null,'a'),
|
||||
(7,4,'a'),(8,55,'a'),(9,null,'a'),(10,null,'a'),(11,null,'a'),(12,-5,'a'),
|
||||
(13,-5,'a'),(14,null,'a'),(15,null,'a'),(16,-5,'a'),(17,-5,'a');
|
||||
select 1
|
||||
from t1
|
||||
left join
|
||||
t2 join t1 as t1_a on t2.i1 = t1_a.pk
|
||||
on t1.c2 = t2.c1
|
||||
where t1_a.pk is null and t1_a.i1 != 3;
|
||||
1
|
||||
explain extended select 1
|
||||
from t1
|
||||
left join
|
||||
t2 join t1 as t1_a on t2.i1 = t1_a.pk
|
||||
on t1.c2 = t2.c1
|
||||
where t1_a.pk is null and t1_a.i1 != 3;
|
||||
id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||
1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
|
||||
Warnings:
|
||||
Note 1003 select 1 AS `1` from `test`.`t1` join `test`.`t2` join `test`.`t1` `t1_a` where 0
|
||||
drop table t1,t2;
|
||||
#
|
||||
# MDEV-18640: TABLE::prune_range_rowid_filters: Conditional jump or
|
||||
# move depends on uninitialized value
|
||||
#
|
||||
CREATE TABLE t1 (
|
||||
pk INT, i INT, PRIMARY KEY (pk), KEY (pk,i)
|
||||
) ENGINE=MyISAM;
|
||||
INSERT INTO t1 VALUES (1,10), (7,70), (2,20);
|
||||
SELECT * FROM t1 WHERE pk < 5;
|
||||
pk i
|
||||
1 10
|
||||
2 20
|
||||
DROP TABLE t1;
|
||||
#
|
||||
# MDEV-18956: Possible rowid filter for subquery for which
|
||||
# in_to_exists strategy has been chosen
|
||||
#
|
||||
CREATE TABLE t1 (pk int) engine=myisam ;
|
||||
INSERT INTO t1 VALUES (1),(2);
|
||||
CREATE TABLE t2 (
|
||||
pk int auto_increment PRIMARY KEY,
|
||||
i1 int, i2 int, c2 varchar(1),
|
||||
KEY (i1), KEY (i2)
|
||||
) engine=myisam;
|
||||
INSERT INTO t2 VALUES
|
||||
(1,8,6,'t'),(2,5,7,'i'),(3,4,4,'h'),(4,207,38,'d'),(5,183,206,'b'),
|
||||
(6,7,null,'o'),(7,1,2,'j'),(8,17,36,'s'),(9,4,5,'q'),(10,0,6,'l'),
|
||||
(11,1,9,'j'),(12,5,6,'y'),(13,null,0,'i'),(14,7,7,'x'),(15,5,2,'u');
|
||||
SELECT * FROM t1 HAVING (7, 9) IN (SELECT t2.i1, t2.i2 FROM t2 WHERE t2.i1 = 3);
|
||||
pk
|
||||
EXPLAIN EXTENDED
|
||||
SELECT * FROM t1 HAVING (7, 9) IN (SELECT t2.i1, t2.i2 FROM t2 WHERE t2.i1 = 3);
|
||||
id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||
1 PRIMARY NULL NULL NULL NULL NULL NULL NULL NULL Impossible HAVING
|
||||
2 SUBQUERY NULL NULL NULL NULL NULL NULL NULL NULL no matching row in const table
|
||||
Warnings:
|
||||
Note 1003 /* select#1 */ select `test`.`t1`.`pk` AS `pk` from `test`.`t1` having 0
|
||||
DROP TABLE t1,t2;
|
||||
#
|
||||
# MDEV-19255: rowid range filter built for range condition
|
||||
# that uses in expensive subquery
|
||||
#
|
||||
CREATE TABLE t1 (
|
||||
pk1 INT PRIMARY KEY, a1 INT, b1 VARCHAR(1), KEY(a1), KEY(b1)
|
||||
) ENGINE=MyISAM;
|
||||
INSERT INTO t1 VALUES
|
||||
(10,0,'z'),(11,3,'j'),(12,8,'f'),(13,8,'p'),(14,6,'w'),(15,0,'c'),(16,1,'j'),
|
||||
(17,1,'f'),(18,5,'v'),(19,3,'f'),(20,2,'q'),(21,8,'y'),(22,0,'a'),(23,9,'w'),
|
||||
(24,3,'e'),(25,1,'b'),(26,9,'r'),(27,2,'k'),(28,5,'c'),(29,3,'k'),(30,9,'b'),
|
||||
(31,8,'j'),(32,1,'t'),(33,8,'n'),(34,3,'z'),(35,0,'u'),(36,3,'a'),(37,3,'g'),
|
||||
(38,1,'f'),(39,6,'p'),(40,6,'m'),(41,6,'t'),(42,7,'i'),(43,4,'h'),(44,3,'d'),
|
||||
(45,2,'b'),(46,1,'o'),(47,2,'j'),(48,6,'s'),(49,5,'q'),(50,6,'l'),(51,9,'j'),
|
||||
(52,6,'y'),(53,0,'i'),(54,7,'x'),(55,2,'u'),(56,6,'t'),(57,4,'b'),(58,5,'m'),
|
||||
(59,4,'x'),(60,8,'x'),(61,6,'v'),(62,8,'m'),(63,4,'j'),(64,8,'z'),(65,2,'a'),
|
||||
(66,9,'i'),(67,4,'g'),(68,8,'h'),(69,1,'p'),(70,8,'a'),(71,0,'x'),(72,2,'s'),
|
||||
(73,6,'k'),(74,0,'m'),(75,6,'e'),(76,9,'y'),(77,7,'d'),(78,7,'w'),(79,6,'y'),
|
||||
(80,9,'s'),(81,9,'x'),(82,6,'l'),(83,9,'f'),(84,8,'x'),(85,1,'p'),(86,7,'y'),
|
||||
(87,6,'p'),(88,1,'g'),(89,3,'c'),(90,5,'h'),(91,3,'p'),(92,2,'b'),(93,1,NULL),
|
||||
(94,3,NULL),(95,2,'y'),(96,7,'s'),(97,7,'x'),(98,6,'i'),(99,9,'t'),(100,5,'j'),
|
||||
(101,0,'u'),(102,7,'r'),(103,2,'x'),(104,8,'e'),(105,8,'i'),(106,5,'q'),
|
||||
(107,8,'z'),(108,3,'k'),(109,65,NULL);
|
||||
CREATE TABLE t2 (pk2 INT PRIMARY KEY, a2 INT, b2 VARCHAR(1)) ENGINE=MyISAM;
|
||||
INSERT INTO t2 VALUES (1,1,'i');
|
||||
INSERT INTO t2 SELECT * FROM t1;
|
||||
INSERT INTO t1 SELECT pk1+200, a1, b1 FROM t1;
|
||||
INSERT INTO t1 SELECT pk1+400, a1, b1 FROM t1;
|
||||
ANALYZE TABLE t1,t2 PERSISTENT FOR ALL;
|
||||
Table Op Msg_type Msg_text
|
||||
test.t1 analyze status Engine-independent statistics collected
|
||||
test.t1 analyze status OK
|
||||
test.t2 analyze status Engine-independent statistics collected
|
||||
test.t2 analyze status OK
|
||||
SELECT * FROM t1 INNER JOIN t2 ON ( pk1+1 = pk2+2 AND a1 = a2 )
|
||||
WHERE b1 <= ( SELECT MAX(b2) FROM t2 WHERE pk2 <= 1 );
|
||||
pk1 a1 b1 pk2 a2 b2
|
||||
17 1 f 16 1 j
|
||||
37 3 g 36 3 a
|
||||
105 8 i 104 8 e
|
||||
EXPLAIN EXTENDED SELECT * FROM t1 INNER JOIN t2 ON ( pk1+1 = pk2+2 AND a1 = a2 )
|
||||
WHERE b1 <= ( SELECT MAX(b2) FROM t2 WHERE pk2 <= 1 );
|
||||
id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||
1 PRIMARY t2 ALL NULL NULL NULL NULL 101 100.00
|
||||
1 PRIMARY t1 ALL a1,b1 NULL NULL NULL 400 2.61 Using where; Using join buffer (flat, BNL join)
|
||||
2 SUBQUERY t2 range PRIMARY PRIMARY 4 NULL 1 100.00 Using index condition
|
||||
Warnings:
|
||||
Note 1003 /* select#1 */ select `test`.`t1`.`pk1` AS `pk1`,`test`.`t1`.`a1` AS `a1`,`test`.`t1`.`b1` AS `b1`,`test`.`t2`.`pk2` AS `pk2`,`test`.`t2`.`a2` AS `a2`,`test`.`t2`.`b2` AS `b2` from `test`.`t1` join `test`.`t2` where `test`.`t1`.`a1` = `test`.`t2`.`a2` and `test`.`t1`.`b1` <= (/* select#2 */ select max(`test`.`t2`.`b2`) from `test`.`t2` where `test`.`t2`.`pk2` <= 1) and `test`.`t1`.`pk1` + 1 = `test`.`t2`.`pk2` + 2
|
||||
set @@optimizer_where_cost=0.0356*4;
|
||||
EXPLAIN EXTENDED SELECT * FROM t1 INNER JOIN t2 ON ( pk1+1 = pk2+2 AND a1 = a2 )
|
||||
WHERE b1 <= ( SELECT MAX(b2) FROM t2 WHERE pk2 <= 1 );
|
||||
id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||
1 PRIMARY t2 ALL NULL NULL NULL NULL 101 100.00 Using where
|
||||
1 PRIMARY t1 ref|filter a1,b1 a1|b1 5|4 test.t2.a2 36 (29%) 28.75 Using where; Using rowid filter
|
||||
2 SUBQUERY t2 range PRIMARY PRIMARY 4 NULL 1 100.00 Using index condition
|
||||
Warnings:
|
||||
Note 1003 /* select#1 */ select `test`.`t1`.`pk1` AS `pk1`,`test`.`t1`.`a1` AS `a1`,`test`.`t1`.`b1` AS `b1`,`test`.`t2`.`pk2` AS `pk2`,`test`.`t2`.`a2` AS `a2`,`test`.`t2`.`b2` AS `b2` from `test`.`t1` join `test`.`t2` where `test`.`t1`.`a1` = `test`.`t2`.`a2` and `test`.`t1`.`b1` <= (/* select#2 */ select max(`test`.`t2`.`b2`) from `test`.`t2` where `test`.`t2`.`pk2` <= 1) and `test`.`t1`.`pk1` + 1 = `test`.`t2`.`pk2` + 2
|
||||
EXPLAIN FORMAT=JSON SELECT * FROM t1 INNER JOIN t2 ON ( pk1+1 = pk2+2 AND a1 = a2 )
|
||||
WHERE b1 <= ( SELECT MAX(b2) FROM t2 WHERE pk2 <= 1 );
|
||||
EXPLAIN
|
||||
{
|
||||
"query_block": {
|
||||
"select_id": 1,
|
||||
"nested_loop": [
|
||||
{
|
||||
"table": {
|
||||
"table_name": "t2",
|
||||
"access_type": "ALL",
|
||||
"rows": 101,
|
||||
"filtered": 100,
|
||||
"attached_condition": "t2.a2 is not null"
|
||||
}
|
||||
},
|
||||
{
|
||||
"table": {
|
||||
"table_name": "t1",
|
||||
"access_type": "ref",
|
||||
"possible_keys": ["a1", "b1"],
|
||||
"key": "a1",
|
||||
"key_length": "5",
|
||||
"used_key_parts": ["a1"],
|
||||
"ref": ["test.t2.a2"],
|
||||
"rowid_filter": {
|
||||
"range": {
|
||||
"key": "b1",
|
||||
"used_key_parts": ["b1"]
|
||||
},
|
||||
"rows": 115,
|
||||
"selectivity_pct": 28.75
|
||||
},
|
||||
"rows": 36,
|
||||
"filtered": 28.75,
|
||||
"attached_condition": "t1.b1 <= (subquery#2) and t1.pk1 + 1 = t2.pk2 + 2"
|
||||
}
|
||||
}
|
||||
],
|
||||
"subqueries": [
|
||||
{
|
||||
"query_block": {
|
||||
"select_id": 2,
|
||||
"nested_loop": [
|
||||
{
|
||||
"table": {
|
||||
"table_name": "t2",
|
||||
"access_type": "range",
|
||||
"possible_keys": ["PRIMARY"],
|
||||
"key": "PRIMARY",
|
||||
"key_length": "4",
|
||||
"used_key_parts": ["pk2"],
|
||||
"rows": 1,
|
||||
"filtered": 100,
|
||||
"index_condition": "t2.pk2 <= 1"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
set @@optimizer_where_cost=default;
|
||||
DROP TABLE t1,t2;
|
||||
#
|
||||
# MDEV-21794: Optimizer flag rowid_filter leads to long query
|
||||
#
|
||||
create table t10(a int);
|
||||
insert into t10 values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9);
|
||||
create table t11(a int);
|
||||
insert into t11 select A.a + B.a* 10 + C.a * 100 from t10 A, t10 B, t10 C;
|
||||
CREATE TABLE t1 (
|
||||
el_id int(10) unsigned NOT NULL ,
|
||||
el_index blob NOT NULL,
|
||||
el_index_60 varbinary(60) NOT NULL,
|
||||
filler blob,
|
||||
PRIMARY KEY (el_id),
|
||||
KEY el_index (el_index(60)),
|
||||
KEY el_index_60 (el_index_60,el_id)
|
||||
);
|
||||
insert into t1
|
||||
select
|
||||
A.a+1000*B.a,
|
||||
A.a+1000*B.a + 10000,
|
||||
A.a+1000*B.a + 10000,
|
||||
'filler-data-filler-data'
|
||||
from
|
||||
t11 A, t10 B;
|
||||
analyze table t1 persistent for all;
|
||||
Table Op Msg_type Msg_text
|
||||
test.t1 analyze status Engine-independent statistics collected
|
||||
test.t1 analyze Warning Engine-independent statistics are not collected for column 'el_index'
|
||||
test.t1 analyze Warning Engine-independent statistics are not collected for column 'filler'
|
||||
test.t1 analyze status OK
|
||||
# This must not use rowid_filter with key=el_index|el_index_60:
|
||||
explain
|
||||
select * from t1
|
||||
where el_index like '10%' and (el_index_60 like '10%' or el_index_60 like '20%');
|
||||
id select_type table type possible_keys key key_len ref rows Extra
|
||||
1 SIMPLE t1 range el_index,el_index_60 el_index 62 NULL 1000 Using where
|
||||
drop table t10, t11, t1;
|
||||
#
|
||||
# MDEV-22160: SIGSEGV in st_join_table::save_explain_data on SELECT
|
||||
#
|
||||
set @save_optimizer_switch= @@optimizer_switch;
|
||||
SET @@optimizer_switch="index_merge_sort_union=OFF";
|
||||
CREATE TABLE t1 (a INT, b INT, INDEX(a), INDEX(b));
|
||||
INSERT INTO t1 VALUES (0,0),(0,0),(1,0),(-1,1), (-2,1), (-2,3), (-3,4), (-2,4),(3,3),(3,4),(3,5),(8,8),(8,9),(1,0),(2,0),(0,0),(0,0);
|
||||
explain
|
||||
SELECT * FROM t1 WHERE a > 0 AND b=0;
|
||||
id select_type table type possible_keys key key_len ref rows Extra
|
||||
1 SIMPLE t1 ref|filter a,b b|a 5|5 const 7 (47%) Using where; Using rowid filter
|
||||
SELECT * FROM t1 WHERE a > 0 AND b=0;
|
||||
a b
|
||||
1 0
|
||||
1 0
|
||||
2 0
|
||||
drop table t1;
|
||||
SET @@optimizer_switch=@save_optimizer_switch;
|
||||
#
|
||||
# MDEV-28846: Poor performance when rowid filter contains no elements
|
||||
#
|
||||
create table t1 (
|
||||
pk int primary key auto_increment,
|
||||
nm varchar(32),
|
||||
fl1 tinyint default 0,
|
||||
fl2 tinyint default 0,
|
||||
index idx1(nm, fl1),
|
||||
index idx2(fl2)
|
||||
) engine=myisam;
|
||||
create table name (
|
||||
pk int primary key auto_increment,
|
||||
nm bigint
|
||||
) engine=myisam;
|
||||
create table flag2 (
|
||||
pk int primary key auto_increment,
|
||||
fl2 tinyint
|
||||
) engine=myisam;
|
||||
insert into name(nm) select seq from seq_1_to_1000 order by rand(17);
|
||||
insert into flag2(fl2) select seq mod 2 from seq_1_to_1000 order by rand(19);
|
||||
insert into t1(nm,fl2)
|
||||
select nm, fl2 from name, flag2 where name.pk = flag2.pk;
|
||||
analyze table t1 persistent for all;
|
||||
Table Op Msg_type Msg_text
|
||||
test.t1 analyze status Engine-independent statistics collected
|
||||
test.t1 analyze status Table is already up to date
|
||||
select '500%' as a;
|
||||
a
|
||||
500%
|
||||
set optimizer_switch='rowid_filter=on';
|
||||
explain
|
||||
select * from t1 where nm like '500%' AND fl2 = 0;
|
||||
id select_type table type possible_keys key key_len ref rows Extra
|
||||
1 SIMPLE t1 range idx1,idx2 idx1 35 NULL 1 Using index condition; Using where
|
||||
analyze format=json
|
||||
select * from t1 where nm like '500%' AND fl2 = 0;
|
||||
ANALYZE
|
||||
{
|
||||
"query_optimization": {
|
||||
"r_total_time_ms": "REPLACED"
|
||||
},
|
||||
"query_block": {
|
||||
"select_id": 1,
|
||||
"r_loops": 1,
|
||||
"r_total_time_ms": "REPLACED",
|
||||
"nested_loop": [
|
||||
{
|
||||
"table": {
|
||||
"table_name": "t1",
|
||||
"access_type": "range",
|
||||
"possible_keys": ["idx1", "idx2"],
|
||||
"key": "idx1",
|
||||
"key_length": "35",
|
||||
"used_key_parts": ["nm"],
|
||||
"r_loops": 1,
|
||||
"rows": 1,
|
||||
"r_rows": 1,
|
||||
"r_table_time_ms": "REPLACED",
|
||||
"r_other_time_ms": "REPLACED",
|
||||
"filtered": 49.20000076,
|
||||
"r_filtered": 100,
|
||||
"index_condition": "t1.nm like '500%'",
|
||||
"attached_condition": "t1.fl2 = 0"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
select * from t1 where nm like '500%' AND fl2 = 0;
|
||||
pk nm fl1 fl2
|
||||
517 500 0 0
|
||||
truncate table name;
|
||||
truncate table flag2;
|
||||
truncate table t1;
|
||||
insert into name(nm) select seq from seq_1_to_1000 order by rand(17);
|
||||
insert into flag2(fl2) select seq mod 2 from seq_1_to_1000 order by rand(19);
|
||||
insert into t1(nm,fl2)
|
||||
select nm, fl2 from name, flag2 where name.pk = flag2.pk;
|
||||
analyze table t1 persistent for all;
|
||||
Table Op Msg_type Msg_text
|
||||
test.t1 analyze status Engine-independent statistics collected
|
||||
test.t1 analyze status Table is already up to date
|
||||
set optimizer_switch='rowid_filter=off';
|
||||
explain
|
||||
select * from t1 where nm like '500%' AND fl2 = 0;
|
||||
id select_type table type possible_keys key key_len ref rows Extra
|
||||
1 SIMPLE t1 range idx1,idx2 idx1 35 NULL 1 Using index condition; Using where
|
||||
analyze format=json
|
||||
select * from t1 where nm like '500%' AND fl2 = 0;
|
||||
ANALYZE
|
||||
{
|
||||
"query_optimization": {
|
||||
"r_total_time_ms": "REPLACED"
|
||||
},
|
||||
"query_block": {
|
||||
"select_id": 1,
|
||||
"r_loops": 1,
|
||||
"r_total_time_ms": "REPLACED",
|
||||
"nested_loop": [
|
||||
{
|
||||
"table": {
|
||||
"table_name": "t1",
|
||||
"access_type": "range",
|
||||
"possible_keys": ["idx1", "idx2"],
|
||||
"key": "idx1",
|
||||
"key_length": "35",
|
||||
"used_key_parts": ["nm"],
|
||||
"r_loops": 1,
|
||||
"rows": 1,
|
||||
"r_rows": 1,
|
||||
"r_table_time_ms": "REPLACED",
|
||||
"r_other_time_ms": "REPLACED",
|
||||
"filtered": 49.20000076,
|
||||
"r_filtered": 100,
|
||||
"index_condition": "t1.nm like '500%'",
|
||||
"attached_condition": "t1.fl2 = 0"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
select * from t1 where nm like '500%' AND fl2 = 0;
|
||||
pk nm fl1 fl2
|
||||
517 500 0 0
|
||||
truncate table name;
|
||||
truncate table flag2;
|
||||
truncate table t1;
|
||||
insert into name(nm) select seq from seq_1_to_1000 order by rand(17);
|
||||
insert into flag2(fl2) select seq mod 10 from seq_1_to_1000 order by rand(19);
|
||||
insert into t1(nm,fl2)
|
||||
select nm, fl2 from name, flag2 where name.pk = flag2.pk;
|
||||
analyze table t1 persistent for all;
|
||||
Table Op Msg_type Msg_text
|
||||
test.t1 analyze status Engine-independent statistics collected
|
||||
test.t1 analyze status Table is already up to date
|
||||
select '607%' as a;
|
||||
a
|
||||
607%
|
||||
set optimizer_switch='rowid_filter=on';
|
||||
explain
|
||||
select * from t1 where nm like '607%' AND fl2 = 0;
|
||||
id select_type table type possible_keys key key_len ref rows Extra
|
||||
1 SIMPLE t1 range idx1,idx2 idx1 35 NULL 1 Using index condition; Using where
|
||||
select * from t1 where nm like '607%' AND fl2 = 0;
|
||||
pk nm fl1 fl2
|
||||
721 607 0 0
|
||||
truncate table name;
|
||||
truncate table flag2;
|
||||
truncate table t1;
|
||||
insert into name(nm) select seq from seq_1_to_10000 order by rand(17);
|
||||
insert into flag2(fl2) select seq mod 100 from seq_1_to_10000 order by rand(19);
|
||||
insert into t1(nm,fl2)
|
||||
select nm, fl2 from name, flag2 where name.pk = flag2.pk;
|
||||
analyze table t1 persistent for all;
|
||||
Table Op Msg_type Msg_text
|
||||
test.t1 analyze status Engine-independent statistics collected
|
||||
test.t1 analyze status Table is already up to date
|
||||
select '75%' as a;
|
||||
a
|
||||
75%
|
||||
set optimizer_switch='rowid_filter=on';
|
||||
explain
|
||||
select * from t1 where nm like '75%' AND fl2 = 0;
|
||||
id select_type table type possible_keys key key_len ref rows Extra
|
||||
1 SIMPLE t1 ref|filter idx1,idx2 idx2|idx1 2|35 const 55 (1%) Using where; Using rowid filter
|
||||
analyze format=json
|
||||
select * from t1 where nm like '75%' AND fl2 = 0;
|
||||
ANALYZE
|
||||
{
|
||||
"query_optimization": {
|
||||
"r_total_time_ms": "REPLACED"
|
||||
},
|
||||
"query_block": {
|
||||
"select_id": 1,
|
||||
"r_loops": 1,
|
||||
"r_total_time_ms": "REPLACED",
|
||||
"nested_loop": [
|
||||
{
|
||||
"table": {
|
||||
"table_name": "t1",
|
||||
"access_type": "ref",
|
||||
"possible_keys": ["idx1", "idx2"],
|
||||
"key": "idx2",
|
||||
"key_length": "2",
|
||||
"used_key_parts": ["fl2"],
|
||||
"ref": ["const"],
|
||||
"rowid_filter": {
|
||||
"range": {
|
||||
"key": "idx1",
|
||||
"used_key_parts": ["nm"]
|
||||
},
|
||||
"rows": 115,
|
||||
"selectivity_pct": 1.15,
|
||||
"r_rows": 111,
|
||||
"r_lookups": 100,
|
||||
"r_selectivity_pct": 2,
|
||||
"r_buffer_size": "REPLACED",
|
||||
"r_filling_time_ms": "REPLACED"
|
||||
},
|
||||
"r_loops": 1,
|
||||
"rows": 55,
|
||||
"r_rows": 2,
|
||||
"r_table_time_ms": "REPLACED",
|
||||
"r_other_time_ms": "REPLACED",
|
||||
"filtered": 1.149999976,
|
||||
"r_filtered": 100,
|
||||
"attached_condition": "t1.nm like '75%'"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
select * from t1 where nm like '75%' AND fl2 = 0;
|
||||
pk nm fl1 fl2
|
||||
4543 7503 0 0
|
||||
7373 7518 0 0
|
||||
drop table name, flag2;
|
||||
drop table t1;
|
||||
create table t1 (
|
||||
pk int primary key auto_increment,
|
||||
nm char(255),
|
||||
fl1 tinyint default 0,
|
||||
fl2 int default 0,
|
||||
index idx1(nm, fl1),
|
||||
index idx2(fl2)
|
||||
) engine=myisam;
|
||||
create table name (
|
||||
pk int primary key auto_increment,
|
||||
nm bigint
|
||||
) engine=myisam;
|
||||
create table flag2 (
|
||||
pk int primary key auto_increment,
|
||||
fl2 int
|
||||
) engine=myisam;
|
||||
insert into name(nm) select seq from seq_1_to_10000 order by rand(17);
|
||||
insert into flag2(fl2) select seq mod 10 from seq_1_to_10000 order by rand(19);
|
||||
insert into t1(nm,fl2)
|
||||
select nm, fl2 from name, flag2 where name.pk = flag2.pk;
|
||||
analyze table t1 persistent for all;
|
||||
Table Op Msg_type Msg_text
|
||||
test.t1 analyze status Engine-independent statistics collected
|
||||
test.t1 analyze status Table is already up to date
|
||||
select * from t1
|
||||
where
|
||||
(
|
||||
nm like '3400%' or nm like '3402%' or nm like '3403%' or
|
||||
nm like '3404%' or nm like '3405%' or nm like '3406%' or nm like '3407%' or
|
||||
nm like '3409%' or
|
||||
nm like '3411%' or nm like '3412%' or nm like '3413%' or
|
||||
nm like '3414%' or nm like '3415%' or nm like '3416%' or nm like '3417%' or
|
||||
nm like '3418%' or nm like '3419%' or
|
||||
nm like '3421%' or nm like '3422%' or nm like '3423%' or
|
||||
nm like '3424%' or nm like '3425%' or nm like '3426%' or nm like '3427%' or
|
||||
nm like '3428%' or nm like '3429%' or
|
||||
nm like '3430%' or nm like '3431%' or nm like '3432%' or nm like '3433%' or
|
||||
nm like '3434%' or nm like '3435%' or nm like '3436%' or nm like '3437%' or
|
||||
nm like '3439%' or
|
||||
nm like '3440%' or nm like '3441%' or nm like '3442%' or nm like '3443%' or
|
||||
nm like '3444%' or nm like '3445%' or nm like '3446%' or nm like '3447%' or
|
||||
nm like '3448%'
|
||||
) and fl2 = 0;
|
||||
pk nm fl1 fl2
|
||||
analyze format=json select * from t1
|
||||
where
|
||||
(
|
||||
nm like '3400%' or nm like '3402%' or nm like '3403%' or
|
||||
nm like '3404%' or nm like '3405%' or nm like '3406%' or nm like '3407%' or
|
||||
nm like '3409%' or
|
||||
nm like '3411%' or nm like '3412%' or nm like '3413%' or
|
||||
nm like '3414%' or nm like '3415%' or nm like '3416%' or nm like '3417%' or
|
||||
nm like '3418%' or nm like '3419%' or
|
||||
nm like '3421%' or nm like '3422%' or nm like '3423%' or
|
||||
nm like '3424%' or nm like '3425%' or nm like '3426%' or nm like '3427%' or
|
||||
nm like '3428%' or nm like '3429%' or
|
||||
nm like '3430%' or nm like '3431%' or nm like '3432%' or nm like '3433%' or
|
||||
nm like '3434%' or nm like '3435%' or nm like '3436%' or nm like '3437%' or
|
||||
nm like '3439%' or
|
||||
nm like '3440%' or nm like '3441%' or nm like '3442%' or nm like '3443%' or
|
||||
nm like '3444%' or nm like '3445%' or nm like '3446%' or nm like '3447%' or
|
||||
nm like '3448%'
|
||||
) and fl2 = 0;
|
||||
ANALYZE
|
||||
{
|
||||
"query_optimization": {
|
||||
"r_total_time_ms": "REPLACED"
|
||||
},
|
||||
"query_block": {
|
||||
"select_id": 1,
|
||||
"r_loops": 1,
|
||||
"r_total_time_ms": "REPLACED",
|
||||
"nested_loop": [
|
||||
{
|
||||
"table": {
|
||||
"table_name": "t1",
|
||||
"access_type": "range",
|
||||
"possible_keys": ["idx1", "idx2"],
|
||||
"key": "idx1",
|
||||
"key_length": "256",
|
||||
"used_key_parts": ["nm"],
|
||||
"rowid_filter": {
|
||||
"range": {
|
||||
"key": "idx2",
|
||||
"used_key_parts": ["fl2"]
|
||||
},
|
||||
"rows": 863,
|
||||
"selectivity_pct": 8.63,
|
||||
"r_rows": 1000,
|
||||
"r_lookups": 44,
|
||||
"r_selectivity_pct": 0,
|
||||
"r_buffer_size": "REPLACED",
|
||||
"r_filling_time_ms": "REPLACED"
|
||||
},
|
||||
"r_loops": 1,
|
||||
"rows": 44,
|
||||
"r_rows": 0,
|
||||
"r_table_time_ms": "REPLACED",
|
||||
"r_other_time_ms": "REPLACED",
|
||||
"filtered": 8.630000114,
|
||||
"r_filtered": 100,
|
||||
"index_condition": "t1.nm like '3400%' or t1.nm like '3402%' or t1.nm like '3403%' or t1.nm like '3404%' or t1.nm like '3405%' or t1.nm like '3406%' or t1.nm like '3407%' or t1.nm like '3409%' or t1.nm like '3411%' or t1.nm like '3412%' or t1.nm like '3413%' or t1.nm like '3414%' or t1.nm like '3415%' or t1.nm like '3416%' or t1.nm like '3417%' or t1.nm like '3418%' or t1.nm like '3419%' or t1.nm like '3421%' or t1.nm like '3422%' or t1.nm like '3423%' or t1.nm like '3424%' or t1.nm like '3425%' or t1.nm like '3426%' or t1.nm like '3427%' or t1.nm like '3428%' or t1.nm like '3429%' or t1.nm like '3430%' or t1.nm like '3431%' or t1.nm like '3432%' or t1.nm like '3433%' or t1.nm like '3434%' or t1.nm like '3435%' or t1.nm like '3436%' or t1.nm like '3437%' or t1.nm like '3439%' or t1.nm like '3440%' or t1.nm like '3441%' or t1.nm like '3442%' or t1.nm like '3443%' or t1.nm like '3444%' or t1.nm like '3445%' or t1.nm like '3446%' or t1.nm like '3447%' or t1.nm like '3448%'",
|
||||
"attached_condition": "t1.fl2 = 0"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
create table t0 select * from t1 where nm like '34%';
|
||||
delete from t1 using t1,t0 where t1.nm=t0.nm;
|
||||
analyze format=json select * from t1
|
||||
where
|
||||
(
|
||||
nm like '3400%' or nm like '3402%' or nm like '3403%' or
|
||||
nm like '3404%' or nm like '3405%' or nm like '3406%' or nm like '3407%' or
|
||||
nm like '3409%' or
|
||||
nm like '3411%' or nm like '3412%' or nm like '3413%' or
|
||||
nm like '3414%' or nm like '3415%' or nm like '3416%' or nm like '3417%' or
|
||||
nm like '3418%' or nm like '3419%' or
|
||||
nm like '3421%' or nm like '3422%' or nm like '3423%' or
|
||||
nm like '3424%' or nm like '3425%' or nm like '3426%' or nm like '3427%' or
|
||||
nm like '3428%' or nm like '3429%' or
|
||||
nm like '3430%' or nm like '3431%' or nm like '3432%' or nm like '3433%' or
|
||||
nm like '3434%' or nm like '3435%' or nm like '3436%' or nm like '3437%' or
|
||||
nm like '3439%' or
|
||||
nm like '3440%' or nm like '3441%' or nm like '3442%' or nm like '3443%' or
|
||||
nm like '3444%' or nm like '3445%' or nm like '3446%' or nm like '3447%' or
|
||||
nm like '3448%'
|
||||
) and fl2 = 0;
|
||||
ANALYZE
|
||||
{
|
||||
"query_optimization": {
|
||||
"r_total_time_ms": "REPLACED"
|
||||
},
|
||||
"query_block": {
|
||||
"select_id": 1,
|
||||
"r_loops": 1,
|
||||
"r_total_time_ms": "REPLACED",
|
||||
"nested_loop": [
|
||||
{
|
||||
"table": {
|
||||
"table_name": "t1",
|
||||
"access_type": "range",
|
||||
"possible_keys": ["idx1", "idx2"],
|
||||
"key": "idx1",
|
||||
"key_length": "256",
|
||||
"used_key_parts": ["nm"],
|
||||
"rowid_filter": {
|
||||
"range": {
|
||||
"key": "idx2",
|
||||
"used_key_parts": ["fl2"]
|
||||
},
|
||||
"rows": 853,
|
||||
"selectivity_pct": 8.53,
|
||||
"r_rows": 987,
|
||||
"r_lookups": 0,
|
||||
"r_selectivity_pct": 0,
|
||||
"r_buffer_size": "REPLACED",
|
||||
"r_filling_time_ms": "REPLACED"
|
||||
},
|
||||
"r_loops": 1,
|
||||
"rows": 44,
|
||||
"r_rows": 0,
|
||||
"r_table_time_ms": "REPLACED",
|
||||
"r_other_time_ms": "REPLACED",
|
||||
"filtered": 8.529999733,
|
||||
"r_filtered": 100,
|
||||
"index_condition": "t1.nm like '3400%' or t1.nm like '3402%' or t1.nm like '3403%' or t1.nm like '3404%' or t1.nm like '3405%' or t1.nm like '3406%' or t1.nm like '3407%' or t1.nm like '3409%' or t1.nm like '3411%' or t1.nm like '3412%' or t1.nm like '3413%' or t1.nm like '3414%' or t1.nm like '3415%' or t1.nm like '3416%' or t1.nm like '3417%' or t1.nm like '3418%' or t1.nm like '3419%' or t1.nm like '3421%' or t1.nm like '3422%' or t1.nm like '3423%' or t1.nm like '3424%' or t1.nm like '3425%' or t1.nm like '3426%' or t1.nm like '3427%' or t1.nm like '3428%' or t1.nm like '3429%' or t1.nm like '3430%' or t1.nm like '3431%' or t1.nm like '3432%' or t1.nm like '3433%' or t1.nm like '3434%' or t1.nm like '3435%' or t1.nm like '3436%' or t1.nm like '3437%' or t1.nm like '3439%' or t1.nm like '3440%' or t1.nm like '3441%' or t1.nm like '3442%' or t1.nm like '3443%' or t1.nm like '3444%' or t1.nm like '3445%' or t1.nm like '3446%' or t1.nm like '3447%' or t1.nm like '3448%'",
|
||||
"attached_condition": "t1.fl2 = 0"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
drop table t0;
|
||||
set optimizer_switch='rowid_filter=default';
|
||||
drop table name, flag2;
|
||||
drop table t1;
|
||||
set @@use_stat_tables=@save_use_stat_tables;
|
||||
#
|
||||
# MDEV-21633
|
||||
# Assertion `tmp >= 0' failed in best_access_path with rowid_filter=ON
|
||||
#
|
||||
set @save_optimizer_switch= @@optimizer_switch;
|
||||
SET optimizer_switch='rowid_filter=on';
|
||||
CREATE TABLE t1 (
|
||||
pk INT AUTO_INCREMENT,
|
||||
a INT,
|
||||
b VARCHAR(8),
|
||||
KEY(a),
|
||||
PRIMARY KEY(pk),
|
||||
KEY (a,pk)
|
||||
) ENGINE=MyISAM;
|
||||
INSERT INTO t1 (a,b) VALUES
|
||||
(NULL,'d'),(9,'b'),(2,'x'),(5,'k'),(NULL,'d'),(3,'s'),(5,'k'),(1,'r'),
|
||||
(8,'l'),(3,'z'),(1,'c'),(1,'q'),(NULL,'x'),(NULL,'p'),(NULL,'z'),(7,'a'),
|
||||
(0,'i'),(3,'s'),(NULL,'h'),(4,'p'),(1,'i'),(4,'f'),(1,'c'),(NULL,'a'),
|
||||
(NULL,'x'),(1,'b'),(NULL,'n'),(NULL,'h'),(5,'i'),(6,'e'),(NULL,'i'),
|
||||
(7,'e'),(1,'r'),(NULL,'z'),(1,'i'),(14,'c'),(6,'u'),(3,'b'),(4,'z'),
|
||||
(2,'c'),(70,'d'),(NULL,'p'),(21,'j'),(6,'e'),(5,'c'),(13,'i'),(42,'d'),
|
||||
(80,'s'),(14,'t'),(9,'a'),(0,'2'),(0,NULL),(0,NULL),(0,NULL),(0,''),
|
||||
(0,''),(0,'1'),(0,''),(0,''),(0,''),(0,''),(0,NULL),(0,''),(0,''),(0,''),
|
||||
(0,NULL),(0,''),(0,''),(0,''),(0,''),(0,''),(0,''),(0,NULL),(0,NULL),
|
||||
(0,NULL),(0,''),(0,''),(0,''),(0,''),(0,NULL),(0,''),(0,NULL),(0,NULL),
|
||||
(0,''),(0,''),(0,''),(0,NULL),(0,''),(0,NULL),(0,''),(0,''),(0,''),(0,''),
|
||||
(0,''),(0,''),(0,''),(0,NULL),(0,''),(0,NULL),(0,'');
|
||||
CREATE TABLE t2 (c INT) ENGINE=MyISAM;
|
||||
INSERT INTO t2 VALUES (1),(2),(3),(4),(5),(6);
|
||||
SELECT * FROM t1 JOIN t2 WHERE a = c AND pk BETWEEN 4 AND 7 AND a BETWEEN 2 AND 12 AND b != 'foo';
|
||||
pk a b c
|
||||
6 3 s 3
|
||||
4 5 k 5
|
||||
7 5 k 5
|
||||
explain SELECT * FROM t1 JOIN t2 WHERE a = c AND pk BETWEEN 4 AND 7 AND a BETWEEN 2 AND 12 AND b != 'foo';
|
||||
id select_type table type possible_keys key key_len ref rows Extra
|
||||
1 SIMPLE t1 range|filter PRIMARY,a,a_2 PRIMARY|a 4|5 NULL 4 (11%) Using index condition; Using where; Using rowid filter
|
||||
1 SIMPLE t2 ALL NULL NULL NULL NULL 6 Using where; Using join buffer (flat, BNL join)
|
||||
SET optimizer_switch='rowid_filter=off';
|
||||
SELECT * FROM t1 JOIN t2 WHERE a = c AND pk BETWEEN 4 AND 7 AND a BETWEEN 2 AND 12 AND b != 'foo';
|
||||
pk a b c
|
||||
6 3 s 3
|
||||
4 5 k 5
|
||||
7 5 k 5
|
||||
SET @@optimizer_switch=@save_optimizer_switch;
|
||||
DROP TABLE t1, t2;
|
||||
SET GLOBAL innodb_stats_persistent=@save_stats_persistent;
|
||||
#
|
||||
# MDEV-18755: possible RORI-plan and possible plan with range filter
|
||||
|
@ -1,3 +1,4 @@
|
||||
SET optimizer_switch='rowid_filter=on';
|
||||
#
|
||||
# MDEV-22553: Assertion `info->lastpos == (~ (my_off_t) 0)' failed in mi_rkey with rowid_filer=on
|
||||
#
|
||||
@ -19,3 +20,675 @@ ALTER TABLE t1 ENABLE KEYS;
|
||||
SELECT * FROM t1 WHERE ( a BETWEEN 255 AND 270 OR f = 200 ) AND f IN ( 1, 4, 112, 143 ) AND d IN ('Montana', 'South Dakota');
|
||||
a b c d e f
|
||||
DROP TABLE t1;
|
||||
use test;
|
||||
#
|
||||
# MDEV-18816: potential range filter for one join table with
|
||||
# impossible WHERE for another
|
||||
#
|
||||
create table t1 (
|
||||
pk int not null primary key, c2 varchar(10) , i1 int,key (c2)
|
||||
) engine=myisam;
|
||||
insert into t1 values (1,'a',-5),(2,'a',null);
|
||||
create table t2 (
|
||||
pk int, i1 int, c1 varchar(30) , key c1 (c1(30)), key i1 (i1)
|
||||
) engine=myisam;
|
||||
insert into t2 values
|
||||
(1,-5,'a'),(2,null,'a'),(3,null,'a'),(4,null,'a'),(5,5,'a'),(6,null,'a'),
|
||||
(7,4,'a'),(8,55,'a'),(9,null,'a'),(10,null,'a'),(11,null,'a'),(12,-5,'a'),
|
||||
(13,-5,'a'),(14,null,'a'),(15,null,'a'),(16,-5,'a'),(17,-5,'a');
|
||||
select 1
|
||||
from t1
|
||||
left join
|
||||
t2 join t1 as t1_a on t2.i1 = t1_a.pk
|
||||
on t1.c2 = t2.c1
|
||||
where t1_a.pk is null and t1_a.i1 != 3;
|
||||
1
|
||||
explain extended select 1
|
||||
from t1
|
||||
left join
|
||||
t2 join t1 as t1_a on t2.i1 = t1_a.pk
|
||||
on t1.c2 = t2.c1
|
||||
where t1_a.pk is null and t1_a.i1 != 3;
|
||||
id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||
1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
|
||||
Warnings:
|
||||
Note 1003 select 1 AS `1` from `test`.`t1` join `test`.`t2` join `test`.`t1` `t1_a` where 0
|
||||
drop table t1,t2;
|
||||
#
|
||||
# MDEV-18640: TABLE::prune_range_rowid_filters: Conditional jump or
|
||||
# move depends on uninitialized value
|
||||
#
|
||||
CREATE TABLE t1 (
|
||||
pk INT, i INT, PRIMARY KEY (pk), KEY (pk,i)
|
||||
) ENGINE=MyISAM;
|
||||
INSERT INTO t1 VALUES (1,10), (7,70), (2,20);
|
||||
SELECT * FROM t1 WHERE pk < 5;
|
||||
pk i
|
||||
1 10
|
||||
2 20
|
||||
DROP TABLE t1;
|
||||
#
|
||||
# MDEV-18956: Possible rowid filter for subquery for which
|
||||
# in_to_exists strategy has been chosen
|
||||
#
|
||||
CREATE TABLE t1 (pk int) engine=myisam ;
|
||||
INSERT INTO t1 VALUES (1),(2);
|
||||
CREATE TABLE t2 (
|
||||
pk int auto_increment PRIMARY KEY,
|
||||
i1 int, i2 int, c2 varchar(1),
|
||||
KEY (i1), KEY (i2)
|
||||
) engine=myisam;
|
||||
INSERT INTO t2 VALUES
|
||||
(1,8,6,'t'),(2,5,7,'i'),(3,4,4,'h'),(4,207,38,'d'),(5,183,206,'b'),
|
||||
(6,7,null,'o'),(7,1,2,'j'),(8,17,36,'s'),(9,4,5,'q'),(10,0,6,'l'),
|
||||
(11,1,9,'j'),(12,5,6,'y'),(13,null,0,'i'),(14,7,7,'x'),(15,5,2,'u');
|
||||
SELECT * FROM t1 HAVING (7, 9) IN (SELECT t2.i1, t2.i2 FROM t2 WHERE t2.i1 = 3);
|
||||
pk
|
||||
EXPLAIN EXTENDED
|
||||
SELECT * FROM t1 HAVING (7, 9) IN (SELECT t2.i1, t2.i2 FROM t2 WHERE t2.i1 = 3);
|
||||
id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||
1 PRIMARY NULL NULL NULL NULL NULL NULL NULL NULL Impossible HAVING
|
||||
2 SUBQUERY NULL NULL NULL NULL NULL NULL NULL NULL no matching row in const table
|
||||
Warnings:
|
||||
Note 1003 /* select#1 */ select `test`.`t1`.`pk` AS `pk` from `test`.`t1` having 0
|
||||
DROP TABLE t1,t2;
|
||||
#
|
||||
# MDEV-19255: rowid range filter built for range condition
|
||||
# that uses in expensive subquery
|
||||
#
|
||||
CREATE TABLE t1 (
|
||||
pk1 INT PRIMARY KEY, a1 INT, b1 VARCHAR(1), KEY(b1)
|
||||
) ENGINE=MyISAM;
|
||||
INSERT INTO t1 VALUES
|
||||
(10,0,'z'),(11,3,'j'),(12,8,'f'),(13,8,'p'),(14,6,'w'),(15,0,'c'),(16,1,'j'),
|
||||
(17,1,'f'),(18,5,'v'),(19,3,'f'),(20,2,'q'),(21,8,'y'),(22,0,'a'),(23,9,'w'),
|
||||
(24,3,'e'),(25,1,'b'),(26,9,'r'),(27,2,'k'),(28,5,'c'),(29,3,'k'),(30,9,'b'),
|
||||
(31,8,'j'),(32,1,'t'),(33,8,'n'),(34,3,'z'),(35,0,'u'),(36,3,'a'),(37,3,'g'),
|
||||
(38,1,'f'),(39,6,'p'),(40,6,'m'),(41,6,'t'),(42,7,'i'),(43,4,'h'),(44,3,'d'),
|
||||
(45,2,'b'),(46,1,'o'),(47,2,'j'),(48,6,'s'),(49,5,'q'),(50,6,'l'),(51,9,'j'),
|
||||
(52,6,'y'),(53,0,'i'),(54,7,'x'),(55,2,'u'),(56,6,'t'),(57,4,'b'),(58,5,'m'),
|
||||
(59,4,'x'),(60,8,'x'),(61,6,'v'),(62,8,'m'),(63,4,'j'),(64,8,'z'),(65,2,'a'),
|
||||
(66,9,'i'),(67,4,'g'),(68,8,'h'),(69,1,'p'),(70,8,'a'),(71,0,'x'),(72,2,'s'),
|
||||
(73,6,'k'),(74,0,'m'),(75,6,'e'),(76,9,'y'),(77,7,'d'),(78,7,'w'),(79,6,'y'),
|
||||
(80,9,'s'),(81,9,'x'),(82,6,'l'),(83,9,'f'),(84,8,'x'),(85,1,'p'),(86,7,'y'),
|
||||
(87,6,'p'),(88,1,'g'),(89,3,'c'),(90,5,'h'),(91,3,'p'),(92,2,'b'),(93,1,NULL),
|
||||
(94,3,NULL),(95,2,'y'),(96,7,'s'),(97,7,'x'),(98,6,'i'),(99,9,'t'),(100,5,'j'),
|
||||
(101,0,'u'),(102,7,'r'),(103,2,'x'),(104,8,'e'),(105,8,'i'),(106,5,'q'),
|
||||
(107,8,'z'),(108,3,'k'),(109,65,NULL);
|
||||
CREATE TABLE t2 (pk2 INT PRIMARY KEY, a2 INT, b2 VARCHAR(1)) ENGINE=MyISAM;
|
||||
INSERT INTO t2 VALUES (1,1,'x');
|
||||
INSERT INTO t2 SELECT * FROM t1;
|
||||
SELECT * FROM t1 INNER JOIN t2 ON ( pk1 <> pk2 AND pk1 = a2 )
|
||||
WHERE b1 <= ( SELECT MAX(b2) FROM t2 WHERE pk2 <= 1 );
|
||||
pk1 a1 b1 pk2 a2 b2
|
||||
65 2 a 109 65 NULL
|
||||
EXPLAIN EXTENDED SELECT * FROM t1 INNER JOIN t2 ON ( pk1 <> pk2 AND pk1 = a2 )
|
||||
WHERE b1 <= ( SELECT MAX(b2) FROM t2 WHERE pk2 <= 1 );
|
||||
id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||
1 PRIMARY t2 ALL NULL NULL NULL NULL 101 100.00 Using where
|
||||
1 PRIMARY t1 eq_ref|filter PRIMARY,b1 PRIMARY|b1 4|4 test.t2.a2 1 (87%) 87.00 Using where; Using rowid filter
|
||||
2 SUBQUERY t2 range PRIMARY PRIMARY 4 NULL 1 100.00 Using index condition
|
||||
Warnings:
|
||||
Note 1003 /* select#1 */ select `test`.`t1`.`pk1` AS `pk1`,`test`.`t1`.`a1` AS `a1`,`test`.`t1`.`b1` AS `b1`,`test`.`t2`.`pk2` AS `pk2`,`test`.`t2`.`a2` AS `a2`,`test`.`t2`.`b2` AS `b2` from `test`.`t1` join `test`.`t2` where `test`.`t1`.`pk1` = `test`.`t2`.`a2` and `test`.`t1`.`b1` <= (/* select#2 */ select max(`test`.`t2`.`b2`) from `test`.`t2` where `test`.`t2`.`pk2` <= 1) and `test`.`t2`.`a2` <> `test`.`t2`.`pk2`
|
||||
EXPLAIN FORMAT=JSON SELECT * FROM t1 INNER JOIN t2 ON ( pk1 <> pk2 AND pk1 = a2 )
|
||||
WHERE b1 <= ( SELECT MAX(b2) FROM t2 WHERE pk2 <= 1 );
|
||||
EXPLAIN
|
||||
{
|
||||
"query_block": {
|
||||
"select_id": 1,
|
||||
"nested_loop": [
|
||||
{
|
||||
"table": {
|
||||
"table_name": "t2",
|
||||
"access_type": "ALL",
|
||||
"rows": 101,
|
||||
"filtered": 100,
|
||||
"attached_condition": "t2.a2 <> t2.pk2 and t2.a2 is not null"
|
||||
}
|
||||
},
|
||||
{
|
||||
"table": {
|
||||
"table_name": "t1",
|
||||
"access_type": "eq_ref",
|
||||
"possible_keys": ["PRIMARY", "b1"],
|
||||
"key": "PRIMARY",
|
||||
"key_length": "4",
|
||||
"used_key_parts": ["pk1"],
|
||||
"ref": ["test.t2.a2"],
|
||||
"rowid_filter": {
|
||||
"range": {
|
||||
"key": "b1",
|
||||
"used_key_parts": ["b1"]
|
||||
},
|
||||
"rows": 87,
|
||||
"selectivity_pct": 87
|
||||
},
|
||||
"rows": 1,
|
||||
"filtered": 87,
|
||||
"attached_condition": "t1.b1 <= (subquery#2)"
|
||||
}
|
||||
}
|
||||
],
|
||||
"subqueries": [
|
||||
{
|
||||
"query_block": {
|
||||
"select_id": 2,
|
||||
"nested_loop": [
|
||||
{
|
||||
"table": {
|
||||
"table_name": "t2",
|
||||
"access_type": "range",
|
||||
"possible_keys": ["PRIMARY"],
|
||||
"key": "PRIMARY",
|
||||
"key_length": "4",
|
||||
"used_key_parts": ["pk2"],
|
||||
"rows": 1,
|
||||
"filtered": 100,
|
||||
"index_condition": "t2.pk2 <= 1"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
DROP TABLE t1,t2;
|
||||
#
|
||||
# MDEV-21794: Optimizer flag rowid_filter leads to long query
|
||||
#
|
||||
create table t10(a int);
|
||||
insert into t10 values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9);
|
||||
create table t11(a int);
|
||||
insert into t11 select A.a + B.a* 10 + C.a * 100 from t10 A, t10 B, t10 C;
|
||||
CREATE TABLE t1 (
|
||||
el_id int(10) unsigned NOT NULL ,
|
||||
el_index blob NOT NULL,
|
||||
el_index_60 varbinary(60) NOT NULL,
|
||||
filler blob,
|
||||
PRIMARY KEY (el_id),
|
||||
KEY el_index (el_index(60)),
|
||||
KEY el_index_60 (el_index_60,el_id)
|
||||
);
|
||||
insert into t1
|
||||
select
|
||||
A.a+1000*B.a,
|
||||
A.a+1000*B.a + 10000,
|
||||
A.a+1000*B.a + 10000,
|
||||
'filler-data-filler-data'
|
||||
from
|
||||
t11 A, t10 B;
|
||||
analyze table t1 persistent for all;
|
||||
Table Op Msg_type Msg_text
|
||||
test.t1 analyze status Engine-independent statistics collected
|
||||
test.t1 analyze Warning Engine-independent statistics are not collected for column 'el_index'
|
||||
test.t1 analyze Warning Engine-independent statistics are not collected for column 'filler'
|
||||
test.t1 analyze status Table is already up to date
|
||||
# This must not use rowid_filter with key=el_index|el_index_60:
|
||||
explain
|
||||
select * from t1
|
||||
where el_index like '10%' and (el_index_60 like '10%' or el_index_60 like '20%');
|
||||
id select_type table type possible_keys key key_len ref rows Extra
|
||||
1 SIMPLE t1 range el_index,el_index_60 el_index 62 NULL 645 Using where
|
||||
drop table t10, t11, t1;
|
||||
#
|
||||
# MDEV-22160: SIGSEGV in st_join_table::save_explain_data on SELECT
|
||||
#
|
||||
set @save_optimizer_switch= @@optimizer_switch;
|
||||
SET @@optimizer_switch="index_merge_sort_union=OFF";
|
||||
CREATE TABLE t1 (a INT, b INT, INDEX(a), INDEX(b));
|
||||
INSERT INTO t1 VALUES (0,0),(0,0),(1,0),(-1,1), (-2,1), (-2,3), (-3,4), (-2,4),(3,3),(3,4),(3,5),(8,8),(8,9),(1,0),(2,0),(0,0),(0,0);
|
||||
explain
|
||||
SELECT * FROM t1 WHERE a > 0 AND b=0;
|
||||
id select_type table type possible_keys key key_len ref rows Extra
|
||||
1 SIMPLE t1 ref|filter a,b b|a 5|5 const 7 (47%) Using where; Using rowid filter
|
||||
SELECT * FROM t1 WHERE a > 0 AND b=0;
|
||||
a b
|
||||
1 0
|
||||
1 0
|
||||
2 0
|
||||
drop table t1;
|
||||
SET @@optimizer_switch=@save_optimizer_switch;
|
||||
#
|
||||
# MDEV-21633
|
||||
# Assertion `tmp >= 0' failed in best_access_path with rowid_filter=ON
|
||||
#
|
||||
set @save_optimizer_switch= @@optimizer_switch;
|
||||
SET optimizer_switch='rowid_filter=on';
|
||||
CREATE TABLE t1 (
|
||||
pk INT AUTO_INCREMENT,
|
||||
a INT,
|
||||
b VARCHAR(8),
|
||||
KEY(a),
|
||||
PRIMARY KEY(pk),
|
||||
KEY (a,pk)
|
||||
) ENGINE=MyISAM;
|
||||
INSERT INTO t1 (a,b) VALUES
|
||||
(NULL,'d'),(9,'b'),(2,'x'),(5,'k'),(NULL,'d'),(3,'s'),(5,'k'),(1,'r'),
|
||||
(8,'l'),(3,'z'),(1,'c'),(1,'q'),(NULL,'x'),(NULL,'p'),(NULL,'z'),(7,'a'),
|
||||
(0,'i'),(3,'s'),(NULL,'h'),(4,'p'),(1,'i'),(4,'f'),(1,'c'),(NULL,'a'),
|
||||
(NULL,'x'),(1,'b'),(NULL,'n'),(NULL,'h'),(5,'i'),(6,'e'),(NULL,'i'),
|
||||
(7,'e'),(1,'r'),(NULL,'z'),(1,'i'),(14,'c'),(6,'u'),(3,'b'),(4,'z'),
|
||||
(2,'c'),(70,'d'),(NULL,'p'),(21,'j'),(6,'e'),(5,'c'),(13,'i'),(42,'d'),
|
||||
(80,'s'),(14,'t'),(9,'a'),(0,'2'),(0,NULL),(0,NULL),(0,NULL),(0,''),
|
||||
(0,''),(0,'1'),(0,''),(0,''),(0,''),(0,''),(0,NULL),(0,''),(0,''),(0,''),
|
||||
(0,NULL),(0,''),(0,''),(0,''),(0,''),(0,''),(0,''),(0,NULL),(0,NULL),
|
||||
(0,NULL),(0,''),(0,''),(0,''),(0,''),(0,NULL),(0,''),(0,NULL),(0,NULL),
|
||||
(0,''),(0,''),(0,''),(0,NULL),(0,''),(0,NULL),(0,''),(0,''),(0,''),(0,''),
|
||||
(0,''),(0,''),(0,''),(0,NULL),(0,''),(0,NULL),(0,'');
|
||||
CREATE TABLE t2 (c INT) ENGINE=MyISAM;
|
||||
INSERT INTO t2 VALUES (1),(2),(3),(4),(5),(6);
|
||||
SELECT * FROM t1 JOIN t2 WHERE a = c AND pk BETWEEN 4 AND 7 AND a BETWEEN 2 AND 12 AND b != 'foo';
|
||||
pk a b c
|
||||
6 3 s 3
|
||||
4 5 k 5
|
||||
7 5 k 5
|
||||
explain SELECT * FROM t1 JOIN t2 WHERE a = c AND pk BETWEEN 4 AND 7 AND a BETWEEN 2 AND 12 AND b != 'foo';
|
||||
id select_type table type possible_keys key key_len ref rows Extra
|
||||
1 SIMPLE t1 range|filter PRIMARY,a,a_2 PRIMARY|a 4|5 NULL 4 (11%) Using index condition; Using where; Using rowid filter
|
||||
1 SIMPLE t2 ALL NULL NULL NULL NULL 6 Using where; Using join buffer (flat, BNL join)
|
||||
SET optimizer_switch='rowid_filter=off';
|
||||
SELECT * FROM t1 JOIN t2 WHERE a = c AND pk BETWEEN 4 AND 7 AND a BETWEEN 2 AND 12 AND b != 'foo';
|
||||
pk a b c
|
||||
6 3 s 3
|
||||
4 5 k 5
|
||||
7 5 k 5
|
||||
SET @@optimizer_switch=@save_optimizer_switch;
|
||||
DROP TABLE t1, t2;
|
||||
#
|
||||
# MDEV-28846: Poor performance when rowid filter contains no elements
|
||||
#
|
||||
create table t1 (
|
||||
pk int primary key auto_increment,
|
||||
nm varchar(32),
|
||||
fl1 tinyint default 0,
|
||||
fl2 tinyint default 0,
|
||||
index idx1(nm, fl1),
|
||||
index idx2(fl2)
|
||||
) engine=myisam;
|
||||
create table name (
|
||||
pk int primary key auto_increment,
|
||||
nm bigint
|
||||
) engine=myisam;
|
||||
create table flag2 (
|
||||
pk int primary key auto_increment,
|
||||
fl2 tinyint
|
||||
) engine=myisam;
|
||||
insert into name(nm) select seq from seq_1_to_1000 order by rand(17);
|
||||
insert into flag2(fl2) select seq mod 2 from seq_1_to_1000 order by rand(19);
|
||||
insert into t1(nm,fl2)
|
||||
select nm, fl2 from name, flag2 where name.pk = flag2.pk;
|
||||
analyze table t1 persistent for all;
|
||||
Table Op Msg_type Msg_text
|
||||
test.t1 analyze status Engine-independent statistics collected
|
||||
test.t1 analyze status Table is already up to date
|
||||
select '500%' as a;
|
||||
a
|
||||
500%
|
||||
set optimizer_switch='rowid_filter=on';
|
||||
explain
|
||||
select * from t1 where nm like '500%' AND fl2 = 0;
|
||||
id select_type table type possible_keys key key_len ref rows Extra
|
||||
1 SIMPLE t1 range idx1,idx2 idx1 35 NULL 1 Using index condition; Using where
|
||||
analyze format=json
|
||||
select * from t1 where nm like '500%' AND fl2 = 0;
|
||||
ANALYZE
|
||||
{
|
||||
"query_optimization": {
|
||||
"r_total_time_ms": "REPLACED"
|
||||
},
|
||||
"query_block": {
|
||||
"select_id": 1,
|
||||
"r_loops": 1,
|
||||
"r_total_time_ms": "REPLACED",
|
||||
"nested_loop": [
|
||||
{
|
||||
"table": {
|
||||
"table_name": "t1",
|
||||
"access_type": "range",
|
||||
"possible_keys": ["idx1", "idx2"],
|
||||
"key": "idx1",
|
||||
"key_length": "35",
|
||||
"used_key_parts": ["nm"],
|
||||
"r_loops": 1,
|
||||
"rows": 1,
|
||||
"r_rows": 1,
|
||||
"r_table_time_ms": "REPLACED",
|
||||
"r_other_time_ms": "REPLACED",
|
||||
"filtered": 49.20000076,
|
||||
"r_filtered": 100,
|
||||
"index_condition": "t1.nm like '500%'",
|
||||
"attached_condition": "t1.fl2 = 0"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
select * from t1 where nm like '500%' AND fl2 = 0;
|
||||
pk nm fl1 fl2
|
||||
517 500 0 0
|
||||
truncate table name;
|
||||
truncate table flag2;
|
||||
truncate table t1;
|
||||
insert into name(nm) select seq from seq_1_to_1000 order by rand(17);
|
||||
insert into flag2(fl2) select seq mod 2 from seq_1_to_1000 order by rand(19);
|
||||
insert into t1(nm,fl2)
|
||||
select nm, fl2 from name, flag2 where name.pk = flag2.pk;
|
||||
analyze table t1 persistent for all;
|
||||
Table Op Msg_type Msg_text
|
||||
test.t1 analyze status Engine-independent statistics collected
|
||||
test.t1 analyze status Table is already up to date
|
||||
set optimizer_switch='rowid_filter=off';
|
||||
explain
|
||||
select * from t1 where nm like '500%' AND fl2 = 0;
|
||||
id select_type table type possible_keys key key_len ref rows Extra
|
||||
1 SIMPLE t1 range idx1,idx2 idx1 35 NULL 1 Using index condition; Using where
|
||||
analyze format=json
|
||||
select * from t1 where nm like '500%' AND fl2 = 0;
|
||||
ANALYZE
|
||||
{
|
||||
"query_optimization": {
|
||||
"r_total_time_ms": "REPLACED"
|
||||
},
|
||||
"query_block": {
|
||||
"select_id": 1,
|
||||
"r_loops": 1,
|
||||
"r_total_time_ms": "REPLACED",
|
||||
"nested_loop": [
|
||||
{
|
||||
"table": {
|
||||
"table_name": "t1",
|
||||
"access_type": "range",
|
||||
"possible_keys": ["idx1", "idx2"],
|
||||
"key": "idx1",
|
||||
"key_length": "35",
|
||||
"used_key_parts": ["nm"],
|
||||
"r_loops": 1,
|
||||
"rows": 1,
|
||||
"r_rows": 1,
|
||||
"r_table_time_ms": "REPLACED",
|
||||
"r_other_time_ms": "REPLACED",
|
||||
"filtered": 49.20000076,
|
||||
"r_filtered": 100,
|
||||
"index_condition": "t1.nm like '500%'",
|
||||
"attached_condition": "t1.fl2 = 0"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
select * from t1 where nm like '500%' AND fl2 = 0;
|
||||
pk nm fl1 fl2
|
||||
517 500 0 0
|
||||
truncate table name;
|
||||
truncate table flag2;
|
||||
truncate table t1;
|
||||
insert into name(nm) select seq from seq_1_to_1000 order by rand(17);
|
||||
insert into flag2(fl2) select seq mod 10 from seq_1_to_1000 order by rand(19);
|
||||
insert into t1(nm,fl2)
|
||||
select nm, fl2 from name, flag2 where name.pk = flag2.pk;
|
||||
analyze table t1 persistent for all;
|
||||
Table Op Msg_type Msg_text
|
||||
test.t1 analyze status Engine-independent statistics collected
|
||||
test.t1 analyze status Table is already up to date
|
||||
select '607%' as a;
|
||||
a
|
||||
607%
|
||||
set optimizer_switch='rowid_filter=on';
|
||||
explain
|
||||
select * from t1 where nm like '607%' AND fl2 = 0;
|
||||
id select_type table type possible_keys key key_len ref rows Extra
|
||||
1 SIMPLE t1 range idx1,idx2 idx1 35 NULL 1 Using index condition; Using where
|
||||
select * from t1 where nm like '607%' AND fl2 = 0;
|
||||
pk nm fl1 fl2
|
||||
721 607 0 0
|
||||
truncate table name;
|
||||
truncate table flag2;
|
||||
truncate table t1;
|
||||
insert into name(nm) select seq from seq_1_to_10000 order by rand(17);
|
||||
insert into flag2(fl2) select seq mod 100 from seq_1_to_10000 order by rand(19);
|
||||
insert into t1(nm,fl2)
|
||||
select nm, fl2 from name, flag2 where name.pk = flag2.pk;
|
||||
analyze table t1 persistent for all;
|
||||
Table Op Msg_type Msg_text
|
||||
test.t1 analyze status Engine-independent statistics collected
|
||||
test.t1 analyze status Table is already up to date
|
||||
select '75%' as a;
|
||||
a
|
||||
75%
|
||||
set optimizer_switch='rowid_filter=on';
|
||||
explain
|
||||
select * from t1 where nm like '75%' AND fl2 = 0;
|
||||
id select_type table type possible_keys key key_len ref rows Extra
|
||||
1 SIMPLE t1 ref|filter idx1,idx2 idx2|idx1 2|35 const 55 (1%) Using where; Using rowid filter
|
||||
analyze format=json
|
||||
select * from t1 where nm like '75%' AND fl2 = 0;
|
||||
ANALYZE
|
||||
{
|
||||
"query_optimization": {
|
||||
"r_total_time_ms": "REPLACED"
|
||||
},
|
||||
"query_block": {
|
||||
"select_id": 1,
|
||||
"r_loops": 1,
|
||||
"r_total_time_ms": "REPLACED",
|
||||
"nested_loop": [
|
||||
{
|
||||
"table": {
|
||||
"table_name": "t1",
|
||||
"access_type": "ref",
|
||||
"possible_keys": ["idx1", "idx2"],
|
||||
"key": "idx2",
|
||||
"key_length": "2",
|
||||
"used_key_parts": ["fl2"],
|
||||
"ref": ["const"],
|
||||
"rowid_filter": {
|
||||
"range": {
|
||||
"key": "idx1",
|
||||
"used_key_parts": ["nm"]
|
||||
},
|
||||
"rows": 115,
|
||||
"selectivity_pct": 1.15,
|
||||
"r_rows": 111,
|
||||
"r_lookups": 100,
|
||||
"r_selectivity_pct": 2,
|
||||
"r_buffer_size": "REPLACED",
|
||||
"r_filling_time_ms": "REPLACED"
|
||||
},
|
||||
"r_loops": 1,
|
||||
"rows": 55,
|
||||
"r_rows": 2,
|
||||
"r_table_time_ms": "REPLACED",
|
||||
"r_other_time_ms": "REPLACED",
|
||||
"filtered": 1.149999976,
|
||||
"r_filtered": 100,
|
||||
"attached_condition": "t1.nm like '75%'"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
select * from t1 where nm like '75%' AND fl2 = 0;
|
||||
pk nm fl1 fl2
|
||||
4543 7503 0 0
|
||||
7373 7518 0 0
|
||||
drop table name, flag2;
|
||||
drop table t1;
|
||||
create table t1 (
|
||||
pk int primary key auto_increment,
|
||||
nm char(255),
|
||||
fl1 tinyint default 0,
|
||||
fl2 int default 0,
|
||||
index idx1(nm, fl1),
|
||||
index idx2(fl2)
|
||||
) engine=myisam;
|
||||
create table name (
|
||||
pk int primary key auto_increment,
|
||||
nm bigint
|
||||
) engine=myisam;
|
||||
create table flag2 (
|
||||
pk int primary key auto_increment,
|
||||
fl2 int
|
||||
) engine=myisam;
|
||||
insert into name(nm) select seq from seq_1_to_10000 order by rand(17);
|
||||
insert into flag2(fl2) select seq mod 10 from seq_1_to_10000 order by rand(19);
|
||||
insert into t1(nm,fl2)
|
||||
select nm, fl2 from name, flag2 where name.pk = flag2.pk;
|
||||
analyze table t1 persistent for all;
|
||||
Table Op Msg_type Msg_text
|
||||
test.t1 analyze status Engine-independent statistics collected
|
||||
test.t1 analyze status Table is already up to date
|
||||
select * from t1
|
||||
where
|
||||
(
|
||||
nm like '3400%' or nm like '3402%' or nm like '3403%' or
|
||||
nm like '3404%' or nm like '3405%' or nm like '3406%' or nm like '3407%' or
|
||||
nm like '3409%' or
|
||||
nm like '3411%' or nm like '3412%' or nm like '3413%' or
|
||||
nm like '3414%' or nm like '3415%' or nm like '3416%' or nm like '3417%' or
|
||||
nm like '3418%' or nm like '3419%' or
|
||||
nm like '3421%' or nm like '3422%' or nm like '3423%' or
|
||||
nm like '3424%' or nm like '3425%' or nm like '3426%' or nm like '3427%' or
|
||||
nm like '3428%' or nm like '3429%' or
|
||||
nm like '3430%' or nm like '3431%' or nm like '3432%' or nm like '3433%' or
|
||||
nm like '3434%' or nm like '3435%' or nm like '3436%' or nm like '3437%' or
|
||||
nm like '3439%' or
|
||||
nm like '3440%' or nm like '3441%' or nm like '3442%' or nm like '3443%' or
|
||||
nm like '3444%' or nm like '3445%' or nm like '3446%' or nm like '3447%' or
|
||||
nm like '3448%'
|
||||
) and fl2 = 0;
|
||||
pk nm fl1 fl2
|
||||
analyze format=json select * from t1
|
||||
where
|
||||
(
|
||||
nm like '3400%' or nm like '3402%' or nm like '3403%' or
|
||||
nm like '3404%' or nm like '3405%' or nm like '3406%' or nm like '3407%' or
|
||||
nm like '3409%' or
|
||||
nm like '3411%' or nm like '3412%' or nm like '3413%' or
|
||||
nm like '3414%' or nm like '3415%' or nm like '3416%' or nm like '3417%' or
|
||||
nm like '3418%' or nm like '3419%' or
|
||||
nm like '3421%' or nm like '3422%' or nm like '3423%' or
|
||||
nm like '3424%' or nm like '3425%' or nm like '3426%' or nm like '3427%' or
|
||||
nm like '3428%' or nm like '3429%' or
|
||||
nm like '3430%' or nm like '3431%' or nm like '3432%' or nm like '3433%' or
|
||||
nm like '3434%' or nm like '3435%' or nm like '3436%' or nm like '3437%' or
|
||||
nm like '3439%' or
|
||||
nm like '3440%' or nm like '3441%' or nm like '3442%' or nm like '3443%' or
|
||||
nm like '3444%' or nm like '3445%' or nm like '3446%' or nm like '3447%' or
|
||||
nm like '3448%'
|
||||
) and fl2 = 0;
|
||||
ANALYZE
|
||||
{
|
||||
"query_optimization": {
|
||||
"r_total_time_ms": "REPLACED"
|
||||
},
|
||||
"query_block": {
|
||||
"select_id": 1,
|
||||
"r_loops": 1,
|
||||
"r_total_time_ms": "REPLACED",
|
||||
"nested_loop": [
|
||||
{
|
||||
"table": {
|
||||
"table_name": "t1",
|
||||
"access_type": "range",
|
||||
"possible_keys": ["idx1", "idx2"],
|
||||
"key": "idx1",
|
||||
"key_length": "256",
|
||||
"used_key_parts": ["nm"],
|
||||
"rowid_filter": {
|
||||
"range": {
|
||||
"key": "idx2",
|
||||
"used_key_parts": ["fl2"]
|
||||
},
|
||||
"rows": 863,
|
||||
"selectivity_pct": 8.63,
|
||||
"r_rows": 1000,
|
||||
"r_lookups": 44,
|
||||
"r_selectivity_pct": 0,
|
||||
"r_buffer_size": "REPLACED",
|
||||
"r_filling_time_ms": "REPLACED"
|
||||
},
|
||||
"r_loops": 1,
|
||||
"rows": 44,
|
||||
"r_rows": 0,
|
||||
"r_table_time_ms": "REPLACED",
|
||||
"r_other_time_ms": "REPLACED",
|
||||
"filtered": 8.630000114,
|
||||
"r_filtered": 100,
|
||||
"index_condition": "t1.nm like '3400%' or t1.nm like '3402%' or t1.nm like '3403%' or t1.nm like '3404%' or t1.nm like '3405%' or t1.nm like '3406%' or t1.nm like '3407%' or t1.nm like '3409%' or t1.nm like '3411%' or t1.nm like '3412%' or t1.nm like '3413%' or t1.nm like '3414%' or t1.nm like '3415%' or t1.nm like '3416%' or t1.nm like '3417%' or t1.nm like '3418%' or t1.nm like '3419%' or t1.nm like '3421%' or t1.nm like '3422%' or t1.nm like '3423%' or t1.nm like '3424%' or t1.nm like '3425%' or t1.nm like '3426%' or t1.nm like '3427%' or t1.nm like '3428%' or t1.nm like '3429%' or t1.nm like '3430%' or t1.nm like '3431%' or t1.nm like '3432%' or t1.nm like '3433%' or t1.nm like '3434%' or t1.nm like '3435%' or t1.nm like '3436%' or t1.nm like '3437%' or t1.nm like '3439%' or t1.nm like '3440%' or t1.nm like '3441%' or t1.nm like '3442%' or t1.nm like '3443%' or t1.nm like '3444%' or t1.nm like '3445%' or t1.nm like '3446%' or t1.nm like '3447%' or t1.nm like '3448%'",
|
||||
"attached_condition": "t1.fl2 = 0"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
create table t0 select * from t1 where nm like '34%';
|
||||
delete from t1 using t1,t0 where t1.nm=t0.nm;
|
||||
analyze format=json select * from t1
|
||||
where
|
||||
(
|
||||
nm like '3400%' or nm like '3402%' or nm like '3403%' or
|
||||
nm like '3404%' or nm like '3405%' or nm like '3406%' or nm like '3407%' or
|
||||
nm like '3409%' or
|
||||
nm like '3411%' or nm like '3412%' or nm like '3413%' or
|
||||
nm like '3414%' or nm like '3415%' or nm like '3416%' or nm like '3417%' or
|
||||
nm like '3418%' or nm like '3419%' or
|
||||
nm like '3421%' or nm like '3422%' or nm like '3423%' or
|
||||
nm like '3424%' or nm like '3425%' or nm like '3426%' or nm like '3427%' or
|
||||
nm like '3428%' or nm like '3429%' or
|
||||
nm like '3430%' or nm like '3431%' or nm like '3432%' or nm like '3433%' or
|
||||
nm like '3434%' or nm like '3435%' or nm like '3436%' or nm like '3437%' or
|
||||
nm like '3439%' or
|
||||
nm like '3440%' or nm like '3441%' or nm like '3442%' or nm like '3443%' or
|
||||
nm like '3444%' or nm like '3445%' or nm like '3446%' or nm like '3447%' or
|
||||
nm like '3448%'
|
||||
) and fl2 = 0;
|
||||
ANALYZE
|
||||
{
|
||||
"query_optimization": {
|
||||
"r_total_time_ms": "REPLACED"
|
||||
},
|
||||
"query_block": {
|
||||
"select_id": 1,
|
||||
"r_loops": 1,
|
||||
"r_total_time_ms": "REPLACED",
|
||||
"nested_loop": [
|
||||
{
|
||||
"table": {
|
||||
"table_name": "t1",
|
||||
"access_type": "range",
|
||||
"possible_keys": ["idx1", "idx2"],
|
||||
"key": "idx1",
|
||||
"key_length": "256",
|
||||
"used_key_parts": ["nm"],
|
||||
"rowid_filter": {
|
||||
"range": {
|
||||
"key": "idx2",
|
||||
"used_key_parts": ["fl2"]
|
||||
},
|
||||
"rows": 853,
|
||||
"selectivity_pct": 8.53,
|
||||
"r_rows": 987,
|
||||
"r_lookups": 0,
|
||||
"r_selectivity_pct": 0,
|
||||
"r_buffer_size": "REPLACED",
|
||||
"r_filling_time_ms": "REPLACED"
|
||||
},
|
||||
"r_loops": 1,
|
||||
"rows": 44,
|
||||
"r_rows": 0,
|
||||
"r_table_time_ms": "REPLACED",
|
||||
"r_other_time_ms": "REPLACED",
|
||||
"filtered": 8.529999733,
|
||||
"r_filtered": 100,
|
||||
"index_condition": "t1.nm like '3400%' or t1.nm like '3402%' or t1.nm like '3403%' or t1.nm like '3404%' or t1.nm like '3405%' or t1.nm like '3406%' or t1.nm like '3407%' or t1.nm like '3409%' or t1.nm like '3411%' or t1.nm like '3412%' or t1.nm like '3413%' or t1.nm like '3414%' or t1.nm like '3415%' or t1.nm like '3416%' or t1.nm like '3417%' or t1.nm like '3418%' or t1.nm like '3419%' or t1.nm like '3421%' or t1.nm like '3422%' or t1.nm like '3423%' or t1.nm like '3424%' or t1.nm like '3425%' or t1.nm like '3426%' or t1.nm like '3427%' or t1.nm like '3428%' or t1.nm like '3429%' or t1.nm like '3430%' or t1.nm like '3431%' or t1.nm like '3432%' or t1.nm like '3433%' or t1.nm like '3434%' or t1.nm like '3435%' or t1.nm like '3436%' or t1.nm like '3437%' or t1.nm like '3439%' or t1.nm like '3440%' or t1.nm like '3441%' or t1.nm like '3442%' or t1.nm like '3443%' or t1.nm like '3444%' or t1.nm like '3445%' or t1.nm like '3446%' or t1.nm like '3447%' or t1.nm like '3448%'",
|
||||
"attached_condition": "t1.fl2 = 0"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
drop table t0;
|
||||
set optimizer_switch='rowid_filter=default';
|
||||
drop table name, flag2;
|
||||
drop table t1;
|
||||
|
@ -1,3 +1,5 @@
|
||||
SET optimizer_switch='rowid_filter=on';
|
||||
|
||||
--echo #
|
||||
--echo # MDEV-22553: Assertion `info->lastpos == (~ (my_off_t) 0)' failed in mi_rkey with rowid_filer=on
|
||||
--echo #
|
||||
@ -1623,3 +1625,405 @@ ALTER TABLE t1 ENABLE KEYS;
|
||||
--echo # Must not crash:
|
||||
SELECT * FROM t1 WHERE ( a BETWEEN 255 AND 270 OR f = 200 ) AND f IN ( 1, 4, 112, 143 ) AND d IN ('Montana', 'South Dakota');
|
||||
DROP TABLE t1;
|
||||
|
||||
|
||||
|
||||
use test;
|
||||
|
||||
--echo #
|
||||
--echo # MDEV-18816: potential range filter for one join table with
|
||||
--echo # impossible WHERE for another
|
||||
--echo #
|
||||
|
||||
create table t1 (
|
||||
pk int not null primary key, c2 varchar(10) , i1 int,key (c2)
|
||||
) engine=myisam;
|
||||
insert into t1 values (1,'a',-5),(2,'a',null);
|
||||
|
||||
create table t2 (
|
||||
pk int, i1 int, c1 varchar(30) , key c1 (c1(30)), key i1 (i1)
|
||||
) engine=myisam;
|
||||
insert into t2 values
|
||||
(1,-5,'a'),(2,null,'a'),(3,null,'a'),(4,null,'a'),(5,5,'a'),(6,null,'a'),
|
||||
(7,4,'a'),(8,55,'a'),(9,null,'a'),(10,null,'a'),(11,null,'a'),(12,-5,'a'),
|
||||
(13,-5,'a'),(14,null,'a'),(15,null,'a'),(16,-5,'a'),(17,-5,'a');
|
||||
|
||||
let $q=
|
||||
select 1
|
||||
from t1
|
||||
left join
|
||||
t2 join t1 as t1_a on t2.i1 = t1_a.pk
|
||||
on t1.c2 = t2.c1
|
||||
where t1_a.pk is null and t1_a.i1 != 3;
|
||||
|
||||
eval $q;
|
||||
eval explain extended $q;
|
||||
|
||||
drop table t1,t2;
|
||||
|
||||
--echo #
|
||||
--echo # MDEV-18640: TABLE::prune_range_rowid_filters: Conditional jump or
|
||||
--echo # move depends on uninitialized value
|
||||
--echo #
|
||||
|
||||
CREATE TABLE t1 (
|
||||
pk INT, i INT, PRIMARY KEY (pk), KEY (pk,i)
|
||||
) ENGINE=MyISAM;
|
||||
INSERT INTO t1 VALUES (1,10), (7,70), (2,20);
|
||||
|
||||
SELECT * FROM t1 WHERE pk < 5;
|
||||
|
||||
DROP TABLE t1;
|
||||
|
||||
--echo #
|
||||
--echo # MDEV-18956: Possible rowid filter for subquery for which
|
||||
--echo # in_to_exists strategy has been chosen
|
||||
--echo #
|
||||
|
||||
CREATE TABLE t1 (pk int) engine=myisam ;
|
||||
INSERT INTO t1 VALUES (1),(2);
|
||||
|
||||
CREATE TABLE t2 (
|
||||
pk int auto_increment PRIMARY KEY,
|
||||
i1 int, i2 int, c2 varchar(1),
|
||||
KEY (i1), KEY (i2)
|
||||
) engine=myisam;
|
||||
|
||||
INSERT INTO t2 VALUES
|
||||
(1,8,6,'t'),(2,5,7,'i'),(3,4,4,'h'),(4,207,38,'d'),(5,183,206,'b'),
|
||||
(6,7,null,'o'),(7,1,2,'j'),(8,17,36,'s'),(9,4,5,'q'),(10,0,6,'l'),
|
||||
(11,1,9,'j'),(12,5,6,'y'),(13,null,0,'i'),(14,7,7,'x'),(15,5,2,'u');
|
||||
|
||||
SELECT * FROM t1 HAVING (7, 9) IN (SELECT t2.i1, t2.i2 FROM t2 WHERE t2.i1 = 3);
|
||||
EXPLAIN EXTENDED
|
||||
SELECT * FROM t1 HAVING (7, 9) IN (SELECT t2.i1, t2.i2 FROM t2 WHERE t2.i1 = 3);
|
||||
|
||||
DROP TABLE t1,t2;
|
||||
|
||||
--echo #
|
||||
--echo # MDEV-19255: rowid range filter built for range condition
|
||||
--echo # that uses in expensive subquery
|
||||
--echo #
|
||||
|
||||
CREATE TABLE t1 (
|
||||
pk1 INT PRIMARY KEY, a1 INT, b1 VARCHAR(1), KEY(b1)
|
||||
) ENGINE=MyISAM;
|
||||
INSERT INTO t1 VALUES
|
||||
(10,0,'z'),(11,3,'j'),(12,8,'f'),(13,8,'p'),(14,6,'w'),(15,0,'c'),(16,1,'j'),
|
||||
(17,1,'f'),(18,5,'v'),(19,3,'f'),(20,2,'q'),(21,8,'y'),(22,0,'a'),(23,9,'w'),
|
||||
(24,3,'e'),(25,1,'b'),(26,9,'r'),(27,2,'k'),(28,5,'c'),(29,3,'k'),(30,9,'b'),
|
||||
(31,8,'j'),(32,1,'t'),(33,8,'n'),(34,3,'z'),(35,0,'u'),(36,3,'a'),(37,3,'g'),
|
||||
(38,1,'f'),(39,6,'p'),(40,6,'m'),(41,6,'t'),(42,7,'i'),(43,4,'h'),(44,3,'d'),
|
||||
(45,2,'b'),(46,1,'o'),(47,2,'j'),(48,6,'s'),(49,5,'q'),(50,6,'l'),(51,9,'j'),
|
||||
(52,6,'y'),(53,0,'i'),(54,7,'x'),(55,2,'u'),(56,6,'t'),(57,4,'b'),(58,5,'m'),
|
||||
(59,4,'x'),(60,8,'x'),(61,6,'v'),(62,8,'m'),(63,4,'j'),(64,8,'z'),(65,2,'a'),
|
||||
(66,9,'i'),(67,4,'g'),(68,8,'h'),(69,1,'p'),(70,8,'a'),(71,0,'x'),(72,2,'s'),
|
||||
(73,6,'k'),(74,0,'m'),(75,6,'e'),(76,9,'y'),(77,7,'d'),(78,7,'w'),(79,6,'y'),
|
||||
(80,9,'s'),(81,9,'x'),(82,6,'l'),(83,9,'f'),(84,8,'x'),(85,1,'p'),(86,7,'y'),
|
||||
(87,6,'p'),(88,1,'g'),(89,3,'c'),(90,5,'h'),(91,3,'p'),(92,2,'b'),(93,1,NULL),
|
||||
(94,3,NULL),(95,2,'y'),(96,7,'s'),(97,7,'x'),(98,6,'i'),(99,9,'t'),(100,5,'j'),
|
||||
(101,0,'u'),(102,7,'r'),(103,2,'x'),(104,8,'e'),(105,8,'i'),(106,5,'q'),
|
||||
(107,8,'z'),(108,3,'k'),(109,65,NULL);
|
||||
|
||||
CREATE TABLE t2 (pk2 INT PRIMARY KEY, a2 INT, b2 VARCHAR(1)) ENGINE=MyISAM;
|
||||
INSERT INTO t2 VALUES (1,1,'x');
|
||||
INSERT INTO t2 SELECT * FROM t1;
|
||||
|
||||
let $q=
|
||||
SELECT * FROM t1 INNER JOIN t2 ON ( pk1 <> pk2 AND pk1 = a2 )
|
||||
WHERE b1 <= ( SELECT MAX(b2) FROM t2 WHERE pk2 <= 1 );
|
||||
|
||||
eval $q;
|
||||
eval EXPLAIN EXTENDED $q;
|
||||
eval EXPLAIN FORMAT=JSON $q;
|
||||
|
||||
DROP TABLE t1,t2;
|
||||
|
||||
--echo #
|
||||
--echo # MDEV-21794: Optimizer flag rowid_filter leads to long query
|
||||
--echo #
|
||||
create table t10(a int);
|
||||
insert into t10 values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9);
|
||||
|
||||
create table t11(a int);
|
||||
insert into t11 select A.a + B.a* 10 + C.a * 100 from t10 A, t10 B, t10 C;
|
||||
|
||||
CREATE TABLE t1 (
|
||||
el_id int(10) unsigned NOT NULL ,
|
||||
el_index blob NOT NULL,
|
||||
el_index_60 varbinary(60) NOT NULL,
|
||||
filler blob,
|
||||
|
||||
PRIMARY KEY (el_id),
|
||||
KEY el_index (el_index(60)),
|
||||
KEY el_index_60 (el_index_60,el_id)
|
||||
);
|
||||
|
||||
insert into t1
|
||||
select
|
||||
A.a+1000*B.a,
|
||||
A.a+1000*B.a + 10000,
|
||||
A.a+1000*B.a + 10000,
|
||||
'filler-data-filler-data'
|
||||
from
|
||||
t11 A, t10 B;
|
||||
analyze table t1 persistent for all;
|
||||
|
||||
--echo # This must not use rowid_filter with key=el_index|el_index_60:
|
||||
explain
|
||||
select * from t1
|
||||
where el_index like '10%' and (el_index_60 like '10%' or el_index_60 like '20%');
|
||||
|
||||
drop table t10, t11, t1;
|
||||
|
||||
|
||||
--echo #
|
||||
--echo # MDEV-22160: SIGSEGV in st_join_table::save_explain_data on SELECT
|
||||
--echo #
|
||||
|
||||
set @save_optimizer_switch= @@optimizer_switch;
|
||||
SET @@optimizer_switch="index_merge_sort_union=OFF";
|
||||
CREATE TABLE t1 (a INT, b INT, INDEX(a), INDEX(b));
|
||||
INSERT INTO t1 VALUES (0,0),(0,0),(1,0),(-1,1), (-2,1), (-2,3), (-3,4), (-2,4),(3,3),(3,4),(3,5),(8,8),(8,9),(1,0),(2,0),(0,0),(0,0);
|
||||
explain
|
||||
SELECT * FROM t1 WHERE a > 0 AND b=0;
|
||||
SELECT * FROM t1 WHERE a > 0 AND b=0;
|
||||
drop table t1;
|
||||
SET @@optimizer_switch=@save_optimizer_switch;
|
||||
|
||||
--echo #
|
||||
--echo # MDEV-21633
|
||||
--echo # Assertion `tmp >= 0' failed in best_access_path with rowid_filter=ON
|
||||
--echo #
|
||||
|
||||
set @save_optimizer_switch= @@optimizer_switch;
|
||||
SET optimizer_switch='rowid_filter=on';
|
||||
|
||||
CREATE TABLE t1 (
|
||||
pk INT AUTO_INCREMENT,
|
||||
a INT,
|
||||
b VARCHAR(8),
|
||||
KEY(a),
|
||||
PRIMARY KEY(pk),
|
||||
KEY (a,pk)
|
||||
) ENGINE=MyISAM;
|
||||
|
||||
INSERT INTO t1 (a,b) VALUES
|
||||
(NULL,'d'),(9,'b'),(2,'x'),(5,'k'),(NULL,'d'),(3,'s'),(5,'k'),(1,'r'),
|
||||
(8,'l'),(3,'z'),(1,'c'),(1,'q'),(NULL,'x'),(NULL,'p'),(NULL,'z'),(7,'a'),
|
||||
(0,'i'),(3,'s'),(NULL,'h'),(4,'p'),(1,'i'),(4,'f'),(1,'c'),(NULL,'a'),
|
||||
(NULL,'x'),(1,'b'),(NULL,'n'),(NULL,'h'),(5,'i'),(6,'e'),(NULL,'i'),
|
||||
(7,'e'),(1,'r'),(NULL,'z'),(1,'i'),(14,'c'),(6,'u'),(3,'b'),(4,'z'),
|
||||
(2,'c'),(70,'d'),(NULL,'p'),(21,'j'),(6,'e'),(5,'c'),(13,'i'),(42,'d'),
|
||||
(80,'s'),(14,'t'),(9,'a'),(0,'2'),(0,NULL),(0,NULL),(0,NULL),(0,''),
|
||||
(0,''),(0,'1'),(0,''),(0,''),(0,''),(0,''),(0,NULL),(0,''),(0,''),(0,''),
|
||||
(0,NULL),(0,''),(0,''),(0,''),(0,''),(0,''),(0,''),(0,NULL),(0,NULL),
|
||||
(0,NULL),(0,''),(0,''),(0,''),(0,''),(0,NULL),(0,''),(0,NULL),(0,NULL),
|
||||
(0,''),(0,''),(0,''),(0,NULL),(0,''),(0,NULL),(0,''),(0,''),(0,''),(0,''),
|
||||
(0,''),(0,''),(0,''),(0,NULL),(0,''),(0,NULL),(0,'');
|
||||
|
||||
CREATE TABLE t2 (c INT) ENGINE=MyISAM;
|
||||
INSERT INTO t2 VALUES (1),(2),(3),(4),(5),(6);
|
||||
|
||||
SELECT * FROM t1 JOIN t2 WHERE a = c AND pk BETWEEN 4 AND 7 AND a BETWEEN 2 AND 12 AND b != 'foo';
|
||||
|
||||
explain SELECT * FROM t1 JOIN t2 WHERE a = c AND pk BETWEEN 4 AND 7 AND a BETWEEN 2 AND 12 AND b != 'foo';
|
||||
|
||||
SET optimizer_switch='rowid_filter=off';
|
||||
|
||||
SELECT * FROM t1 JOIN t2 WHERE a = c AND pk BETWEEN 4 AND 7 AND a BETWEEN 2 AND 12 AND b != 'foo';
|
||||
|
||||
SET @@optimizer_switch=@save_optimizer_switch;
|
||||
|
||||
# Cleanup
|
||||
DROP TABLE t1, t2;
|
||||
|
||||
--echo #
|
||||
--echo # MDEV-28846: Poor performance when rowid filter contains no elements
|
||||
--echo #
|
||||
|
||||
--source include/have_sequence.inc
|
||||
|
||||
create table t1 (
|
||||
pk int primary key auto_increment,
|
||||
nm varchar(32),
|
||||
fl1 tinyint default 0,
|
||||
fl2 tinyint default 0,
|
||||
index idx1(nm, fl1),
|
||||
index idx2(fl2)
|
||||
) engine=myisam;
|
||||
|
||||
create table name (
|
||||
pk int primary key auto_increment,
|
||||
nm bigint
|
||||
) engine=myisam;
|
||||
|
||||
create table flag2 (
|
||||
pk int primary key auto_increment,
|
||||
fl2 tinyint
|
||||
) engine=myisam;
|
||||
|
||||
insert into name(nm) select seq from seq_1_to_1000 order by rand(17);
|
||||
insert into flag2(fl2) select seq mod 2 from seq_1_to_1000 order by rand(19);
|
||||
|
||||
insert into t1(nm,fl2)
|
||||
select nm, fl2 from name, flag2 where name.pk = flag2.pk;
|
||||
|
||||
analyze table t1 persistent for all;
|
||||
|
||||
let $a=
|
||||
`select concat((select nm from t1 where fl2=0 order by RAND(13) limit 1),'%')`;
|
||||
eval select '$a' as a;
|
||||
|
||||
set optimizer_switch='rowid_filter=on';
|
||||
eval
|
||||
explain
|
||||
select * from t1 where nm like '$a' AND fl2 = 0;
|
||||
--source include/analyze-format.inc
|
||||
eval
|
||||
analyze format=json
|
||||
select * from t1 where nm like '$a' AND fl2 = 0;
|
||||
eval
|
||||
select * from t1 where nm like '$a' AND fl2 = 0;
|
||||
|
||||
truncate table name;
|
||||
truncate table flag2;
|
||||
truncate table t1;
|
||||
|
||||
insert into name(nm) select seq from seq_1_to_1000 order by rand(17);
|
||||
insert into flag2(fl2) select seq mod 2 from seq_1_to_1000 order by rand(19);
|
||||
|
||||
insert into t1(nm,fl2)
|
||||
select nm, fl2 from name, flag2 where name.pk = flag2.pk;
|
||||
|
||||
analyze table t1 persistent for all;
|
||||
|
||||
set optimizer_switch='rowid_filter=off';
|
||||
eval
|
||||
explain
|
||||
select * from t1 where nm like '$a' AND fl2 = 0;
|
||||
--source include/analyze-format.inc
|
||||
eval
|
||||
analyze format=json
|
||||
select * from t1 where nm like '$a' AND fl2 = 0;
|
||||
eval
|
||||
select * from t1 where nm like '$a' AND fl2 = 0;
|
||||
|
||||
truncate table name;
|
||||
truncate table flag2;
|
||||
truncate table t1;
|
||||
|
||||
insert into name(nm) select seq from seq_1_to_1000 order by rand(17);
|
||||
insert into flag2(fl2) select seq mod 10 from seq_1_to_1000 order by rand(19);
|
||||
|
||||
insert into t1(nm,fl2)
|
||||
select nm, fl2 from name, flag2 where name.pk = flag2.pk;
|
||||
|
||||
analyze table t1 persistent for all;
|
||||
|
||||
let $a=
|
||||
`select concat((select nm from t1 where fl2=0 order by RAND(13) limit 1),'%')`;
|
||||
eval select '$a' as a;
|
||||
|
||||
set optimizer_switch='rowid_filter=on';
|
||||
eval
|
||||
explain
|
||||
select * from t1 where nm like '$a' AND fl2 = 0;
|
||||
eval
|
||||
select * from t1 where nm like '$a' AND fl2 = 0;
|
||||
|
||||
truncate table name;
|
||||
truncate table flag2;
|
||||
truncate table t1;
|
||||
|
||||
insert into name(nm) select seq from seq_1_to_10000 order by rand(17);
|
||||
insert into flag2(fl2) select seq mod 100 from seq_1_to_10000 order by rand(19);
|
||||
|
||||
insert into t1(nm,fl2)
|
||||
select nm, fl2 from name, flag2 where name.pk = flag2.pk;
|
||||
|
||||
analyze table t1 persistent for all;
|
||||
|
||||
let $a=
|
||||
`select concat(left((select nm from t1 where fl2=0 order by RAND(13) limit 1),2),'%')`;
|
||||
eval select '$a' as a;
|
||||
|
||||
set optimizer_switch='rowid_filter=on';
|
||||
eval
|
||||
explain
|
||||
select * from t1 where nm like '$a' AND fl2 = 0;
|
||||
--source include/analyze-format.inc
|
||||
eval
|
||||
analyze format=json
|
||||
select * from t1 where nm like '$a' AND fl2 = 0;
|
||||
eval
|
||||
select * from t1 where nm like '$a' AND fl2 = 0;
|
||||
|
||||
drop table name, flag2;
|
||||
drop table t1;
|
||||
|
||||
# This test shows that if the container is empty there are no lookups into it
|
||||
|
||||
create table t1 (
|
||||
pk int primary key auto_increment,
|
||||
nm char(255),
|
||||
fl1 tinyint default 0,
|
||||
fl2 int default 0,
|
||||
index idx1(nm, fl1),
|
||||
index idx2(fl2)
|
||||
) engine=myisam;
|
||||
|
||||
create table name (
|
||||
pk int primary key auto_increment,
|
||||
nm bigint
|
||||
) engine=myisam;
|
||||
|
||||
create table flag2 (
|
||||
pk int primary key auto_increment,
|
||||
fl2 int
|
||||
) engine=myisam;
|
||||
|
||||
insert into name(nm) select seq from seq_1_to_10000 order by rand(17);
|
||||
insert into flag2(fl2) select seq mod 10 from seq_1_to_10000 order by rand(19);
|
||||
|
||||
insert into t1(nm,fl2)
|
||||
select nm, fl2 from name, flag2 where name.pk = flag2.pk;
|
||||
|
||||
analyze table t1 persistent for all;
|
||||
|
||||
let $q=
|
||||
select * from t1
|
||||
where
|
||||
(
|
||||
nm like '3400%' or nm like '3402%' or nm like '3403%' or
|
||||
nm like '3404%' or nm like '3405%' or nm like '3406%' or nm like '3407%' or
|
||||
nm like '3409%' or
|
||||
nm like '3411%' or nm like '3412%' or nm like '3413%' or
|
||||
nm like '3414%' or nm like '3415%' or nm like '3416%' or nm like '3417%' or
|
||||
nm like '3418%' or nm like '3419%' or
|
||||
nm like '3421%' or nm like '3422%' or nm like '3423%' or
|
||||
nm like '3424%' or nm like '3425%' or nm like '3426%' or nm like '3427%' or
|
||||
nm like '3428%' or nm like '3429%' or
|
||||
nm like '3430%' or nm like '3431%' or nm like '3432%' or nm like '3433%' or
|
||||
nm like '3434%' or nm like '3435%' or nm like '3436%' or nm like '3437%' or
|
||||
nm like '3439%' or
|
||||
nm like '3440%' or nm like '3441%' or nm like '3442%' or nm like '3443%' or
|
||||
nm like '3444%' or nm like '3445%' or nm like '3446%' or nm like '3447%' or
|
||||
nm like '3448%'
|
||||
) and fl2 = 0;
|
||||
|
||||
eval $q;
|
||||
--source include/analyze-format.inc
|
||||
eval analyze format=json $q;
|
||||
|
||||
create table t0 select * from t1 where nm like '34%';
|
||||
delete from t1 using t1,t0 where t1.nm=t0.nm;
|
||||
--source include/analyze-format.inc
|
||||
eval analyze format=json $q;
|
||||
|
||||
drop table t0;
|
||||
|
||||
set optimizer_switch='rowid_filter=default';
|
||||
|
||||
drop table name, flag2;
|
||||
drop table t1;
|
||||
|
@ -409,7 +409,7 @@ WHERE (pk BETWEEN 4 AND 5 OR pk < 2) AND c1 < 240
|
||||
ORDER BY c1
|
||||
LIMIT 1;
|
||||
id select_type table type possible_keys key key_len ref rows Extra
|
||||
1 SIMPLE t1 range PRIMARY,k1 k1 5 NULL 4 Using index condition; Using where
|
||||
1 SIMPLE t1 range|filter PRIMARY,k1 k1|PRIMARY 5|4 NULL 4 (38%) Using index condition; Using where; Using rowid filter
|
||||
DROP TABLE t1;
|
||||
#
|
||||
#
|
||||
|
@ -92,7 +92,7 @@ my_bool init_dynamic_array2(PSI_memory_key psi_key, DYNAMIC_ARRAY *array,
|
||||
my_bool insert_dynamic(DYNAMIC_ARRAY *array, const void * element)
|
||||
{
|
||||
void *buffer;
|
||||
if (array->elements == array->max_element)
|
||||
if (unlikely(array->elements == array->max_element))
|
||||
{ /* Call only when necessary */
|
||||
if (!(buffer=alloc_dynamic(array)))
|
||||
return TRUE;
|
||||
@ -102,7 +102,42 @@ my_bool insert_dynamic(DYNAMIC_ARRAY *array, const void * element)
|
||||
buffer=array->buffer+(array->elements * array->size_of_element);
|
||||
array->elements++;
|
||||
}
|
||||
memcpy(buffer,element,(size_t) array->size_of_element);
|
||||
memcpy(buffer, element, array->size_of_element);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
/* Fast version of appending to dynamic array */
|
||||
|
||||
void init_append_dynamic(DYNAMIC_ARRAY_APPEND *append,
|
||||
DYNAMIC_ARRAY *array)
|
||||
{
|
||||
append->array= array;
|
||||
append->pos= array->buffer + array->elements * array->size_of_element;
|
||||
append->end= array->buffer + array->max_element * array->size_of_element;
|
||||
}
|
||||
|
||||
|
||||
my_bool append_dynamic(DYNAMIC_ARRAY_APPEND *append,
|
||||
const void *element)
|
||||
{
|
||||
DYNAMIC_ARRAY *array= append->array;
|
||||
size_t size_of_element= array->size_of_element;
|
||||
if (unlikely(append->pos == append->end))
|
||||
{
|
||||
void *buffer;
|
||||
if (!(buffer=alloc_dynamic(array)))
|
||||
return TRUE;
|
||||
append->pos= (uchar*)buffer + size_of_element;
|
||||
append->end= array->buffer + array->max_element * size_of_element;
|
||||
memcpy(buffer, element, size_of_element);
|
||||
}
|
||||
else
|
||||
{
|
||||
array->elements++;
|
||||
memcpy(append->pos, element, size_of_element);
|
||||
append->pos+= size_of_element;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
@ -281,7 +316,7 @@ my_bool allocate_dynamic(DYNAMIC_ARRAY *array, size_t max_elements)
|
||||
|
||||
void get_dynamic(DYNAMIC_ARRAY *array, void *element, size_t idx)
|
||||
{
|
||||
if (idx >= array->elements)
|
||||
if (unlikely(idx >= array->elements))
|
||||
{
|
||||
DBUG_PRINT("warning",("To big array idx: %d, array size is %d",
|
||||
idx,array->elements));
|
||||
@ -306,7 +341,7 @@ void delete_dynamic(DYNAMIC_ARRAY *array)
|
||||
/*
|
||||
Just mark as empty if we are using a static buffer
|
||||
*/
|
||||
if (!(array->malloc_flags & MY_INIT_BUFFER_USED) && array->buffer)
|
||||
if (array->buffer && !(array->malloc_flags & MY_INIT_BUFFER_USED))
|
||||
my_free(array->buffer);
|
||||
|
||||
array->buffer= 0;
|
||||
|
@ -6964,8 +6964,7 @@ check_result_t handler_rowid_filter_check(void *h_arg)
|
||||
|
||||
extern "C" int handler_rowid_filter_is_active(void *h_arg)
|
||||
{
|
||||
if (!h_arg)
|
||||
return false;
|
||||
DBUG_ASSERT(h_arg);
|
||||
handler *h= (handler*) h_arg;
|
||||
return h->rowid_filter_is_active;
|
||||
}
|
||||
|
@ -4665,10 +4665,14 @@ public:
|
||||
DBUG_ASSERT(pushed_rowid_filter != NULL &&
|
||||
save_pushed_rowid_filter == NULL);
|
||||
save_pushed_rowid_filter= pushed_rowid_filter;
|
||||
if (rowid_filter_is_active)
|
||||
save_rowid_filter_is_active= rowid_filter_is_active;
|
||||
pushed_rowid_filter= NULL;
|
||||
|
||||
if (rowid_filter_is_active)
|
||||
{
|
||||
rowid_filter_is_active= false;
|
||||
rowid_filter_changed();
|
||||
}
|
||||
}
|
||||
|
||||
virtual void enable_pushed_rowid_filter()
|
||||
@ -4676,12 +4680,17 @@ public:
|
||||
DBUG_ASSERT(save_pushed_rowid_filter != NULL &&
|
||||
pushed_rowid_filter == NULL);
|
||||
pushed_rowid_filter= save_pushed_rowid_filter;
|
||||
if (save_rowid_filter_is_active)
|
||||
rowid_filter_is_active= true;
|
||||
save_pushed_rowid_filter= NULL;
|
||||
if (save_rowid_filter_is_active)
|
||||
{
|
||||
rowid_filter_is_active= true;
|
||||
rowid_filter_changed();
|
||||
}
|
||||
}
|
||||
|
||||
virtual bool rowid_filter_push(Rowid_filter *rowid_filter) { return true; }
|
||||
/* Signal that rowid filter may have been enabled / disabled */
|
||||
virtual void rowid_filter_changed() {}
|
||||
|
||||
/* Needed for partition / spider */
|
||||
virtual TABLE_LIST *get_next_global_for_child() { return NULL; }
|
||||
|
@ -86,6 +86,13 @@
|
||||
/* Rowid copy is usually just a single memcpy of a short string */
|
||||
#define DEFAULT_ROWID_COPY_COST 0.000002653
|
||||
|
||||
/*
|
||||
Cost modifiers rowid_filter. These takes into account the overhead of
|
||||
using and calling Rowid_filter_sorted_array::check() from the engine
|
||||
*/
|
||||
#define ROWID_FILTER_PER_CHECK_MODIFIER 4 /* times key_copy_cost */
|
||||
#define ROWID_FILTER_PER_ELEMENT_MODIFIER 3 /* times rowid_compare_cost */
|
||||
|
||||
/*
|
||||
Average disk seek time on a hard disk is 8-10 ms, which is also
|
||||
about the time to read a IO_SIZE (8192) block.
|
||||
|
@ -19,6 +19,7 @@
|
||||
#include "sql_class.h"
|
||||
#include "opt_range.h"
|
||||
#include "rowid_filter.h"
|
||||
#include "optimizer_defaults.h"
|
||||
#include "sql_select.h"
|
||||
#include "opt_trace.h"
|
||||
|
||||
@ -127,8 +128,10 @@ void Range_rowid_filter_cost_info::init(Rowid_filter_container_type cont_type,
|
||||
cost_of_building_range_filter= build_cost(container_type);
|
||||
|
||||
where_cost= tab->in_use->variables.optimizer_where_cost;
|
||||
base_lookup_cost= tab->file->ROW_NEXT_FIND_COST;
|
||||
rowid_compare_cost= tab->file->ROWID_COMPARE_COST;
|
||||
base_lookup_cost= (ROWID_FILTER_PER_CHECK_MODIFIER *
|
||||
tab->file->KEY_COPY_COST);
|
||||
rowid_compare_cost= (ROWID_FILTER_PER_ELEMENT_MODIFIER *
|
||||
tab->file->ROWID_COMPARE_COST);
|
||||
selectivity= est_elements/((double) table->stat_records());
|
||||
gain= avg_access_and_eval_gain_per_row(container_type,
|
||||
tab->file->ROW_LOOKUP_COST);
|
||||
@ -589,41 +592,40 @@ bool Range_rowid_filter::fill()
|
||||
file->pushed_idx_cond_keyno= MAX_KEY;
|
||||
file->in_range_check_pushed_down= false;
|
||||
|
||||
/* We're going to just read rowids / primary keys */
|
||||
/* We're going to just read rowids / clustered primary keys */
|
||||
table->prepare_for_position();
|
||||
|
||||
table->file->ha_start_keyread(quick->index);
|
||||
file->ha_start_keyread(quick->index);
|
||||
|
||||
if (quick->init() || quick->reset())
|
||||
rc= 1;
|
||||
goto end;
|
||||
|
||||
while (!rc)
|
||||
{
|
||||
rc= quick->get_next();
|
||||
if (thd->killed)
|
||||
rc= 1;
|
||||
if (!rc)
|
||||
while (!(rc= quick->get_next()))
|
||||
{
|
||||
file->position(quick->record);
|
||||
if (container->add(NULL, (char*) file->ref))
|
||||
if (container->add(NULL, (char*) file->ref) || thd->killed)
|
||||
{
|
||||
rc= 1;
|
||||
else
|
||||
tracker->increment_container_elements_count();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
end:
|
||||
quick->range_end();
|
||||
table->file->ha_end_keyread();
|
||||
file->ha_end_keyread();
|
||||
|
||||
table->status= table_status_save;
|
||||
file->pushed_idx_cond= pushed_idx_cond_save;
|
||||
file->pushed_idx_cond_keyno= pushed_idx_cond_keyno_save;
|
||||
file->in_range_check_pushed_down= in_range_check_pushed_down_save;
|
||||
tracker->report_container_buff_size(table->file->ref_length);
|
||||
|
||||
tracker->set_container_elements_count(container->elements());
|
||||
tracker->report_container_buff_size(file->ref_length);
|
||||
|
||||
if (rc != HA_ERR_END_OF_FILE)
|
||||
return 1;
|
||||
table->file->rowid_filter_is_active= true;
|
||||
container->sort(refpos_order_cmp, (void *) file);
|
||||
file->rowid_filter_is_active= container->elements() != 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -647,18 +649,13 @@ bool Range_rowid_filter::fill()
|
||||
|
||||
bool Rowid_filter_sorted_array::check(void *ctxt, char *elem)
|
||||
{
|
||||
TABLE *table= (TABLE *) ctxt;
|
||||
if (!is_checked)
|
||||
{
|
||||
refpos_container.sort(refpos_order_cmp, (void *) (table->file));
|
||||
is_checked= true;
|
||||
}
|
||||
handler *file= ((TABLE *) ctxt)->file;
|
||||
int l= 0;
|
||||
int r= refpos_container.elements()-1;
|
||||
while (l <= r)
|
||||
{
|
||||
int m= (l + r) / 2;
|
||||
int cmp= refpos_order_cmp((void *) (table->file),
|
||||
int cmp= refpos_order_cmp((void *) file,
|
||||
refpos_container.get_pos(m), elem);
|
||||
if (cmp == 0)
|
||||
return true;
|
||||
@ -675,14 +672,6 @@ Range_rowid_filter::~Range_rowid_filter()
|
||||
{
|
||||
delete container;
|
||||
container= 0;
|
||||
if (select)
|
||||
{
|
||||
if (select->quick)
|
||||
{
|
||||
delete select->quick;
|
||||
select->quick= 0;
|
||||
}
|
||||
delete select;
|
||||
select= 0;
|
||||
}
|
||||
}
|
||||
|
@ -186,7 +186,10 @@ public:
|
||||
virtual bool check(void *ctxt, char *elem) = 0;
|
||||
|
||||
/* True if the container does not contain any element */
|
||||
virtual bool is_empty() = 0;
|
||||
bool is_empty() { return elements() == 0; }
|
||||
virtual uint elements() = 0;
|
||||
virtual void sort (int (*cmp) (void *ctxt, const void *el1, const void *el2),
|
||||
void *cmp_arg) = 0;
|
||||
|
||||
virtual ~Rowid_filter_container() {}
|
||||
};
|
||||
@ -264,7 +267,7 @@ public:
|
||||
|
||||
bool build() { return fill(); }
|
||||
|
||||
bool check(char *elem)
|
||||
bool check(char *elem) override
|
||||
{
|
||||
if (container->is_empty())
|
||||
return false;
|
||||
@ -296,52 +299,49 @@ class Refpos_container_sorted_array : public Sql_alloc
|
||||
/* Number of bytes allocated for an element */
|
||||
uint elem_size;
|
||||
/* The dynamic array over which the wrapper is built */
|
||||
Dynamic_array<char> *array;
|
||||
DYNAMIC_ARRAY array;
|
||||
DYNAMIC_ARRAY_APPEND append;
|
||||
|
||||
public:
|
||||
|
||||
Refpos_container_sorted_array(uint max_elems, uint elem_sz)
|
||||
: max_elements(max_elems), elem_size(elem_sz), array(0) {}
|
||||
:max_elements(max_elems), elem_size(elem_sz)
|
||||
{
|
||||
bzero(&array, sizeof(array));
|
||||
}
|
||||
|
||||
~Refpos_container_sorted_array()
|
||||
{
|
||||
delete array;
|
||||
array= 0;
|
||||
delete_dynamic(&array);
|
||||
}
|
||||
|
||||
bool alloc()
|
||||
{
|
||||
array= new Dynamic_array<char> (PSI_INSTRUMENT_MEM,
|
||||
elem_size * max_elements,
|
||||
elem_size * max_elements/sizeof(char) + 1);
|
||||
return array == NULL;
|
||||
/* This can never fail as things will be allocated on demand */
|
||||
init_dynamic_array2(PSI_INSTRUMENT_MEM, &array, elem_size, 0,
|
||||
max_elements, 512, MYF(0));
|
||||
init_append_dynamic(&append, &array);
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool add(char *elem)
|
||||
bool add(const char *elem)
|
||||
{
|
||||
for (uint i= 0; i < elem_size; i++)
|
||||
{
|
||||
if (array->append(elem[i]))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
return append_dynamic(&append, elem);
|
||||
}
|
||||
|
||||
char *get_pos(uint n)
|
||||
inline uchar *get_pos(uint n) const
|
||||
{
|
||||
return array->get_pos(n * elem_size);
|
||||
return dynamic_array_ptr(&array, n);
|
||||
}
|
||||
|
||||
uint elements() { return (uint) (array->elements() / elem_size); }
|
||||
inline uint elements() const { return (uint) array.elements; }
|
||||
|
||||
void sort (int (*cmp) (void *ctxt, const void *el1, const void *el2),
|
||||
void *cmp_arg)
|
||||
{
|
||||
my_qsort2(array->front(), array->elements()/elem_size,
|
||||
my_qsort2(array.buffer, array.elements,
|
||||
elem_size, (qsort2_cmp) cmp, cmp_arg);
|
||||
}
|
||||
|
||||
bool is_empty() { return elements() == 0; }
|
||||
};
|
||||
|
||||
|
||||
@ -356,23 +356,29 @@ class Rowid_filter_sorted_array: public Rowid_filter_container
|
||||
{
|
||||
/* The dynamic array to store rowids / primary keys */
|
||||
Refpos_container_sorted_array refpos_container;
|
||||
/* Initially false, becomes true after the first call of (check() */
|
||||
bool is_checked;
|
||||
|
||||
public:
|
||||
Rowid_filter_sorted_array(uint elems, uint elem_size)
|
||||
: refpos_container(elems, elem_size), is_checked(false) {}
|
||||
: refpos_container(elems, elem_size) {}
|
||||
|
||||
Rowid_filter_container_type get_type()
|
||||
Rowid_filter_container_type get_type() override
|
||||
{ return SORTED_ARRAY_CONTAINER; }
|
||||
|
||||
bool alloc() { return refpos_container.alloc(); }
|
||||
bool alloc() override { return refpos_container.alloc(); }
|
||||
|
||||
bool add(void *ctxt, char *elem) { return refpos_container.add(elem); }
|
||||
bool add(void *ctxt, char *elem) override
|
||||
{ return refpos_container.add(elem); }
|
||||
|
||||
bool check(void *ctxt, char *elem);
|
||||
bool check(void *ctxt, char *elem) override;
|
||||
|
||||
uint elements() override { return refpos_container.elements(); }
|
||||
|
||||
void sort (int (*cmp) (void *ctxt, const void *el1, const void *el2),
|
||||
void *cmp_arg)
|
||||
{
|
||||
return refpos_container.sort(cmp, cmp_arg);
|
||||
}
|
||||
|
||||
bool is_empty() { return refpos_container.is_empty(); }
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -414,7 +414,8 @@ public:
|
||||
n_positive_checks++;
|
||||
}
|
||||
|
||||
inline void increment_container_elements_count() { container_elements++; }
|
||||
inline void set_container_elements_count(uint elements)
|
||||
{ container_elements= elements; }
|
||||
|
||||
uint get_container_elements() const { return container_elements; }
|
||||
|
||||
|
@ -170,10 +170,9 @@ static double get_merge_buffers_cost(THD *thd, uint *buff_elems, uint elem_size,
|
||||
|
||||
size_t n_buffers= last - first + 1;
|
||||
|
||||
/* Using log2(n)=log(n)/log(2) formula */
|
||||
return (2*((double)total_buf_elems*elem_size) / IO_SIZE *
|
||||
default_optimizer_costs.disk_read_cost +
|
||||
total_buf_elems*log((double) n_buffers) * compare_factor / M_LN2);
|
||||
total_buf_elems*log2((double) n_buffers) * compare_factor);
|
||||
}
|
||||
|
||||
|
||||
|
@ -4040,7 +4040,8 @@ row_search_idx_cond_check(
|
||||
ut_ad(rec_offs_validate(rec, prebuilt->index, offsets));
|
||||
|
||||
if (!prebuilt->idx_cond) {
|
||||
if (!handler_rowid_filter_is_active(prebuilt->pk_filter)) {
|
||||
if (!prebuilt->pk_filter ||
|
||||
!handler_rowid_filter_is_active(prebuilt->pk_filter)) {
|
||||
return(CHECK_POS);
|
||||
}
|
||||
} else {
|
||||
@ -4082,7 +4083,8 @@ row_search_idx_cond_check(
|
||||
|
||||
switch (result) {
|
||||
case CHECK_POS:
|
||||
if (handler_rowid_filter_is_active(prebuilt->pk_filter)) {
|
||||
if (prebuilt->pk_filter &&
|
||||
handler_rowid_filter_is_active(prebuilt->pk_filter)) {
|
||||
ut_ad(!prebuilt->index->is_primary());
|
||||
if (prebuilt->clust_index_was_generated) {
|
||||
ulint len;
|
||||
|
@ -1094,8 +1094,9 @@ ulong ha_maria::index_flags(uint inx, uint part, bool all_parts) const
|
||||
}
|
||||
else
|
||||
{
|
||||
flags= HA_READ_NEXT | HA_READ_PREV | HA_READ_RANGE |
|
||||
HA_READ_ORDER | HA_KEYREAD_ONLY | HA_DO_INDEX_COND_PUSHDOWN;
|
||||
flags= (HA_READ_NEXT | HA_READ_PREV | HA_READ_RANGE |
|
||||
HA_READ_ORDER | HA_KEYREAD_ONLY | HA_DO_INDEX_COND_PUSHDOWN |
|
||||
HA_DO_RANGE_FILTER_PUSHDOWN);
|
||||
}
|
||||
return flags;
|
||||
}
|
||||
@ -2535,10 +2536,12 @@ int ha_maria::index_read_idx_map(uchar * buf, uint index, const uchar * key,
|
||||
end_range= NULL;
|
||||
if (index == pushed_idx_cond_keyno)
|
||||
ma_set_index_cond_func(file, handler_index_cond_check, this);
|
||||
if (pushed_rowid_filter && handler_rowid_filter_is_active(this))
|
||||
ma_set_rowid_filter_func(file, handler_rowid_filter_check, this);
|
||||
|
||||
error= maria_rkey(file, buf, index, key, keypart_map, find_flag);
|
||||
|
||||
ma_set_index_cond_func(file, NULL, 0);
|
||||
ma_reset_index_filter_functions(file);
|
||||
return error;
|
||||
}
|
||||
|
||||
@ -2615,15 +2618,19 @@ int ha_maria::index_init(uint idx, bool sorted)
|
||||
active_index= idx;
|
||||
if (pushed_idx_cond_keyno == idx)
|
||||
ma_set_index_cond_func(file, handler_index_cond_check, this);
|
||||
if (pushed_rowid_filter && handler_rowid_filter_is_active(this))
|
||||
ma_set_rowid_filter_func(file, handler_rowid_filter_check, this);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int ha_maria::index_end()
|
||||
{
|
||||
/*
|
||||
in_range_check_pushed_down and index_id_cond_keyno are reset in
|
||||
handler::cancel_pushed_idx_cond()
|
||||
*/
|
||||
active_index=MAX_KEY;
|
||||
ma_set_index_cond_func(file, NULL, 0);
|
||||
in_range_check_pushed_down= FALSE;
|
||||
ma_reset_index_filter_functions(file);
|
||||
ds_mrr.dsmrr_close();
|
||||
return 0;
|
||||
}
|
||||
@ -2811,7 +2818,7 @@ int ha_maria::extra(enum ha_extra_function operation)
|
||||
|
||||
int ha_maria::reset(void)
|
||||
{
|
||||
ma_set_index_cond_func(file, NULL, 0);
|
||||
ma_reset_index_filter_functions(file);
|
||||
ds_mrr.dsmrr_close();
|
||||
if (file->trn)
|
||||
{
|
||||
@ -3871,8 +3878,6 @@ bool ha_maria::is_changed() const
|
||||
|
||||
static void aria_update_optimizer_costs(OPTIMIZER_COSTS *costs)
|
||||
{
|
||||
costs->rowid_copy_cost= 0.000001; // Just a short memcopy
|
||||
costs->rowid_cmp_cost= 0.000001; // Just a short memcmp
|
||||
}
|
||||
|
||||
|
||||
@ -4269,6 +4274,26 @@ Item *ha_maria::idx_cond_push(uint keyno_arg, Item* idx_cond_arg)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bool ha_maria::rowid_filter_push(Rowid_filter* rowid_filter)
|
||||
{
|
||||
/* This will be used in index_init() */
|
||||
pushed_rowid_filter= rowid_filter;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/* Enable / disable rowid filter depending if it's active or not */
|
||||
|
||||
void ha_maria::rowid_filter_changed()
|
||||
{
|
||||
if (pushed_rowid_filter && handler_rowid_filter_is_active(this))
|
||||
ma_set_rowid_filter_func(file, handler_rowid_filter_check, this);
|
||||
else
|
||||
ma_set_rowid_filter_func(file, NULL, this);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
Find record by unique constrain (used in temporary tables)
|
||||
|
||||
|
@ -184,6 +184,8 @@ public:
|
||||
|
||||
/* Index condition pushdown implementation */
|
||||
Item *idx_cond_push(uint keyno, Item* idx_cond) override final;
|
||||
bool rowid_filter_push(Rowid_filter* rowid_filter) override;
|
||||
void rowid_filter_changed() override;
|
||||
|
||||
int find_unique_row(uchar *record, uint unique_idx) override final;
|
||||
|
||||
|
@ -510,8 +510,17 @@ void ma_set_index_cond_func(MARIA_HA *info, index_cond_func_t func,
|
||||
{
|
||||
info->index_cond_func= func;
|
||||
info->index_cond_func_arg= func_arg;
|
||||
info->has_cond_pushdown= (info->index_cond_func || info->rowid_filter_func);
|
||||
}
|
||||
|
||||
void ma_set_rowid_filter_func(MARIA_HA *info,
|
||||
rowid_filter_func_t check_func,
|
||||
void *func_arg)
|
||||
{
|
||||
info->rowid_filter_func= check_func;
|
||||
info->rowid_filter_func_arg= func_arg;
|
||||
info->has_cond_pushdown= (info->index_cond_func || info->rowid_filter_func);
|
||||
}
|
||||
|
||||
/*
|
||||
Start/Stop Inserting Duplicates Into a Table, WL#1648.
|
||||
|
@ -20,14 +20,6 @@
|
||||
#include <sys/stat.h>
|
||||
#endif
|
||||
|
||||
/* Get position to last record */
|
||||
|
||||
MARIA_RECORD_POS maria_position(MARIA_HA *info)
|
||||
{
|
||||
return info->cur_row.lastpos;
|
||||
}
|
||||
|
||||
|
||||
uint maria_max_key_length()
|
||||
{
|
||||
uint tmp= (_ma_max_key_length() - 8 - HA_MAX_KEY_SEG*3);
|
||||
|
@ -678,21 +678,43 @@ int _ma_read_key_record(MARIA_HA *info, uchar *buf, MARIA_RECORD_POS filepos)
|
||||
CHECK_OUT_OF_RANGE to indicate that we don't have any active row.
|
||||
*/
|
||||
|
||||
check_result_t ma_check_index_cond(register MARIA_HA *info, uint keynr,
|
||||
check_result_t ma_check_index_cond_real(register MARIA_HA *info, uint keynr,
|
||||
uchar *record)
|
||||
{
|
||||
check_result_t res= CHECK_POS;
|
||||
if (info->index_cond_func)
|
||||
{
|
||||
DBUG_ASSERT(info->index_cond_func || info->rowid_filter_func);
|
||||
|
||||
if (_ma_put_key_in_record(info, keynr, FALSE, record))
|
||||
{
|
||||
/* Impossible case; Can only happen if bug in code */
|
||||
_ma_print_error(info, HA_ERR_CRASHED, 0);
|
||||
info->cur_row.lastpos= HA_OFFSET_ERROR; /* No active record */
|
||||
my_errno= HA_ERR_CRASHED;
|
||||
res= CHECK_ERROR;
|
||||
return CHECK_ERROR;
|
||||
}
|
||||
else if ((res= info->index_cond_func(info->index_cond_func_arg)) ==
|
||||
|
||||
if (info->index_cond_func)
|
||||
{
|
||||
if ((res= info->index_cond_func(info->index_cond_func_arg)) ==
|
||||
CHECK_OUT_OF_RANGE)
|
||||
{
|
||||
/* We got beyond the end of scanned range */
|
||||
info->cur_row.lastpos= HA_OFFSET_ERROR; /* No active record */
|
||||
my_errno= HA_ERR_END_OF_FILE;
|
||||
return res;
|
||||
}
|
||||
/*
|
||||
If we got an error, out-of-range condition, or ICP condition computed to
|
||||
FALSE - we don't need to check the Rowid Filter.
|
||||
*/
|
||||
if (res != CHECK_POS)
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Check the Rowid Filter, if present */
|
||||
if (info->rowid_filter_func)
|
||||
{
|
||||
if ((res= info->rowid_filter_func(info->rowid_filter_func_arg)) ==
|
||||
CHECK_OUT_OF_RANGE)
|
||||
{
|
||||
/* We got beyond the end of scanned range */
|
||||
|
@ -120,6 +120,7 @@ int maria_rkey(MARIA_HA *info, uchar *buf, int inx, const uchar *key_data,
|
||||
|
||||
/* The key references a concurrently inserted record. */
|
||||
if (search_flag == HA_READ_KEY_EXACT &&
|
||||
(keyinfo->flag & HA_NOSAME) &&
|
||||
last_used_keyseg == keyinfo->seg + keyinfo->keysegs)
|
||||
{
|
||||
/* Simply ignore the key if it matches exactly. (Bug #29838) */
|
||||
|
@ -213,7 +213,6 @@ extern int maria_rsame_with_pos(MARIA_HA *file, uchar *record,
|
||||
extern int maria_update(MARIA_HA *file, const uchar *old,
|
||||
const uchar *new_record);
|
||||
extern int maria_write(MARIA_HA *file, const uchar *buff);
|
||||
extern MARIA_RECORD_POS maria_position(MARIA_HA *file);
|
||||
extern int maria_status(MARIA_HA *info, MARIA_INFO *x, uint flag);
|
||||
extern int maria_lock_database(MARIA_HA *file, int lock_type);
|
||||
extern int maria_delete_table(const char *name);
|
||||
@ -1011,6 +1010,7 @@ struct st_maria_handler
|
||||
my_bool switched_transactional;
|
||||
/* If transaction will autocommit */
|
||||
my_bool autocommit;
|
||||
my_bool has_cond_pushdown;
|
||||
#ifdef _WIN32
|
||||
my_bool owned_by_merge; /* This Maria table is part of a merge union */
|
||||
#endif
|
||||
@ -1022,6 +1022,8 @@ struct st_maria_handler
|
||||
my_bool create_unique_index_by_sort;
|
||||
index_cond_func_t index_cond_func; /* Index condition function */
|
||||
void *index_cond_func_arg; /* parameter for the func */
|
||||
rowid_filter_func_t rowid_filter_func; /* rowid filter check function */
|
||||
void *rowid_filter_func_arg; /* parameter for the func */
|
||||
};
|
||||
|
||||
/* Table options for the Aria and S3 storage engine */
|
||||
@ -1347,7 +1349,11 @@ extern int _ma_read_rnd_no_record(MARIA_HA *info, uchar *buf,
|
||||
MARIA_RECORD_POS filepos,
|
||||
my_bool skip_deleted_blocks);
|
||||
my_off_t _ma_no_keypos_to_recpos(MARIA_SHARE *share, my_off_t pos);
|
||||
|
||||
/* Get position to last record */
|
||||
static inline MARIA_RECORD_POS maria_position(MARIA_HA *info)
|
||||
{
|
||||
return info->cur_row.lastpos;
|
||||
}
|
||||
extern my_bool _ma_ck_write(MARIA_HA *info, MARIA_KEY *key);
|
||||
extern my_bool _ma_enlarge_root(MARIA_HA *info, MARIA_KEY *key,
|
||||
MARIA_RECORD_POS *root);
|
||||
@ -1734,7 +1740,25 @@ extern my_bool maria_flush_log_for_page_none(PAGECACHE_IO_HOOK_ARGS *args);
|
||||
extern PAGECACHE *maria_log_pagecache;
|
||||
extern void ma_set_index_cond_func(MARIA_HA *info, index_cond_func_t func,
|
||||
void *func_arg);
|
||||
check_result_t ma_check_index_cond(MARIA_HA *info, uint keynr, uchar *record);
|
||||
extern void ma_set_rowid_filter_func(MARIA_HA *info,
|
||||
rowid_filter_func_t check_func,
|
||||
void *func_arg);
|
||||
static inline void ma_reset_index_filter_functions(MARIA_HA *info)
|
||||
{
|
||||
info->index_cond_func= NULL;
|
||||
info->rowid_filter_func= NULL;
|
||||
info->has_cond_pushdown= 0;
|
||||
}
|
||||
check_result_t ma_check_index_cond_real(MARIA_HA *info, uint keynr,
|
||||
uchar *record);
|
||||
static inline check_result_t ma_check_index_cond(MARIA_HA *info, uint keynr,
|
||||
uchar *record)
|
||||
{
|
||||
if (!info->has_cond_pushdown)
|
||||
return CHECK_POS;
|
||||
return ma_check_index_cond_real(info, keynr, record);
|
||||
}
|
||||
|
||||
|
||||
extern my_bool ma_yield_and_check_if_killed(MARIA_HA *info, int inx);
|
||||
extern my_bool ma_killed_standalone(MARIA_HA *);
|
||||
|
@ -1971,9 +1971,8 @@ int ha_myisam::index_init(uint idx, bool sorted)
|
||||
active_index=idx;
|
||||
if (pushed_idx_cond_keyno == idx)
|
||||
mi_set_index_cond_func(file, handler_index_cond_check, this);
|
||||
if (pushed_rowid_filter)
|
||||
mi_set_rowid_filter_func(file, handler_rowid_filter_check,
|
||||
handler_rowid_filter_is_active, this);
|
||||
if (pushed_rowid_filter && handler_rowid_filter_is_active(this))
|
||||
mi_set_rowid_filter_func(file, handler_rowid_filter_check, this);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -1982,10 +1981,9 @@ int ha_myisam::index_end()
|
||||
{
|
||||
DBUG_ENTER("ha_myisam::index_end");
|
||||
active_index= MAX_KEY;
|
||||
//pushed_idx_cond_keyno= MAX_KEY;
|
||||
mi_set_index_cond_func(file, NULL, 0);
|
||||
in_range_check_pushed_down= FALSE;
|
||||
mi_set_rowid_filter_func(file, NULL, NULL, 0);
|
||||
mi_set_rowid_filter_func(file, NULL, 0);
|
||||
ds_mrr.dsmrr_close();
|
||||
#if !defined(DBUG_OFF) && defined(SQL_SELECT_FIXED_FOR_UPDATE)
|
||||
file->update&= ~HA_STATE_AKTIV; // Forget active row
|
||||
@ -2021,9 +2019,8 @@ int ha_myisam::index_read_idx_map(uchar *buf, uint index, const uchar *key,
|
||||
end_range= NULL;
|
||||
if (index == pushed_idx_cond_keyno)
|
||||
mi_set_index_cond_func(file, handler_index_cond_check, this);
|
||||
if (pushed_rowid_filter)
|
||||
mi_set_rowid_filter_func(file, handler_rowid_filter_check,
|
||||
handler_rowid_filter_is_active, this);
|
||||
if (pushed_rowid_filter && handler_rowid_filter_is_active(this))
|
||||
mi_set_rowid_filter_func(file, handler_rowid_filter_check, this);
|
||||
res= mi_rkey(file, buf, index, key, keypart_map, find_flag);
|
||||
mi_set_index_cond_func(file, NULL, 0);
|
||||
return res;
|
||||
@ -2728,12 +2725,23 @@ Item *ha_myisam::idx_cond_push(uint keyno_arg, Item* idx_cond_arg)
|
||||
|
||||
bool ha_myisam::rowid_filter_push(Rowid_filter* rowid_filter)
|
||||
{
|
||||
/* This will be used in index_init() */
|
||||
pushed_rowid_filter= rowid_filter;
|
||||
mi_set_rowid_filter_func(file, handler_rowid_filter_check,
|
||||
handler_rowid_filter_is_active, this);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/* Enable / disable rowid filter depending if it's active or not */
|
||||
|
||||
void ha_myisam::rowid_filter_changed()
|
||||
{
|
||||
if (pushed_rowid_filter && handler_rowid_filter_is_active(this))
|
||||
mi_set_rowid_filter_func(file, handler_rowid_filter_check, this);
|
||||
else
|
||||
mi_set_rowid_filter_func(file, NULL, this);
|
||||
}
|
||||
|
||||
|
||||
struct st_mysql_storage_engine myisam_storage_engine=
|
||||
{ MYSQL_HANDLERTON_INTERFACE_VERSION };
|
||||
|
||||
|
@ -173,8 +173,9 @@ public:
|
||||
int multi_range_read_explain_info(uint mrr_mode, char *str, size_t size);
|
||||
|
||||
/* Index condition pushdown implementation */
|
||||
Item *idx_cond_push(uint keyno, Item* idx_cond);
|
||||
bool rowid_filter_push(Rowid_filter* rowid_filter);
|
||||
Item *idx_cond_push(uint keyno, Item* idx_cond) override;
|
||||
bool rowid_filter_push(Rowid_filter* rowid_filter) override;
|
||||
void rowid_filter_changed() override;
|
||||
|
||||
private:
|
||||
DsMrr_impl ds_mrr;
|
||||
|
@ -376,16 +376,16 @@ void mi_set_index_cond_func(MI_INFO *info, index_cond_func_t func,
|
||||
{
|
||||
info->index_cond_func= func;
|
||||
info->index_cond_func_arg= func_arg;
|
||||
info->has_cond_pushdown= (info->index_cond_func || info->rowid_filter_func);
|
||||
}
|
||||
|
||||
void mi_set_rowid_filter_func(MI_INFO *info,
|
||||
rowid_filter_func_t check_func,
|
||||
rowid_filter_is_active_func_t is_active_func,
|
||||
void *func_arg)
|
||||
{
|
||||
info->rowid_filter_func= check_func;
|
||||
info->rowid_filter_is_active_func= is_active_func;
|
||||
info->rowid_filter_func_arg= func_arg;
|
||||
info->has_cond_pushdown= (info->index_cond_func || info->rowid_filter_func);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -510,14 +510,6 @@ int mi_unpack_index_tuple(MI_INFO *info, uint keynr, uchar *record)
|
||||
}
|
||||
|
||||
|
||||
static int mi_check_rowid_filter_is_active(MI_INFO *info)
|
||||
{
|
||||
if (info->rowid_filter_is_active_func == NULL)
|
||||
return 0;
|
||||
return info->rowid_filter_is_active_func(info->rowid_filter_func_arg);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Check the current index tuple: Check ICP condition and/or Rowid Filter
|
||||
|
||||
@ -532,21 +524,23 @@ static int mi_check_rowid_filter_is_active(MI_INFO *info)
|
||||
Check result according to check_result_t definition
|
||||
*/
|
||||
|
||||
check_result_t mi_check_index_tuple(MI_INFO *info, uint keynr, uchar *record)
|
||||
check_result_t mi_check_index_tuple_real(MI_INFO *info, uint keynr, uchar *record)
|
||||
{
|
||||
int need_unpack= TRUE;
|
||||
check_result_t res= CHECK_POS;
|
||||
DBUG_ASSERT(info->index_cond_func || info->rowid_filter_func);
|
||||
|
||||
if (mi_unpack_index_tuple(info, keynr, record))
|
||||
return CHECK_ERROR;
|
||||
|
||||
if (info->index_cond_func)
|
||||
{
|
||||
if (mi_unpack_index_tuple(info, keynr, record))
|
||||
res= CHECK_ERROR;
|
||||
else if ((res= info->index_cond_func(info->index_cond_func_arg)) ==
|
||||
if ((res= info->index_cond_func(info->index_cond_func_arg)) ==
|
||||
CHECK_OUT_OF_RANGE)
|
||||
{
|
||||
/* We got beyond the end of scanned range */
|
||||
info->lastpos= HA_OFFSET_ERROR; /* No active record */
|
||||
my_errno= HA_ERR_END_OF_FILE;
|
||||
return res;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -555,17 +549,10 @@ check_result_t mi_check_index_tuple(MI_INFO *info, uint keynr, uchar *record)
|
||||
*/
|
||||
if (res != CHECK_POS)
|
||||
return res;
|
||||
|
||||
need_unpack= FALSE;
|
||||
}
|
||||
|
||||
/* Check the Rowid Filter, if present */
|
||||
if (mi_check_rowid_filter_is_active(info))
|
||||
{
|
||||
/* Unpack the index tuple if we haven't done it already */
|
||||
if (need_unpack && mi_unpack_index_tuple(info, keynr, record))
|
||||
res= CHECK_ERROR;
|
||||
else
|
||||
if (info->rowid_filter_func)
|
||||
{
|
||||
if ((res= info->rowid_filter_func(info->rowid_filter_func_arg)) ==
|
||||
CHECK_OUT_OF_RANGE)
|
||||
@ -575,7 +562,6 @@ check_result_t mi_check_index_tuple(MI_INFO *info, uint keynr, uchar *record)
|
||||
my_errno= HA_ERR_END_OF_FILE;
|
||||
}
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
|
@ -304,10 +304,10 @@ struct st_myisam_info
|
||||
/* If info->buff has to be reread for rnext */
|
||||
my_bool buff_used;
|
||||
my_bool create_unique_index_by_sort;
|
||||
my_bool has_cond_pushdown;
|
||||
index_cond_func_t index_cond_func; /* Index condition function */
|
||||
void *index_cond_func_arg; /* parameter for the func */
|
||||
rowid_filter_func_t rowid_filter_func; /* rowid filter check function */
|
||||
rowid_filter_is_active_func_t rowid_filter_is_active_func; /* is activefunction */
|
||||
void *rowid_filter_func_arg; /* parameter for the func */
|
||||
THR_LOCK_DATA lock;
|
||||
uchar *rtree_recursion_state; /* For RTREE */
|
||||
@ -742,7 +742,15 @@ my_bool mi_dynmap_file(MI_INFO *info, my_off_t size);
|
||||
int mi_munmap_file(MI_INFO *info);
|
||||
void mi_remap_file(MI_INFO *info, my_off_t size);
|
||||
|
||||
check_result_t mi_check_index_tuple(MI_INFO *info, uint keynr, uchar *record);
|
||||
check_result_t mi_check_index_tuple_real(MI_INFO *info, uint keynr,
|
||||
uchar *record);
|
||||
static inline check_result_t mi_check_index_tuple(MI_INFO *info, uint keynr,
|
||||
uchar *record)
|
||||
{
|
||||
if (!info->has_cond_pushdown && ! info->rowid_filter_func)
|
||||
return CHECK_POS;
|
||||
return mi_check_index_tuple_real(info, keynr, record);
|
||||
}
|
||||
|
||||
/* Functions needed by mi_check */
|
||||
int killed_ptr(HA_CHECK *param);
|
||||
@ -754,7 +762,6 @@ extern void mi_set_index_cond_func(MI_INFO *info, index_cond_func_t check_func,
|
||||
void *func_arg);
|
||||
extern void mi_set_rowid_filter_func(MI_INFO *info,
|
||||
rowid_filter_func_t check_func,
|
||||
rowid_filter_is_active_func_t is_active_func,
|
||||
void *func_arg);
|
||||
int flush_blocks(HA_CHECK *param, KEY_CACHE *key_cache, File file,
|
||||
ulonglong *dirty_part_map);
|
||||
|
Reference in New Issue
Block a user