select * from information_schema.engines where engine = 'xengine'; ENGINE SUPPORT COMMENT TRANSACTIONS XA SAVEPOINTS XENGINE DEFAULT X-Engine storage engine YES YES YES drop table if exists t0,t1,t2,t3; create table t0 (a int) engine=myisam; insert into t0 values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9); create table t1(a int) engine=myisam; insert into t1 select A.a + B.a* 10 + C.a * 100 from t0 A, t0 B, t0 C; create table t2 ( pk int primary key, kp1 int, kp2 int, col1 int, key (kp1,kp2) comment 'cf1' ) engine=xengine; insert into t2 select a,a,a,a from t1; # Try a basic case: explain select * from t2 where kp1 between 1 and 10 and mod(kp2,2)=0; id select_type table partitions type possible_keys key key_len ref rows filtered Extra 1 SIMPLE t2 NULL range kp1 kp1 5 NULL # 100.00 Using index condition Warnings: Note 1003 /* select#1 */ select `test`.`t2`.`pk` AS `pk`,`test`.`t2`.`kp1` AS `kp1`,`test`.`t2`.`kp2` AS `kp2`,`test`.`t2`.`col1` AS `col1` from `test`.`t2` where ((`test`.`t2`.`kp1` between 1 and 10) and ((`test`.`t2`.`kp2` % 2) = 0)) select * from t2 where kp1 between 1 and 10 and mod(kp2,2)=0; pk kp1 kp2 col1 2 2 2 2 4 4 4 4 6 6 6 6 8 8 8 8 10 10 10 10 # Check that ICP doesnt work for columns where column value # cant be restored from mem-comparable form: create table t3 ( pk int primary key, kp1 int, kp2 varchar(10) collate utf8_general_ci, col1 int, key (kp1,kp2) comment 'cf1' ) engine=xengine; Warnings: Warning 3778 'utf8_general_ci' is a collation of the deprecated character set UTF8MB3. Please consider using UTF8MB4 with an appropriate collation instead. # This must not use ICP: explain select * from t3 where kp1=3 and kp2 like '%foo%'; id select_type table partitions type possible_keys key key_len ref rows filtered Extra 1 SIMPLE t3 NULL ref kp1 kp1 5 const # 100.00 Using index condition Warnings: Note 1003 /* select#1 */ select `test`.`t3`.`pk` AS `pk`,`test`.`t3`.`kp1` AS `kp1`,`test`.`t3`.`kp2` AS `kp2`,`test`.`t3`.`col1` AS `col1` from `test`.`t3` where ((`test`.`t3`.`kp1` = 3) and (`test`.`t3`.`kp2` like '%foo%')) select * from t3 where kp1=3 and kp2 like '%foo%'; pk kp1 kp2 col1 explain format=json select * from t3 where kp1 between 2 and 4 and mod(kp1,3)=0 and kp2 like '%foo%'; EXPLAIN { "query_block": { "select_id": 1, "cost_info": { "query_cost": "0.71" }, "table": { "table_name": "t3", "access_type": "range", "possible_keys": [ "kp1" ], "key": "kp1", "used_key_parts": [ "kp1" ], "key_length": "5", "rows_examined_per_scan": 1, "rows_produced_per_join": 1, "filtered": "100.00", "index_condition": "((`test`.`t3`.`kp1` between 2 and 4) and ((`test`.`t3`.`kp1` % 3) = 0) and (`test`.`t3`.`kp2` like '%foo%'))", "cost_info": { "read_cost": "0.61", "eval_cost": "0.10", "prefix_cost": "0.71", "data_read_per_join": "48" }, "used_columns": [ "pk", "kp1", "kp2", "col1" ] } } } Warnings: Note 1003 /* select#1 */ select `test`.`t3`.`pk` AS `pk`,`test`.`t3`.`kp1` AS `kp1`,`test`.`t3`.`kp2` AS `kp2`,`test`.`t3`.`col1` AS `col1` from `test`.`t3` where ((`test`.`t3`.`kp1` between 2 and 4) and ((`test`.`t3`.`kp1` % 3) = 0) and (`test`.`t3`.`kp2` like '%foo%')) # Check that we handle the case where out-of-range is encountered sooner # than matched index condition explain select * from t2 where kp1< 3 and kp2+1>50000; id select_type table partitions type possible_keys key key_len ref rows filtered Extra 1 SIMPLE t2 NULL range kp1 kp1 5 NULL # 100.00 Using index condition Warnings: Note 1003 /* select#1 */ select `test`.`t2`.`pk` AS `pk`,`test`.`t2`.`kp1` AS `kp1`,`test`.`t2`.`kp2` AS `kp2`,`test`.`t2`.`col1` AS `col1` from `test`.`t2` where ((`test`.`t2`.`kp1` < 3) and ((`test`.`t2`.`kp2` + 1) > 50000)) select * from t2 where kp1< 3 and kp2+1>50000; pk kp1 kp2 col1 explain select * from t2 where kp1< 3 and kp2+1>50000; id select_type table partitions type possible_keys key key_len ref rows filtered Extra 1 SIMPLE t2 NULL range kp1 kp1 5 NULL # 100.00 Using index condition Warnings: Note 1003 /* select#1 */ select `test`.`t2`.`pk` AS `pk`,`test`.`t2`.`kp1` AS `kp1`,`test`.`t2`.`kp2` AS `kp2`,`test`.`t2`.`col1` AS `col1` from `test`.`t2` where ((`test`.`t2`.`kp1` < 3) and ((`test`.`t2`.`kp2` + 1) > 50000)) select * from t2 where kp1< 3 and kp2+1>50000; pk kp1 kp2 col1 # Try doing backwards scans explain select * from t2 where kp1 between 1 and 10 and mod(kp2,2)=0 order by kp1 desc; id select_type table partitions type possible_keys key key_len ref rows filtered Extra 1 SIMPLE t2 NULL range kp1 kp1 5 NULL # 100.00 Using index condition; Backward index scan Warnings: Note 1003 /* select#1 */ select `test`.`t2`.`pk` AS `pk`,`test`.`t2`.`kp1` AS `kp1`,`test`.`t2`.`kp2` AS `kp2`,`test`.`t2`.`col1` AS `col1` from `test`.`t2` where ((`test`.`t2`.`kp1` between 1 and 10) and ((`test`.`t2`.`kp2` % 2) = 0)) order by `test`.`t2`.`kp1` desc select * from t2 where kp1 between 1 and 10 and mod(kp2,2)=0 order by kp1 desc; pk kp1 kp2 col1 10 10 10 10 8 8 8 8 6 6 6 6 4 4 4 4 2 2 2 2 explain select * from t2 where kp1 >990 and mod(kp2,2)=0 order by kp1 desc; id select_type table partitions type possible_keys key key_len ref rows filtered Extra 1 SIMPLE t2 NULL range kp1 kp1 5 NULL # 100.00 Using index condition; Backward index scan Warnings: Note 1003 /* select#1 */ select `test`.`t2`.`pk` AS `pk`,`test`.`t2`.`kp1` AS `kp1`,`test`.`t2`.`kp2` AS `kp2`,`test`.`t2`.`col1` AS `col1` from `test`.`t2` where ((`test`.`t2`.`kp1` > 990) and ((`test`.`t2`.`kp2` % 2) = 0)) order by `test`.`t2`.`kp1` desc select * from t2 where kp1 >990 and mod(kp2,2)=0 order by kp1 desc; pk kp1 kp2 col1 998 998 998 998 996 996 996 996 994 994 994 994 992 992 992 992 explain select * from t2 where kp1< 3 and kp2+1>50000 order by kp1 desc; id select_type table partitions type possible_keys key key_len ref rows filtered Extra 1 SIMPLE t2 NULL range kp1 kp1 5 NULL # 100.00 Using index condition; Backward index scan Warnings: Note 1003 /* select#1 */ select `test`.`t2`.`pk` AS `pk`,`test`.`t2`.`kp1` AS `kp1`,`test`.`t2`.`kp2` AS `kp2`,`test`.`t2`.`col1` AS `col1` from `test`.`t2` where ((`test`.`t2`.`kp1` < 3) and ((`test`.`t2`.`kp2` + 1) > 50000)) order by `test`.`t2`.`kp1` desc select * from t2 where kp1< 3 and kp2+1>50000 order by kp1 desc; pk kp1 kp2 col1 drop table t0,t1,t2,t3; # # Check how ICP affects counters # # First, some preparations # create table t4 ( id int, id1 int, id2 int, value int, value2 varchar(100), primary key (id), key id1_id2 (id1, id2) comment 'cf1' ) engine=xengine charset=latin1 collate latin1_bin; insert into t4 values (1,1,1,1,1), (2,1,2,2,2), (3,1,3,3,3),(4,1,4,4,4),(5,1,5,5,5), (6,1,6,6,6), (7,1,7,7,7), (8,1,8,8,8),(9,1,9,9,9),(10,1,10,10,10); # # Now, the test itself # # ============== index-only query ============== explain select id1,id2 from t4 force index (id1_id2) where id1=1 and id2 % 10 = 1; id select_type table partitions type possible_keys key key_len ref rows filtered Extra 1 SIMPLE t4 NULL ref id1_id2 id1_id2 5 const # 100.00 Using where; Using index Warnings: Note 1003 /* select#1 */ select `test`.`t4`.`id1` AS `id1`,`test`.`t4`.`id2` AS `id2` from `test`.`t4` FORCE INDEX (`id1_id2`) where ((`test`.`t4`.`id1` = 1) and ((`test`.`t4`.`id2` % 10) = 1)) select id1,id2 from t4 force index (id1_id2) where id1=1 and id2 % 10 = 1; id1 id2 1 1 # ============== Query without ICP ============== set optimizer_switch='index_condition_pushdown=off'; explain select * from t4 force index (id1_id2) where id1=1 and id2 % 10 = 1; id select_type table partitions type possible_keys key key_len ref rows filtered Extra 1 SIMPLE t4 NULL ref id1_id2 id1_id2 5 const # 100.00 Using where Warnings: Note 1003 /* select#1 */ select `test`.`t4`.`id` AS `id`,`test`.`t4`.`id1` AS `id1`,`test`.`t4`.`id2` AS `id2`,`test`.`t4`.`value` AS `value`,`test`.`t4`.`value2` AS `value2` from `test`.`t4` FORCE INDEX (`id1_id2`) where ((`test`.`t4`.`id1` = 1) and ((`test`.`t4`.`id2` % 10) = 1)) select * from t4 force index (id1_id2) where id1=1 and id2 % 10 = 1; id id1 id2 value value2 1 1 1 1 1 # ============== Query with ICP ============== set optimizer_switch='index_condition_pushdown=on'; explain select * from t4 force index (id1_id2) where id1=1 and id2 % 10 = 1; id select_type table partitions type possible_keys key key_len ref rows filtered Extra 1 SIMPLE t4 NULL ref id1_id2 id1_id2 5 const # 100.00 Using index condition Warnings: Note 1003 /* select#1 */ select `test`.`t4`.`id` AS `id`,`test`.`t4`.`id1` AS `id1`,`test`.`t4`.`id2` AS `id2`,`test`.`t4`.`value` AS `value`,`test`.`t4`.`value2` AS `value2` from `test`.`t4` FORCE INDEX (`id1_id2`) where ((`test`.`t4`.`id1` = 1) and ((`test`.`t4`.`id2` % 10) = 1)) select * from t4 force index (id1_id2) where id1=1 and id2 % 10 = 1; id id1 id2 value value2 1 1 1 1 1 drop table t4; # # Issue #67: Inefficient index condition pushdown # create table t0 (a int); insert into t0 values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9); create table t1 ( pk int not null primary key, key1 bigint(20) unsigned, col1 int, key (key1) ) engine=xengine; Warnings: Warning 1681 Integer display width is deprecated and will be removed in a future release. insert into t1 select A.a+10*B.a+100*C.a, A.a+10*B.a+100*C.a, 1234 from t0 A, t0 B, t0 C; set @count=0; explain select * from t1 where key1=1; id select_type table partitions type possible_keys key key_len ref rows filtered Extra 1 SIMPLE t1 NULL ref key1 key1 9 const # 100.00 NULL Warnings: Note 1003 /* select#1 */ select `test`.`t1`.`pk` AS `pk`,`test`.`t1`.`key1` AS `key1`,`test`.`t1`.`col1` AS `col1` from `test`.`t1` where (`test`.`t1`.`key1` = 1) set @count_diff =(select (value - @count) from information_schema.xengine_perf_context where table_schema=database() and table_name='t1' and stat_type='INTERNAL_KEY_SKIPPED_COUNT'); select * from t1 where key1=1; pk key1 col1 1 1 1234 set @count_diff =(select (value - @count) from information_schema.xengine_perf_context where table_schema=database() and table_name='t1' and stat_type='INTERNAL_KEY_SKIPPED_COUNT'); # The following must be =1, or in any case not 999: select @count_diff as "INTERNAL_KEY_SKIPPED_COUNT increment"; INTERNAL_KEY_SKIPPED_COUNT increment NULL drop table t0,t1;